mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 11:16:35 +00:00
Add slider bar (#14094)
* Add slider bar * a11y feedbacks * allow undefined values * rename variable * Add end style * Add vertical slider * Allow theming * Improve theming * Improve colors * fix properties * stepped value for aria value * use vertical instead of orientation * Improve a11y * force role slider
This commit is contained in:
parent
928f20ada5
commit
55467666f7
3
gallery/src/pages/components/ha-bar-slider.markdown
Normal file
3
gallery/src/pages/components/ha-bar-slider.markdown
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
title: Bar Sliders
|
||||||
|
---
|
169
gallery/src/pages/components/ha-bar-slider.ts
Normal file
169
gallery/src/pages/components/ha-bar-slider.ts
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import { css, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { ifDefined } from "lit/directives/if-defined";
|
||||||
|
import { repeat } from "lit/directives/repeat";
|
||||||
|
import "../../../../src/components/ha-bar-slider";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
|
||||||
|
const sliders: {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
mode?: "start" | "end" | "indicator";
|
||||||
|
class?: string;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
id: "slider-start",
|
||||||
|
label: "Slider (start mode)",
|
||||||
|
mode: "start",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "slider-end",
|
||||||
|
label: "Slider (end mode)",
|
||||||
|
mode: "end",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "slider-indicator",
|
||||||
|
label: "Slider (indicator mode)",
|
||||||
|
mode: "indicator",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "slider-start-custom",
|
||||||
|
label: "Slider (start mode) and custom style",
|
||||||
|
mode: "start",
|
||||||
|
class: "custom",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "slider-end-custom",
|
||||||
|
label: "Slider (end mode) and custom style",
|
||||||
|
mode: "end",
|
||||||
|
class: "custom",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "slider-indicator-custom",
|
||||||
|
label: "Slider (indicator mode) and custom style",
|
||||||
|
mode: "indicator",
|
||||||
|
class: "custom",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@customElement("demo-components-ha-bar-slider")
|
||||||
|
export class DemoHaBarSlider extends LitElement {
|
||||||
|
@state() private value = 50;
|
||||||
|
|
||||||
|
@state() private sliderPosition?: number;
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.value = e.detail.value as number;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSliderMoved(e: CustomEvent) {
|
||||||
|
this.sliderPosition = e.detail.value as number;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<p><b>Slider values</b></p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>position</td>
|
||||||
|
<td>${this.sliderPosition ?? "-"}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>value</td>
|
||||||
|
<td>${this.value ?? "-"}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
${repeat(sliders, (slider) => {
|
||||||
|
const { id, label, ...config } = slider;
|
||||||
|
return html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<label id=${id}>${label}</label>
|
||||||
|
<pre>Config: ${JSON.stringify(config)}</pre>
|
||||||
|
<ha-bar-slider
|
||||||
|
.value=${this.value}
|
||||||
|
.mode=${config.mode}
|
||||||
|
class=${ifDefined(config.class)}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
@slider-moved=${this.handleSliderMoved}
|
||||||
|
aria-labelledby=${id}
|
||||||
|
>
|
||||||
|
</ha-bar-slider>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
})}
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="title"><b>Vertical</b></p>
|
||||||
|
<div class="vertical-sliders">
|
||||||
|
${repeat(sliders, (slider) => {
|
||||||
|
const { id, label, ...config } = slider;
|
||||||
|
return html`
|
||||||
|
<ha-bar-slider
|
||||||
|
.value=${this.value}
|
||||||
|
.mode=${config.mode}
|
||||||
|
vertical
|
||||||
|
class=${ifDefined(config.class)}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
@slider-moved=${this.handleSliderMoved}
|
||||||
|
aria-label=${label}
|
||||||
|
>
|
||||||
|
</ha-bar-slider>
|
||||||
|
`;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-card {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 24px auto;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.custom {
|
||||||
|
--slider-bar-color: #ffcf4c;
|
||||||
|
--slider-bar-background: #ffcf4c64;
|
||||||
|
--slider-bar-thickness: 100px;
|
||||||
|
--slider-bar-border-radius: 24px;
|
||||||
|
}
|
||||||
|
.vertical-sliders {
|
||||||
|
height: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
p.title {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.vertical-sliders > *:not(:last-child) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-components-ha-bar-slider": DemoHaBarSlider;
|
||||||
|
}
|
||||||
|
}
|
@ -110,6 +110,7 @@
|
|||||||
"deep-freeze": "^0.0.1",
|
"deep-freeze": "^0.0.1",
|
||||||
"fuse.js": "^6.0.0",
|
"fuse.js": "^6.0.0",
|
||||||
"google-timezones-json": "^1.0.2",
|
"google-timezones-json": "^1.0.2",
|
||||||
|
"hammerjs": "^2.0.8",
|
||||||
"hls.js": "^1.2.3",
|
"hls.js": "^1.2.3",
|
||||||
"home-assistant-js-websocket": "^8.0.0",
|
"home-assistant-js-websocket": "^8.0.0",
|
||||||
"idb-keyval": "^5.1.3",
|
"idb-keyval": "^5.1.3",
|
||||||
@ -169,6 +170,7 @@
|
|||||||
"@types/chromecast-caf-receiver": "5.0.12",
|
"@types/chromecast-caf-receiver": "5.0.12",
|
||||||
"@types/chromecast-caf-sender": "^1.0.3",
|
"@types/chromecast-caf-sender": "^1.0.3",
|
||||||
"@types/glob": "^7",
|
"@types/glob": "^7",
|
||||||
|
"@types/hammerjs": "^2.0.41",
|
||||||
"@types/js-yaml": "^4",
|
"@types/js-yaml": "^4",
|
||||||
"@types/leaflet": "^1",
|
"@types/leaflet": "^1",
|
||||||
"@types/leaflet-draw": "^1",
|
"@types/leaflet-draw": "^1",
|
||||||
|
426
src/components/ha-bar-slider.ts
Normal file
426
src/components/ha-bar-slider.ts
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
import "hammerjs";
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResultGroup,
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
PropertyValues,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit";
|
||||||
|
import { customElement, property, query } from "lit/decorators";
|
||||||
|
import { classMap } from "lit/directives/class-map";
|
||||||
|
import { styleMap } from "lit/directives/style-map";
|
||||||
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"slider-moved": { value?: number };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const A11Y_KEY_CODES = new Set([
|
||||||
|
"ArrowRight",
|
||||||
|
"ArrowUp",
|
||||||
|
"ArrowLeft",
|
||||||
|
"ArrowDown",
|
||||||
|
"PageUp",
|
||||||
|
"PageDown",
|
||||||
|
"Home",
|
||||||
|
"End",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const getPercentageFromEvent = (e: HammerInput, vertical: boolean) => {
|
||||||
|
if (vertical) {
|
||||||
|
const y = e.center.y;
|
||||||
|
const offset = e.target.getBoundingClientRect().top;
|
||||||
|
const total = e.target.clientHeight;
|
||||||
|
return Math.max(Math.min(1, 1 - (y - offset) / total), 0);
|
||||||
|
}
|
||||||
|
const x = e.center.x;
|
||||||
|
const offset = e.target.getBoundingClientRect().left;
|
||||||
|
const total = e.target.clientWidth;
|
||||||
|
return Math.max(Math.min(1, (x - offset) / total), 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
@customElement("ha-bar-slider")
|
||||||
|
export class HaBarSlider extends LitElement {
|
||||||
|
@property({ type: Boolean })
|
||||||
|
public disabled = false;
|
||||||
|
|
||||||
|
@property()
|
||||||
|
public mode?: "start" | "end" | "indicator" = "start";
|
||||||
|
|
||||||
|
@property({ type: Boolean })
|
||||||
|
public vertical = false;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
public value?: number;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
public step = 1;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
public min = 0;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
public max = 100;
|
||||||
|
|
||||||
|
@property()
|
||||||
|
public label?: string;
|
||||||
|
|
||||||
|
private _mc?: HammerManager;
|
||||||
|
|
||||||
|
@property({ type: Boolean, reflect: true })
|
||||||
|
public pressed = false;
|
||||||
|
|
||||||
|
valueToPercentage(value: number) {
|
||||||
|
return (value - this.min) / (this.max - this.min);
|
||||||
|
}
|
||||||
|
|
||||||
|
percentageToValue(value: number) {
|
||||||
|
return (this.max - this.min) * value + this.min;
|
||||||
|
}
|
||||||
|
|
||||||
|
steppedValue(value: number) {
|
||||||
|
return Math.round(value / this.step) * this.step;
|
||||||
|
}
|
||||||
|
|
||||||
|
boundedValue(value: number) {
|
||||||
|
return Math.min(Math.max(value, this.min), this.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||||
|
super.firstUpdated(changedProperties);
|
||||||
|
this.setupListeners();
|
||||||
|
this.setAttribute("role", "slider");
|
||||||
|
if (!this.hasAttribute("tabindex")) {
|
||||||
|
this.setAttribute("tabindex", "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProps: PropertyValues) {
|
||||||
|
super.updated(changedProps);
|
||||||
|
if (changedProps.has("value")) {
|
||||||
|
const valuenow = this.steppedValue(this.value ?? 0);
|
||||||
|
this.setAttribute("aria-valuenow", valuenow.toString());
|
||||||
|
}
|
||||||
|
if (changedProps.has("min")) {
|
||||||
|
this.setAttribute("aria-valuemin", this.min.toString());
|
||||||
|
}
|
||||||
|
if (changedProps.has("max")) {
|
||||||
|
this.setAttribute("aria-valuemax", this.max.toString());
|
||||||
|
}
|
||||||
|
if (changedProps.has("vertical")) {
|
||||||
|
const orientation = this.vertical ? "vertical" : "horizontal";
|
||||||
|
this.setAttribute("aria-orientation", orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
this.setupListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback(): void {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
this.destroyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
@query("#slider")
|
||||||
|
private slider;
|
||||||
|
|
||||||
|
setupListeners() {
|
||||||
|
if (this.slider && !this._mc) {
|
||||||
|
this._mc = new Hammer.Manager(this.slider, {
|
||||||
|
touchAction: this.vertical ? "pan-x" : "pan-y",
|
||||||
|
});
|
||||||
|
this._mc.add(
|
||||||
|
new Hammer.Pan({
|
||||||
|
threshold: 10,
|
||||||
|
direction: Hammer.DIRECTION_ALL,
|
||||||
|
enable: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this._mc.add(new Hammer.Tap({ event: "singletap" }));
|
||||||
|
|
||||||
|
let savedValue;
|
||||||
|
this._mc.on("panstart", () => {
|
||||||
|
if (this.disabled) return;
|
||||||
|
this.pressed = true;
|
||||||
|
savedValue = this.value;
|
||||||
|
});
|
||||||
|
this._mc.on("pancancel", () => {
|
||||||
|
if (this.disabled) return;
|
||||||
|
this.pressed = false;
|
||||||
|
this.value = savedValue;
|
||||||
|
});
|
||||||
|
this._mc.on("panmove", (e) => {
|
||||||
|
if (this.disabled) return;
|
||||||
|
const percentage = getPercentageFromEvent(e, this.vertical);
|
||||||
|
this.value = this.percentageToValue(percentage);
|
||||||
|
const value = this.steppedValue(this.value);
|
||||||
|
fireEvent(this, "slider-moved", { value });
|
||||||
|
});
|
||||||
|
this._mc.on("panend", (e) => {
|
||||||
|
if (this.disabled) return;
|
||||||
|
this.pressed = false;
|
||||||
|
const percentage = getPercentageFromEvent(e, this.vertical);
|
||||||
|
this.value = this.steppedValue(this.percentageToValue(percentage));
|
||||||
|
fireEvent(this, "slider-moved", { value: undefined });
|
||||||
|
fireEvent(this, "value-changed", { value: this.value });
|
||||||
|
});
|
||||||
|
|
||||||
|
this._mc.on("singletap", (e) => {
|
||||||
|
if (this.disabled) return;
|
||||||
|
const percentage = getPercentageFromEvent(e, this.vertical);
|
||||||
|
this.value = this.steppedValue(this.percentageToValue(percentage));
|
||||||
|
fireEvent(this, "value-changed", { value: this.value });
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addEventListener("keydown", this._handleKeyDown);
|
||||||
|
this.addEventListener("keyup", this._handleKeyUp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyListeners() {
|
||||||
|
if (this._mc) {
|
||||||
|
this._mc.destroy();
|
||||||
|
this._mc = undefined;
|
||||||
|
}
|
||||||
|
this.removeEventListener("keydown", this._handleKeyDown);
|
||||||
|
this.removeEventListener("keyup", this._handleKeyDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _tenPercentStep() {
|
||||||
|
return Math.max(this.step, (this.max - this.min) / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleKeyDown(e: KeyboardEvent) {
|
||||||
|
if (!A11Y_KEY_CODES.has(e.code)) return;
|
||||||
|
e.preventDefault();
|
||||||
|
switch (e.code) {
|
||||||
|
case "ArrowRight":
|
||||||
|
case "ArrowUp":
|
||||||
|
this.value = this.boundedValue((this.value ?? 0) + this.step);
|
||||||
|
break;
|
||||||
|
case "ArrowLeft":
|
||||||
|
case "ArrowDown":
|
||||||
|
this.value = this.boundedValue((this.value ?? 0) - this.step);
|
||||||
|
break;
|
||||||
|
case "PageUp":
|
||||||
|
this.value = this.steppedValue(
|
||||||
|
this.boundedValue((this.value ?? 0) + this._tenPercentStep)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "PageDown":
|
||||||
|
this.value = this.steppedValue(
|
||||||
|
this.boundedValue((this.value ?? 0) - this._tenPercentStep)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "Home":
|
||||||
|
this.value = this.min;
|
||||||
|
break;
|
||||||
|
case "End":
|
||||||
|
this.value = this.max;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fireEvent(this, "slider-moved", { value: this.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleKeyUp(e: KeyboardEvent) {
|
||||||
|
if (!A11Y_KEY_CODES.has(e.code)) return;
|
||||||
|
e.preventDefault();
|
||||||
|
fireEvent(this, "value-changed", { value: this.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div
|
||||||
|
id="slider"
|
||||||
|
class="slider"
|
||||||
|
style=${styleMap({
|
||||||
|
"--value": `${this.valueToPercentage(this.value ?? 0)}`,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<div class="slider-track-background"></div>
|
||||||
|
${this.mode === "indicator"
|
||||||
|
? html`
|
||||||
|
<div
|
||||||
|
class=${classMap({
|
||||||
|
"slider-track-indicator": true,
|
||||||
|
vertical: this.vertical,
|
||||||
|
})}
|
||||||
|
></div>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<div
|
||||||
|
class=${classMap({
|
||||||
|
"slider-track-bar": true,
|
||||||
|
vertical: this.vertical,
|
||||||
|
[this.mode ?? "start"]: true,
|
||||||
|
})}
|
||||||
|
></div>
|
||||||
|
`}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
--slider-bar-color: rgb(var(--rgb-primary-color));
|
||||||
|
--slider-bar-background: rgba(var(--rgb-disabled-color), 0.2);
|
||||||
|
--slider-bar-thickness: 40px;
|
||||||
|
--slider-bar-border-radius: 12px;
|
||||||
|
height: var(--slider-bar-thickness);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
:host([vertical]) {
|
||||||
|
width: var(--slider-bar-thickness);
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.slider {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: var(--slider-bar-border-radius);
|
||||||
|
transform: translateZ(0);
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.slider * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.slider .slider-track-background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: var(--slider-bar-background);
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar {
|
||||||
|
--border-radius: calc(var(--slider-bar-border-radius) / 2);
|
||||||
|
--handle-size: 4px;
|
||||||
|
--handle-margin: calc(var(--slider-bar-thickness) / 8);
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--slider-bar-color);
|
||||||
|
transition: transform 180ms ease-in-out;
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar::after {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: var(--handle-size);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
transform: translate3d(calc((var(--value, 0) - 1) * 100%), 0, 0);
|
||||||
|
border-radius: 0 var(--border-radius) var(--border-radius) 0;
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar:after {
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: var(--handle-margin);
|
||||||
|
height: 50%;
|
||||||
|
width: var(--handle-size);
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar.end {
|
||||||
|
right: 0;
|
||||||
|
left: initial;
|
||||||
|
transform: translate3d(calc(var(--value, 0) * 100%), 0, 0);
|
||||||
|
border-radius: var(--border-radius) 0 0 var(--border-radius);
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar.end::after {
|
||||||
|
right: initial;
|
||||||
|
left: var(--handle-margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider .slider-track-bar.vertical {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
transform: translate3d(0, calc((1 - var(--value, 0)) * 100%), 0);
|
||||||
|
border-radius: var(--border-radius) var(--border-radius) 0 0;
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar.vertical:after {
|
||||||
|
top: var(--handle-margin);
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: initial;
|
||||||
|
width: 50%;
|
||||||
|
height: var(--handle-size);
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar.vertical.end {
|
||||||
|
top: 0;
|
||||||
|
bottom: initial;
|
||||||
|
transform: translate3d(0, calc((0 - var(--value, 0)) * 100%), 0);
|
||||||
|
border-radius: 0 0 var(--border-radius) var(--border-radius);
|
||||||
|
}
|
||||||
|
.slider .slider-track-bar.vertical.end::after {
|
||||||
|
top: initial;
|
||||||
|
bottom: var(--handle-margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider .slider-track-indicator:after {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
background-color: rgb(var(--rgb-secondary-text-color));
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: var(--handle-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider .slider-track-indicator {
|
||||||
|
--indicator-size: calc(var(--slider-bar-thickness) / 4);
|
||||||
|
--handle-size: 4px;
|
||||||
|
position: absolute;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: var(--handle-size);
|
||||||
|
transition: left 180ms ease-in-out, bottom 180ms ease-in-out;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: calc(var(--value, 0) * (100% - var(--indicator-size)));
|
||||||
|
width: var(--indicator-size);
|
||||||
|
}
|
||||||
|
.slider .slider-track-indicator:after {
|
||||||
|
height: 50%;
|
||||||
|
width: var(--handle-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider .slider-track-indicator.vertical {
|
||||||
|
top: initial;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: calc(var(--value, 0) * (100% - var(--indicator-size)));
|
||||||
|
height: var(--indicator-size);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.slider .slider-track-indicator.vertical:after {
|
||||||
|
height: var(--handle-size);
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([pressed]) .slider-track-bar,
|
||||||
|
:host([pressed]) .slider-track-indicator {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-bar-slider": HaBarSlider;
|
||||||
|
}
|
||||||
|
}
|
16
yarn.lock
16
yarn.lock
@ -3816,6 +3816,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/hammerjs@npm:^2.0.41":
|
||||||
|
version: 2.0.41
|
||||||
|
resolution: "@types/hammerjs@npm:2.0.41"
|
||||||
|
checksum: d16fbd688fc9b18cc270abe8dea8d4c50ef7bd8375e593d92c233d299387933a6b003c8db69819344833052458bc5f9ef1b472001277a49f095928d184356006
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/har-format@npm:*":
|
"@types/har-format@npm:*":
|
||||||
version: 1.2.4
|
version: 1.2.4
|
||||||
resolution: "@types/har-format@npm:1.2.4"
|
resolution: "@types/har-format@npm:1.2.4"
|
||||||
@ -8823,6 +8830,13 @@ fsevents@^1.2.7:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"hammerjs@npm:^2.0.8":
|
||||||
|
version: 2.0.8
|
||||||
|
resolution: "hammerjs@npm:2.0.8"
|
||||||
|
checksum: b092da7d1565a165d7edb53ef0ce212837a8b11f897aa3cf81a7818b66686b0ab3f4747fbce8fc8a41d1376594639ce3a054b0fd4889ca8b5b136a29ca500e27
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"handle-thing@npm:^2.0.0":
|
"handle-thing@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "handle-thing@npm:2.0.0"
|
resolution: "handle-thing@npm:2.0.0"
|
||||||
@ -9032,6 +9046,7 @@ fsevents@^1.2.7:
|
|||||||
"@types/chromecast-caf-receiver": 5.0.12
|
"@types/chromecast-caf-receiver": 5.0.12
|
||||||
"@types/chromecast-caf-sender": ^1.0.3
|
"@types/chromecast-caf-sender": ^1.0.3
|
||||||
"@types/glob": ^7
|
"@types/glob": ^7
|
||||||
|
"@types/hammerjs": ^2.0.41
|
||||||
"@types/js-yaml": ^4
|
"@types/js-yaml": ^4
|
||||||
"@types/leaflet": ^1
|
"@types/leaflet": ^1
|
||||||
"@types/leaflet-draw": ^1
|
"@types/leaflet-draw": ^1
|
||||||
@ -9085,6 +9100,7 @@ fsevents@^1.2.7:
|
|||||||
gulp-merge-json: ^1.3.1
|
gulp-merge-json: ^1.3.1
|
||||||
gulp-rename: ^2.0.0
|
gulp-rename: ^2.0.0
|
||||||
gulp-zopfli-green: ^3.0.1
|
gulp-zopfli-green: ^3.0.1
|
||||||
|
hammerjs: ^2.0.8
|
||||||
hls.js: ^1.2.3
|
hls.js: ^1.2.3
|
||||||
home-assistant-js-websocket: ^8.0.0
|
home-assistant-js-websocket: ^8.0.0
|
||||||
html-minifier: ^4.0.0
|
html-minifier: ^4.0.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user