Convert hui-picture-elements-card to TypeScript/LitElement (#1853)

* Convert hui-picture-elements-card to TypeScript/LitElement

Elements are not showing currently

* Address review comments

* Update demo
This commit is contained in:
Ian Richardson 2018-10-26 03:04:04 -05:00 committed by Paulus Schoutsen
parent 17b4f873e7
commit 7ff9211dfc
4 changed files with 151 additions and 104 deletions

View File

@ -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`
<demo-cards configs="[[_configs]]"></demo-cards>
<demo-cards
id='demos'
configs="[[_configs]]"
></demo-cards>
`;
}
@ -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);

View File

@ -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`
<style>
ha-card {
overflow: hidden;
}
#root {
position: relative;
overflow: hidden;
}
#root img {
display: block;
width: 100%;
}
.element {
position: absolute;
transform: translate(-50%, -50%);
}
</style>
<ha-card header="[[_config.title]]">
<div id="root"></div>
</ha-card>
`;
}
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);

View File

@ -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()}
<ha-card .header="${this._config.title}">
<div id="root">
<img src="${this._config.image}">
${this._config.elements.map((elementConfig: LovelaceElementConfig) =>
this._createHuiElement(elementConfig)
)}
</div>
</ha-card>
`;
}
private renderStyle(): TemplateResult {
return html`
<style>
ha-card {
overflow: hidden;
}
#root {
position: relative;
overflow: hidden;
}
#root img {
display: block;
width: 100%;
}
.element {
position: absolute;
transform: translate(-50%, -50%);
}
</style>
`;
}
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);

View File

@ -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;
}