diff --git a/src/common/dom/handle-click.ts b/src/common/dom/handle-click.ts new file mode 100644 index 0000000000..99bd776524 --- /dev/null +++ b/src/common/dom/handle-click.ts @@ -0,0 +1,44 @@ +import { HomeAssistant } from "../../types"; +import { LovelaceElementConfig } from "../../panels/lovelace/elements/types"; +import { fireEvent } from "../dom/fire_event.js"; +import { navigate } from "../../common/navigate"; +import toggleEntity from "../../../src/panels/lovelace/common/entity/toggle-entity"; + +export const handleClick = ( + node: HTMLElement, + hass: HomeAssistant, + config: LovelaceElementConfig, + hold: boolean +): void => { + let action = config.tap_action || "more-info"; + + if (hold && config.hold_action) { + action = config.hold_action; + } + + if (action === "none") { + return; + } + + switch (action) { + case "more-info": + fireEvent(node, "hass-more-info", { entityId: config.entity }); + break; + case "navigate": + navigate(node, config.navigation_path ? config.navigation_path : ""); + break; + case "toggle": + toggleEntity(hass, config.entity); + break; + case "call-service": { + if (config.service) { + const [domain, service] = config.service.split(".", 2); + const serviceData = { + entity_id: config.entity, + ...config.service_data, + }; + hass.callService(domain, service, serviceData); + } + } + } +}; diff --git a/src/common/string/compute-tooltip.ts b/src/common/string/compute-tooltip.ts new file mode 100644 index 0000000000..4346e97234 --- /dev/null +++ b/src/common/string/compute-tooltip.ts @@ -0,0 +1,38 @@ +import computeStateName from "../../common/entity/compute_state_name"; +import { HomeAssistant } from "../../types"; +import { LovelaceElementConfig } from "../../panels/lovelace/elements/types"; + +export const computeTooltip = ( + hass: HomeAssistant, + config: LovelaceElementConfig +): string => { + if (config.title) { + return config.title; + } + + let stateName = ""; + let tooltip: string; + + if (config.entity) { + stateName = + config.entity in hass.states + ? computeStateName(hass.states[config.entity]) + : config.entity; + } + + switch (config.tap_action) { + case "navigate": + tooltip = `Navigate to ${config.navigation_path}`; + break; + case "toggle": + tooltip = `Toggle ${stateName}`; + break; + case "call-service": + tooltip = `Call service ${config.service}`; + break; + default: + tooltip = `Show more-info: ${stateName}`; + } + + return tooltip; +}; diff --git a/src/panels/lovelace/common/create-hui-element.js b/src/panels/lovelace/common/create-hui-element.js index e74985ca13..8394c12115 100644 --- a/src/panels/lovelace/common/create-hui-element.js +++ b/src/panels/lovelace/common/create-hui-element.js @@ -1,4 +1,4 @@ -import "../elements/hui-icon-element.js"; +import "../elements/hui-icon-element"; import "../elements/hui-image-element.js"; import "../elements/hui-service-button-element.js"; import "../elements/hui-state-badge-element.js"; diff --git a/src/panels/lovelace/elements/hui-icon-element.js b/src/panels/lovelace/elements/hui-icon-element.js deleted file mode 100644 index 5eb2bb2631..0000000000 --- a/src/panels/lovelace/elements/hui-icon-element.js +++ /dev/null @@ -1,53 +0,0 @@ -import { html } from "@polymer/polymer/lib/utils/html-tag.js"; -import { PolymerElement } from "@polymer/polymer/polymer-element.js"; - -import "../../../components/ha-icon.js"; - -import ElementClickMixin from "../mixins/element-click-mixin.js"; -import { longPressBind } from "../common/directives/long-press-directive"; - -/* - * @appliesMixin ElementClickMixin - */ -class HuiIconElement extends ElementClickMixin(PolymerElement) { - static get template() { - return html` - - - `; - } - - static get properties() { - return { - hass: Object, - _config: Object, - }; - } - - ready() { - super.ready(); - longPressBind(this); - this.addEventListener("ha-click", () => - this.handleClick(this.hass, this._config, false) - ); - this.addEventListener("ha-hold", () => - this.handleClick(this.hass, this._config, true) - ); - } - - setConfig(config) { - if (!config || !config.icon) { - throw Error("Error in element configuration"); - } - - this._config = config; - } -} -customElements.define("hui-icon-element", HuiIconElement); diff --git a/src/panels/lovelace/elements/hui-icon-element.ts b/src/panels/lovelace/elements/hui-icon-element.ts new file mode 100644 index 0000000000..00c291a0c2 --- /dev/null +++ b/src/panels/lovelace/elements/hui-icon-element.ts @@ -0,0 +1,68 @@ +import { html, LitElement } from "@polymer/lit-element"; + +import "../../../components/ha-icon.js"; + +import { computeTooltip } from "../../../common/string/compute-tooltip"; +import { handleClick } from "../../../common/dom/handle-click"; +import { longPress } from "../common/directives/long-press-directive"; +import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin"; +import { LovelaceElement, LovelaceElementConfig } from "./types.js"; +import { HomeAssistant } from "../../../types.js"; +import { TemplateResult } from "lit-html"; + +interface Config extends LovelaceElementConfig { + icon: string; +} + +export class HuiIconElement extends hassLocalizeLitMixin(LitElement) + implements LovelaceElement { + public hass?: HomeAssistant; + private _config?: Config; + + static get properties() { + return { hass: {}, _config: {} }; + } + + public setConfig(config: Config): void { + if (!config.icon) { + throw Error("Invalid Configuration: 'icon' required"); + } + + this._config = config; + } + + protected render(): TemplateResult { + if (!this._config) { + return html``; + } + + return html` + ${this.renderStyle()} + + `; + } + + private renderStyle(): TemplateResult { + return html` + + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-icon-element": HuiIconElement; + } +} + +customElements.define("hui-icon-element", HuiIconElement); diff --git a/src/panels/lovelace/elements/types.ts b/src/panels/lovelace/elements/types.ts index 7b8b2c59cd..105ac3d2d9 100644 --- a/src/panels/lovelace/elements/types.ts +++ b/src/panels/lovelace/elements/types.ts @@ -2,8 +2,14 @@ import { HomeAssistant } from "../../../types"; export interface LovelaceElementConfig { type: string; - entity?: string; style: object; + entity?: string; + hold_action?: string; + navigation_path?: string; + service?: string; + service_data?: object; + tap_action?: string; + title?: string; } export interface LovelaceElement extends HTMLElement {