From 7ffe5b531df04ab5cb4603ed1f2ef26a9c31fcd5 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 24 May 2022 09:42:59 +0200 Subject: [PATCH] feat(slider): add animation and step support to slider (#521) * feat(slider): add animation and step support to slider * feat(slider): add animation of slider indicator --- .../controls/fan-percentage-control.ts | 3 +- src/cards/fan-card/fan-card.ts | 2 +- src/cards/fan-card/utils.ts | 7 ++++ src/shared/slider.ts | 32 ++++++++++++++++--- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/cards/fan-card/controls/fan-percentage-control.ts b/src/cards/fan-card/controls/fan-percentage-control.ts index 22736002b..cb9dea292 100644 --- a/src/cards/fan-card/controls/fan-percentage-control.ts +++ b/src/cards/fan-card/controls/fan-percentage-control.ts @@ -4,7 +4,7 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators.js"; import { isActive, isAvailable } from "../../../ha/data/entity"; import "../../../shared/slider"; -import { getPercentage } from "../utils"; +import { computePercentageStep, getPercentage } from "../utils"; @customElement("mushroom-fan-percentage-control") export class FanPercentageControl extends LitElement { @@ -42,6 +42,7 @@ export class FanPercentageControl extends LitElement { .showActive=${true} @change=${this.onChange} @current-change=${this.onCurrentChange} + step=${computePercentageStep(this.entity)} /> `; } diff --git a/src/cards/fan-card/fan-card.ts b/src/cards/fan-card/fan-card.ts index 623996173..4ce34960b 100644 --- a/src/cards/fan-card/fan-card.ts +++ b/src/cards/fan-card/fan-card.ts @@ -95,7 +95,7 @@ export class FanCard extends MushroomBaseElement implements LovelaceCard { private onCurrentPercentageChange(e: CustomEvent<{ value?: number }>): void { if (e.detail.value != null) { - this.percentage = e.detail.value; + this.percentage = Math.round(e.detail.value); } } diff --git a/src/cards/fan-card/utils.ts b/src/cards/fan-card/utils.ts index 902164f77..227b2262d 100644 --- a/src/cards/fan-card/utils.ts +++ b/src/cards/fan-card/utils.ts @@ -9,3 +9,10 @@ export function getPercentage(entity: HassEntity) { export function isOscillating(entity: HassEntity) { return entity.attributes.oscillating != null ? Boolean(entity.attributes.oscillating) : false; } + +export function computePercentageStep(entity: HassEntity) { + if (entity.attributes.percentage_step) { + return entity.attributes.percentage_step; + } + return 1; +} diff --git a/src/shared/slider.ts b/src/shared/slider.ts index 4cd7ef0c3..6e48b58bd 100644 --- a/src/shared/slider.ts +++ b/src/shared/slider.ts @@ -1,5 +1,5 @@ import { css, CSSResultGroup, html, LitElement, PropertyValues, TemplateResult } from "lit"; -import { customElement, property, query } from "lit/decorators.js"; +import { customElement, property, query, state } from "lit/decorators.js"; import { classMap } from "lit/directives/class-map.js"; import { styleMap } from "lit/directives/style-map.js"; import "hammerjs"; @@ -33,6 +33,9 @@ export class SliderItem extends LitElement { @property({ attribute: false, type: Number, reflect: true }) public value?: number; + @property({ type: Number }) + public step: number = 1; + @property({ type: Number }) public min: number = 0; @@ -41,6 +44,8 @@ export class SliderItem extends LitElement { private _mc?: HammerManager; + @state() controlled: boolean = false; + valueToPercentage(value: number) { return (value - this.min) / (this.max - this.min); } @@ -84,10 +89,12 @@ export class SliderItem extends LitElement { let savedValue; this._mc.on("panstart", () => { if (this.disabled) return; + this.controlled = true; savedValue = this.value; }); this._mc.on("pancancel", () => { if (this.disabled) return; + this.controlled = false; this.value = savedValue; }); this._mc.on("panmove", (e) => { @@ -97,13 +104,14 @@ export class SliderItem extends LitElement { this.dispatchEvent( new CustomEvent("current-change", { detail: { - value: Math.round(this.value), + value: Math.round(this.value / this.step) * this.step, }, }) ); }); this._mc.on("panend", (e) => { if (this.disabled) return; + this.controlled = false; const percentage = getPercentageFromEvent(e); this.value = this.percentageToValue(percentage); this.dispatchEvent( @@ -116,7 +124,7 @@ export class SliderItem extends LitElement { this.dispatchEvent( new CustomEvent("change", { detail: { - value: Math.round(this.value), + value: Math.round(this.value / this.step) * this.step, }, }) ); @@ -129,7 +137,7 @@ export class SliderItem extends LitElement { this.dispatchEvent( new CustomEvent("change", { detail: { - value: Math.round(this.value), + value: Math.round(this.value / this.step) * this.step, }, }) ); @@ -146,7 +154,13 @@ export class SliderItem extends LitElement { protected render(): TemplateResult { return html` -
+