diff --git a/src/components/ha-control-switch.ts b/src/components/ha-control-switch.ts index b2a05073ce..ae15ce98b7 100644 --- a/src/components/ha-control-switch.ts +++ b/src/components/ha-control-switch.ts @@ -1,3 +1,10 @@ +import { + DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL, + Manager, + Swipe, + Tap, +} from "@egjs/hammerjs"; import { css, CSSResultGroup, @@ -6,7 +13,7 @@ import { PropertyValues, TemplateResult, } from "lit"; -import { customElement, property } from "lit/decorators"; +import { customElement, property, query } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; import "./ha-svg-icon"; @@ -30,8 +37,11 @@ export class HaControlSwitch extends LitElement { // SVG icon path (if you need a non SVG icon instead, use the provided off icon slot to pass an in) @property({ type: String }) pathOff?: string; + private _mc?: HammerManager; + protected firstUpdated(changedProperties: PropertyValues): void { super.firstUpdated(changedProperties); + this.setupListeners(); this.setAttribute("role", "switch"); if (!this.hasAttribute("tabindex")) { this.setAttribute("tabindex", "0"); @@ -53,14 +63,70 @@ export class HaControlSwitch extends LitElement { connectedCallback(): void { super.connectedCallback(); - this.addEventListener("keydown", this._keydown); - this.addEventListener("click", this._toggle); + this.setupListeners(); } disconnectedCallback(): void { super.disconnectedCallback(); + this.destroyListeners(); + } + + @query("#switch") + private switch!: HTMLDivElement; + + setupListeners() { + if (this.switch && !this._mc) { + this._mc = new Manager(this.switch, { + touchAction: this.vertical ? "pan-x" : "pan-y", + }); + this._mc.add( + new Swipe({ + direction: this.vertical ? DIRECTION_VERTICAL : DIRECTION_HORIZONTAL, + }) + ); + + this._mc.add(new Tap({ event: "singletap" })); + + if (this.vertical) { + this._mc.on("swipeup", () => { + if (this.disabled) return; + this.checked = !!this.reversed; + fireEvent(this, "change"); + }); + + this._mc.on("swipedown", () => { + if (this.disabled) return; + this.checked = !this.reversed; + fireEvent(this, "change"); + }); + } else { + this._mc.on("swiperight", () => { + if (this.disabled) return; + this.checked = !this.reversed; + fireEvent(this, "change"); + }); + + this._mc.on("swipeleft", () => { + if (this.disabled) return; + this.checked = !!this.reversed; + fireEvent(this, "change"); + }); + } + + this._mc.on("singletap", () => { + if (this.disabled) return; + this._toggle(); + }); + this.addEventListener("keydown", this._keydown); + } + } + + destroyListeners() { + if (this._mc) { + this._mc.destroy(); + this._mc = undefined; + } this.removeEventListener("keydown", this._keydown); - this.removeEventListener("click", this._toggle); } private _keydown(ev: any) { @@ -73,7 +139,7 @@ export class HaControlSwitch extends LitElement { protected render(): TemplateResult { return html` -
+