diff --git a/gallery/src/demos/demo-hui-picture-elements-card.js b/gallery/src/demos/demo-hui-picture-elements-card.js index 20b0fb60a5..99cfa7c12c 100644 --- a/gallery/src/demos/demo-hui-picture-elements-card.js +++ b/gallery/src/demos/demo-hui-picture-elements-card.js @@ -1,8 +1,32 @@ import { html } from "@polymer/polymer/lib/utils/html-tag.js"; import { PolymerElement } from "@polymer/polymer/polymer-element.js"; +import getEntity from "../data/entity.js"; +import provideHass from "../data/provide_hass.js"; import "../components/demo-cards.js"; +const ENTITIES = [ + getEntity("light", "bed_light", "on", { + friendly_name: "Bed Light", + }), + getEntity("group", "all_lights", "on", { + entity_id: ["light.bed_light"], + order: 8, + friendly_name: "All Lights", + }), + getEntity("camera", "demo_camera", "idle", { + access_token: + "2f5bb163fb91cd8770a9494fa5e7eab172d8d34f4aba806eb6b59411b8c720b8", + friendly_name: "Demo camera", + entity_picture: + "/api/camera_proxy/camera.demo_camera?token=2f5bb163fb91cd8770a9494fa5e7eab172d8d34f4aba806eb6b59411b8c720b8", + }), + getEntity("binary_sensor", "movement_backyard", "on", { + friendly_name: "Movement Backyard", + device_class: "motion", + }), +]; + const CONFIGS = [ { heading: "Card with few elements", @@ -56,7 +80,10 @@ const CONFIGS = [ class DemoPicElements extends PolymerElement { static get template() { return html` - + `; } @@ -68,6 +95,12 @@ class DemoPicElements extends PolymerElement { }, }; } + + ready() { + super.ready(); + const hass = provideHass(this.$.demos); + hass.addEntities(ENTITIES); + } } customElements.define("demo-hui-picture-elements-card", DemoPicElements); diff --git a/src/panels/lovelace/cards/hui-picture-elements-card.js b/src/panels/lovelace/cards/hui-picture-elements-card.js deleted file mode 100644 index 2dc138bf7b..0000000000 --- a/src/panels/lovelace/cards/hui-picture-elements-card.js +++ /dev/null @@ -1,103 +0,0 @@ -import { html } from "@polymer/polymer/lib/utils/html-tag.js"; -import { PolymerElement } from "@polymer/polymer/polymer-element.js"; - -import createHuiElement from "../common/create-hui-element.js"; - -class HuiPictureElementsCard extends PolymerElement { - static get template() { - return html` - - - - - -`; - } - - static get properties() { - return { - hass: { - type: Object, - observer: "_hassChanged", - }, - _config: Object, - }; - } - - constructor() { - super(); - this._elements = []; - } - - ready() { - super.ready(); - if (this._config) this._buildConfig(); - } - - getCardSize() { - return 4; - } - - setConfig(config) { - if (!config || !config.image || !Array.isArray(config.elements)) { - throw new Error("Invalid card configuration"); - } - - this._config = config; - if (this.$) this._buildConfig(); - } - - _buildConfig() { - const config = this._config; - const root = this.$.root; - this._elements = []; - - while (root.lastChild) { - root.removeChild(root.lastChild); - } - - const img = document.createElement("img"); - img.src = config.image; - root.appendChild(img); - - config.elements.forEach((element) => { - const el = createHuiElement(element); - el.hass = this.hass; - this._elements.push(el); - - el.classList.add("element"); - Object.keys(element.style).forEach((prop) => { - el.style.setProperty(prop, element.style[prop]); - }); - root.appendChild(el); - }); - - if (this.hass) { - this._hassChanged(this.hass); - } - } - - _hassChanged(hass) { - this._elements.forEach((element) => { - element.hass = hass; - }); - } -} - -customElements.define("hui-picture-elements-card", HuiPictureElementsCard); diff --git a/src/panels/lovelace/cards/hui-picture-elements-card.ts b/src/panels/lovelace/cards/hui-picture-elements-card.ts new file mode 100644 index 0000000000..d5d662b8b6 --- /dev/null +++ b/src/panels/lovelace/cards/hui-picture-elements-card.ts @@ -0,0 +1,105 @@ +import { html, LitElement } from "@polymer/lit-element"; +import { TemplateResult } from "lit-html"; + +import createHuiElement from "../common/create-hui-element.js"; + +import { LovelaceCard, LovelaceConfig } from "../types"; +import { HomeAssistant } from "../../../types.js"; +import { LovelaceElementConfig, LovelaceElement } from "../elements/types.js"; + +interface Config extends LovelaceConfig { + title?: string; + image: string; + elements: LovelaceElementConfig[]; +} + +class HuiPictureElementsCard extends LitElement implements LovelaceCard { + protected _config?: Config; + private _hass?: HomeAssistant; + + static get properties() { + return { + _config: {}, + }; + } + + set hass(hass: HomeAssistant) { + this._hass = hass; + for (const el of this.shadowRoot!.querySelectorAll("#root > *")) { + const element = el as LovelaceElement; + element.hass = this._hass; + } + } + + public getCardSize(): number { + return 4; + } + + public setConfig(config: Config): void { + if (!config) { + throw new Error("Invalid Configuration"); + } else if (!config.image) { + throw new Error("Invalid Configuration: image required"); + } else if (!Array.isArray(config.elements)) { + throw new Error("Invalid Configuration: elements required"); + } + + this._config = config; + } + + protected render(): TemplateResult { + if (!this._config) { + return html``; + } + + return html` + ${this.renderStyle()} + + + + ${this._config.elements.map((elementConfig: LovelaceElementConfig) => + this._createHuiElement(elementConfig) + )} + + + `; + } + + private renderStyle(): TemplateResult { + return html` + + `; + } + + private _createHuiElement( + elementConfig: LovelaceElementConfig + ): LovelaceElement { + const element = createHuiElement(elementConfig) as LovelaceElement; + element.hass = this._hass; + element.classList.add("element"); + + Object.keys(elementConfig.style).forEach((prop) => { + element.style.setProperty(prop, elementConfig.style[prop]); + }); + + return element; + } +} + +customElements.define("hui-picture-elements-card", HuiPictureElementsCard); diff --git a/src/panels/lovelace/elements/types.ts b/src/panels/lovelace/elements/types.ts new file mode 100644 index 0000000000..cdcc1dbe3d --- /dev/null +++ b/src/panels/lovelace/elements/types.ts @@ -0,0 +1,12 @@ +import { HomeAssistant } from "../../../types"; + +export interface LovelaceElementConfig { + type: string; + entity?: string; + style: object; +} + +export interface LovelaceElement extends HTMLElement { + hass?: HomeAssistant; + setConfig(config: LovelaceElementConfig): void; +} \ No newline at end of file