From f23258eb8c9fb0f416069ad0402083b72016b413 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 9 Feb 2019 11:55:46 -0800 Subject: [PATCH] Convert state badge to TypeScript (#2712) --- src/components/entity/state-badge.js | 110 ----------------------- src/components/entity/state-badge.ts | 127 +++++++++++++++++++++++++++ src/components/ha-icon.js | 18 ---- src/components/ha-icon.ts | 36 ++++++++ 4 files changed, 163 insertions(+), 128 deletions(-) delete mode 100644 src/components/entity/state-badge.js create mode 100644 src/components/entity/state-badge.ts delete mode 100644 src/components/ha-icon.js create mode 100644 src/components/ha-icon.ts diff --git a/src/components/entity/state-badge.js b/src/components/entity/state-badge.js deleted file mode 100644 index ab3e0906ab..0000000000 --- a/src/components/entity/state-badge.js +++ /dev/null @@ -1,110 +0,0 @@ -import { html } from "@polymer/polymer/lib/utils/html-tag"; -import { PolymerElement } from "@polymer/polymer/polymer-element"; - -import "../ha-icon"; -import computeStateDomain from "../../common/entity/compute_state_domain"; -import stateIcon from "../../common/entity/state_icon"; - -class StateBadge extends PolymerElement { - static get template() { - return html` - - - - `; - } - - static get properties() { - return { - stateObj: { - type: Object, - observer: "_updateIconAppearance", - }, - overrideIcon: String, - }; - } - - _computeDomain(stateObj) { - return computeStateDomain(stateObj); - } - - _computeIcon(stateObj, overrideIcon) { - return overrideIcon || stateIcon(stateObj); - } - - _updateIconAppearance(newVal) { - var errorMessage = null; - const iconStyle = { - color: "", - filter: "", - }; - const hostStyle = { - backgroundImage: "", - }; - // hide icon if we have entity picture - if (newVal.attributes.entity_picture) { - hostStyle.backgroundImage = - "url(" + newVal.attributes.entity_picture + ")"; - iconStyle.display = "none"; - } else { - if (newVal.attributes.hs_color) { - const hue = newVal.attributes.hs_color[0]; - const sat = newVal.attributes.hs_color[1]; - if (sat > 10) iconStyle.color = `hsl(${hue}, 100%, ${100 - sat / 2}%)`; - } - if (newVal.attributes.brightness) { - const brightness = newVal.attributes.brightness; - if (typeof brightness !== "number") { - errorMessage = `Type error: state-badge expected number, but type of ${ - newVal.entity_id - }.attributes.brightness is ${typeof brightness} (${brightness})`; - // eslint-disable-next-line - console.warn(errorMessage); - } - // lowest brighntess will be around 50% (that's pretty dark) - iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`; - } - } - Object.assign(this.$.icon.style, iconStyle); - Object.assign(this.style, hostStyle); - if (errorMessage) { - throw new Error(`Frontend error: ${errorMessage}`); - } - } -} -customElements.define("state-badge", StateBadge); diff --git a/src/components/entity/state-badge.ts b/src/components/entity/state-badge.ts new file mode 100644 index 0000000000..4554c382fb --- /dev/null +++ b/src/components/entity/state-badge.ts @@ -0,0 +1,127 @@ +import { + LitElement, + TemplateResult, + css, + CSSResult, + html, + property, + PropertyValues, + query, +} from "lit-element"; +import "../ha-icon"; +import computeStateDomain from "../../common/entity/compute_state_domain"; +import stateIcon from "../../common/entity/state_icon"; +import { HassEntity } from "home-assistant-js-websocket"; +// Not duplicate, this is for typing. +// tslint:disable-next-line +import { HaIcon } from "../ha-icon"; + +class StateBadge extends LitElement { + @property() public stateObj?: HassEntity; + @property() public overrideIcon?: string; + @query("ha-icon") private _icon!: HaIcon; + + protected render(): TemplateResult | void { + const stateObj = this.stateObj; + + if (!stateObj) { + return html``; + } + + return html` + + `; + } + + protected updated(changedProps: PropertyValues) { + if (!changedProps.has("stateObj")) { + return; + } + const stateObj = this.stateObj; + + const iconStyle: Partial = { + color: "", + filter: "", + }; + const hostStyle: Partial = { + backgroundImage: "", + }; + if (stateObj) { + // hide icon if we have entity picture + if (stateObj.attributes.entity_picture) { + hostStyle.backgroundImage = + "url(" + stateObj.attributes.entity_picture + ")"; + iconStyle.display = "none"; + } else { + if (stateObj.attributes.hs_color) { + const hue = stateObj.attributes.hs_color[0]; + const sat = stateObj.attributes.hs_color[1]; + if (sat > 10) { + iconStyle.color = `hsl(${hue}, 100%, ${100 - sat / 2}%)`; + } + } + if (stateObj.attributes.brightness) { + const brightness = stateObj.attributes.brightness; + if (typeof brightness !== "number") { + const errorMessage = `Type error: state-badge expected number, but type of ${ + stateObj.entity_id + }.attributes.brightness is ${typeof brightness} (${brightness})`; + // tslint:disable-next-line + console.warn(errorMessage); + } + // lowest brighntess will be around 50% (that's pretty dark) + iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`; + } + } + } + Object.assign(this._icon.style, iconStyle); + Object.assign(this.style, hostStyle); + } + + static get styles(): CSSResult { + return css` + :host { + position: relative; + display: inline-block; + width: 40px; + color: var(--paper-item-icon-color, #44739e); + border-radius: 50%; + height: 40px; + text-align: center; + background-size: cover; + line-height: 40px; + } + + ha-icon { + transition: color 0.3s ease-in-out, filter 0.3s ease-in-out; + } + + /* Color the icon if light or sun is on */ + ha-icon[data-domain="light"][data-state="on"], + ha-icon[data-domain="switch"][data-state="on"], + ha-icon[data-domain="binary_sensor"][data-state="on"], + ha-icon[data-domain="fan"][data-state="on"], + ha-icon[data-domain="sun"][data-state="above_horizon"] { + color: var(--paper-item-icon-active-color, #fdd835); + } + + /* Color the icon if unavailable */ + ha-icon[data-state="unavailable"] { + color: var(--state-icon-unavailable-color); + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "state-badge": StateBadge; + } +} + +customElements.define("state-badge", StateBadge); diff --git a/src/components/ha-icon.js b/src/components/ha-icon.js deleted file mode 100644 index 29cb8b88b1..0000000000 --- a/src/components/ha-icon.js +++ /dev/null @@ -1,18 +0,0 @@ -import "@polymer/iron-icon/iron-icon"; - -const IronIconClass = customElements.get("iron-icon"); - -let loaded = false; - -class HaIcon extends IronIconClass { - listen(...args) { - super.listen(...args); - - if (!loaded && this._iconsetName === "mdi") { - loaded = true; - import(/* webpackChunkName: "mdi-icons" */ "../resources/mdi-icons"); - } - } -} - -customElements.define("ha-icon", HaIcon); diff --git a/src/components/ha-icon.ts b/src/components/ha-icon.ts new file mode 100644 index 0000000000..2e2a6ba848 --- /dev/null +++ b/src/components/ha-icon.ts @@ -0,0 +1,36 @@ +import { Constructor } from "lit-element"; +import "@polymer/iron-icon/iron-icon"; +// Not duplicate, this is for typing. +// tslint:disable-next-line +import { IronIconElement } from "@polymer/iron-icon/iron-icon"; + +const ironIconClass = customElements.get("iron-icon") as Constructor< + IronIconElement +>; + +let loaded = false; + +export class HaIcon extends ironIconClass { + private _iconsetName?: string; + + public listen( + node: EventTarget | null, + eventName: string, + methodName: string + ): void { + super.listen(node, eventName, methodName); + + if (!loaded && this._iconsetName === "mdi") { + loaded = true; + import(/* webpackChunkName: "mdi-icons" */ "../resources/mdi-icons"); + } + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-icon": HaIcon; + } +} + +customElements.define("ha-icon", HaIcon);