card level themes (#4057)

* card level themes

weather-forecast
shopping-list
plant-status
markdown
alarm-panel

* fix markdown

* address comments

also added picture cards

* update updated

* address comments

* address comments
This commit is contained in:
Ian Richardson 2019-10-21 12:38:06 -05:00 committed by GitHub
parent 540f1d9bce
commit 0078b48e3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 444 additions and 51 deletions

View File

@ -3,7 +3,7 @@ import { PolymerElement } from "@polymer/polymer";
import "@polymer/paper-icon-button"; import "@polymer/paper-icon-button";
import "../../src/resources/ha-style"; import "../../src/resources/ha-style";
import applyThemesOnElement from "../../src/common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
import { fireEvent } from "../../src/common/dom/fire_event"; import { fireEvent } from "../../src/common/dom/fire_event";
import { import {
HassRouterPage, HassRouterPage,

View File

@ -21,12 +21,12 @@ const hexToRgb = (hex: string): string | null => {
* localTheme: selected theme. * localTheme: selected theme.
* updateMeta: boolean if we should update the theme-color meta element. * updateMeta: boolean if we should update the theme-color meta element.
*/ */
export default function applyThemesOnElement( export const applyThemesOnElement = (
element, element,
themes, themes,
localTheme, localTheme,
updateMeta = false updateMeta = false
) { ) => {
if (!element._themes) { if (!element._themes) {
element._themes = {}; element._themes = {};
} }
@ -76,4 +76,4 @@ export default function applyThemesOnElement(
styles["--primary-color"] || meta.getAttribute("default-content"); styles["--primary-color"] || meta.getAttribute("default-content");
meta.setAttribute("content", themeColor); meta.setAttribute("content", themeColor);
} }
} };

View File

@ -1,4 +1,4 @@
import applyThemesOnElement from "../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../common/dom/apply_themes_on_element";
import { demoConfig } from "./demo_config"; import { demoConfig } from "./demo_config";
import { demoServices } from "./demo_services"; import { demoServices } from "./demo_services";

View File

@ -22,6 +22,7 @@ import {
} from "../../../data/alarm_control_panel"; } from "../../../data/alarm_control_panel";
import { AlarmPanelCardConfig } from "./types"; import { AlarmPanelCardConfig } from "./types";
import { PaperInputElement } from "@polymer/paper-input/paper-input"; import { PaperInputElement } from "@polymer/paper-input/paper-input";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
const ICONS = { const ICONS = {
armed_away: "hass:shield-lock", armed_away: "hass:shield-lock",
@ -81,19 +82,44 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
this._code = ""; this._code = "";
} }
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| AlarmPanelCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
}
protected shouldUpdate(changedProps: PropertyValues): boolean { protected shouldUpdate(changedProps: PropertyValues): boolean {
if (changedProps.has("_config") || changedProps.has("_code")) { if (changedProps.has("_config") || changedProps.has("_code")) {
return true; return true;
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
if (oldHass) {
return ( if (
oldHass.states[this._config!.entity] !== !oldHass ||
this.hass!.states[this._config!.entity] oldHass.themes !== this.hass!.themes ||
); oldHass.language !== this.hass!.language
) {
return true;
} }
return true; return (
oldHass.states[this._config!.entity] !==
this.hass!.states[this._config!.entity]
);
} }
protected render(): TemplateResult | void { protected render(): TemplateResult | void {

View File

@ -22,7 +22,7 @@ import { createRowElement } from "../common/create-row-element";
import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types"; import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
@customElement("hui-entities-card") @customElement("hui-entities-card")
class HuiEntitiesCard extends LitElement implements LovelaceCard { class HuiEntitiesCard extends LitElement implements LovelaceCard {
@ -71,9 +71,22 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
this._configEntities = entities; this._configEntities = entities;
} }
protected updated(changedProperties: PropertyValues): void { protected updated(changedProps: PropertyValues): void {
super.updated(changedProperties); super.updated(changedProps);
if (this._hass && this._config) { if (!this._config || !this._hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| EntitiesCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this._hass.themes, this._config.theme); applyThemesOnElement(this, this._hass.themes, this._config.theme);
} }
} }

View File

@ -19,7 +19,7 @@ import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import { stateIcon } from "../../../common/entity/state_icon"; import { stateIcon } from "../../../common/entity/state_icon";
import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { HomeAssistant, LightEntity } from "../../../types"; import { HomeAssistant, LightEntity } from "../../../types";
@ -91,13 +91,19 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
if (oldHass) {
return ( if (
oldHass.states[this._config!.entity] !== !oldHass ||
this.hass!.states[this._config!.entity] oldHass.themes !== this.hass!.themes ||
); oldHass.language !== this.hass!.language
) {
return true;
} }
return true;
return (
oldHass.states[this._config!.entity] !==
this.hass!.states[this._config!.entity]
);
} }
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
@ -161,7 +167,16 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
return; return;
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
if (!oldHass || oldHass.themes !== this.hass.themes) { const oldConfig = changedProps.get("_config") as
| EntityButtonCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme); applyThemesOnElement(this, this.hass.themes, this._config.theme);
} }
} }

View File

@ -14,7 +14,7 @@ import "../../../components/ha-card";
import "../components/hui-warning"; import "../components/hui-warning";
import { isValidEntityId } from "../../../common/entity/valid_entity_id"; import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
@ -149,8 +149,16 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| GaugeCardConfig
| undefined;
if (!oldHass || oldHass.themes !== this.hass.themes) { if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme); applyThemesOnElement(this, this.hass.themes, this._config.theme);
} }
} }

View File

@ -11,7 +11,7 @@ import {
import { classMap } from "lit-html/directives/class-map"; import { classMap } from "lit-html/directives/class-map";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import relativeTime from "../../../common/datetime/relative_time"; import relativeTime from "../../../common/datetime/relative_time";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
@ -87,17 +87,23 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
if (oldHass && this._configEntities) {
for (const entity of this._configEntities) { if (
if ( !this._configEntities ||
oldHass.states[entity.entity] !== this.hass!.states[entity.entity] !oldHass ||
) { oldHass.themes !== this.hass!.themes ||
return true; oldHass.language !== this.hass!.language
} ) {
} return true;
return false;
} }
return true;
for (const entity of this._configEntities) {
if (oldHass.states[entity.entity] !== this.hass!.states[entity.entity]) {
return true;
}
}
return false;
} }
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
@ -117,14 +123,23 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
`; `;
} }
protected updated(changedProperties: PropertyValues): void { protected updated(changedProps: PropertyValues): void {
super.updated(changedProperties); super.updated(changedProps);
if (!this._config || !this.hass) { if (!this._config || !this.hass) {
return; return;
} }
const oldHass = changedProperties.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
if (!oldHass || oldHass.themes !== this.hass.themes) { const oldConfig = changedProps.get("_config") as
| GlanceCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme); applyThemesOnElement(this, this.hass.themes, this._config.theme);
} }
} }

View File

@ -11,7 +11,7 @@ import "@thomasloven/round-slider";
import { stateIcon } from "../../../common/entity/state_icon"; import { stateIcon } from "../../../common/entity/state_icon";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-icon";
@ -145,7 +145,16 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
if (!oldHass || oldHass.themes !== this.hass.themes) { const oldConfig = changedProps.get("_config") as
| LightCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme); applyThemesOnElement(this, this.hass.themes, this._config.theme);
} }
} }

View File

@ -6,6 +6,7 @@ import {
property, property,
css, css,
CSSResult, CSSResult,
PropertyValues,
} from "lit-element"; } from "lit-element";
import { classMap } from "lit-html/directives/class-map"; import { classMap } from "lit-html/directives/class-map";
import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { UnsubscribeFunc } from "home-assistant-js-websocket";
@ -17,6 +18,7 @@ import { HomeAssistant } from "../../../types";
import { LovelaceCard, LovelaceCardEditor } from "../types"; import { LovelaceCard, LovelaceCardEditor } from "../types";
import { MarkdownCardConfig } from "./types"; import { MarkdownCardConfig } from "./types";
import { subscribeRenderTemplate } from "../../../data/ws-templates"; import { subscribeRenderTemplate } from "../../../data/ws-templates";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
@customElement("hui-markdown-card") @customElement("hui-markdown-card")
export class HuiMarkdownCard extends LitElement implements LovelaceCard { export class HuiMarkdownCard extends LitElement implements LovelaceCard {
@ -84,6 +86,26 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
`; `;
} }
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this._hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| MarkdownCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this._hass.themes, this._config.theme);
}
}
private async _connect() { private async _connect() {
if (!this._unsubRenderTemplate && this._hass && this._config) { if (!this._unsubRenderTemplate && this._hass && this._config) {
this._unsubRenderTemplate = subscribeRenderTemplate( this._unsubRenderTemplate = subscribeRenderTemplate(

View File

@ -6,6 +6,7 @@ import {
property, property,
css, css,
CSSResult, CSSResult,
PropertyValues,
} from "lit-element"; } from "lit-element";
import "../../../components/ha-card"; import "../../../components/ha-card";
@ -17,6 +18,7 @@ import { handleClick } from "../common/handle-click";
import { longPress } from "../common/directives/long-press-directive"; import { longPress } from "../common/directives/long-press-directive";
import { PictureCardConfig } from "./types"; import { PictureCardConfig } from "./types";
import { hasDoubleClick } from "../common/has-double-click"; import { hasDoubleClick } from "../common/has-double-click";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
@customElement("hui-picture-card") @customElement("hui-picture-card")
export class HuiPictureCard extends LitElement implements LovelaceCard { export class HuiPictureCard extends LitElement implements LovelaceCard {
@ -49,6 +51,26 @@ export class HuiPictureCard extends LitElement implements LovelaceCard {
this._config = config; this._config = config;
} }
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| PictureCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this._config || !this.hass) { if (!this._config || !this.hass) {
return html``; return html``;

View File

@ -6,6 +6,7 @@ import {
customElement, customElement,
css, css,
CSSResult, CSSResult,
PropertyValues,
} from "lit-element"; } from "lit-element";
import { createStyledHuiElement } from "./picture-elements/create-styled-hui-element"; import { createStyledHuiElement } from "./picture-elements/create-styled-hui-element";
@ -13,6 +14,7 @@ import { LovelaceCard } from "../types";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceElementConfig, LovelaceElement } from "../elements/types"; import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
import { PictureElementsCardConfig } from "./types"; import { PictureElementsCardConfig } from "./types";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
@customElement("hui-picture-elements-card") @customElement("hui-picture-elements-card")
class HuiPictureElementsCard extends LitElement implements LovelaceCard { class HuiPictureElementsCard extends LitElement implements LovelaceCard {
@ -49,6 +51,26 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard {
this._config = config; this._config = config;
} }
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this._hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| PictureElementsCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this._hass.themes, this._config.theme);
}
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this._config) { if (!this._config) {
return html``; return html``;

View File

@ -26,6 +26,7 @@ import { UNAVAILABLE } from "../../../data/entity";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
import { PictureEntityCardConfig } from "./types"; import { PictureEntityCardConfig } from "./types";
import { hasDoubleClick } from "../common/has-double-click"; import { hasDoubleClick } from "../common/has-double-click";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
@customElement("hui-picture-entity-card") @customElement("hui-picture-entity-card")
class HuiPictureEntityCard extends LitElement implements LovelaceCard { class HuiPictureEntityCard extends LitElement implements LovelaceCard {
@ -68,6 +69,26 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
return hasConfigOrEntityChanged(this, changedProps); return hasConfigOrEntityChanged(this, changedProps);
} }
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| PictureEntityCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this._config || !this.hass) { if (!this._config || !this.hass) {
return html``; return html``;

View File

@ -28,6 +28,7 @@ import { handleClick } from "../common/handle-click";
import { hasDoubleClick } from "../common/has-double-click"; import { hasDoubleClick } from "../common/has-double-click";
import { PictureGlanceCardConfig, PictureGlanceEntityConfig } from "./types"; import { PictureGlanceCardConfig, PictureGlanceEntityConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]); const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]);
@ -93,6 +94,14 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
if (
!oldHass ||
oldHass.themes !== this.hass!.themes ||
oldHass.language !== this.hass!.language
) {
return true;
}
if (this._entitiesDialog) { if (this._entitiesDialog) {
for (const entity of this._entitiesDialog) { for (const entity of this._entitiesDialog) {
if ( if (
@ -116,6 +125,26 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
return false; return false;
} }
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| PictureGlanceCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this._config || !this.hass) { if (!this._config || !this.hass) {
return html``; return html``;

View File

@ -20,6 +20,7 @@ import { HomeAssistant } from "../../../types";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
import { PlantStatusCardConfig, PlantAttributeTarget } from "./types"; import { PlantStatusCardConfig, PlantAttributeTarget } from "./types";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
const SENSORS = { const SENSORS = {
moisture: "hass:water", moisture: "hass:water",
@ -60,6 +61,26 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
return hasConfigOrEntityChanged(this, changedProps); return hasConfigOrEntityChanged(this, changedProps);
} }
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| PlantStatusCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass || !this._config) { if (!this.hass || !this._config) {
return html``; return html``;

View File

@ -11,7 +11,7 @@ import {
} from "lit-element"; } from "lit-element";
import "@polymer/paper-spinner/paper-spinner"; import "@polymer/paper-spinner/paper-spinner";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon"; import { stateIcon } from "../../../common/entity/state_icon";
@ -277,7 +277,16 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
if (!oldHass || oldHass.themes !== this.hass.themes) { const oldConfig = changedProps.get("_config") as
| SensorCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config!.theme); applyThemesOnElement(this, this.hass.themes, this._config!.theme);
} }

View File

@ -6,6 +6,7 @@ import {
CSSResult, CSSResult,
property, property,
customElement, customElement,
PropertyValues,
} from "lit-element"; } from "lit-element";
import { repeat } from "lit-html/directives/repeat"; import { repeat } from "lit-html/directives/repeat";
import { PaperInputElement } from "@polymer/paper-input/paper-input"; import { PaperInputElement } from "@polymer/paper-input/paper-input";
@ -23,7 +24,8 @@ import {
clearItems, clearItems,
addItem, addItem,
} from "../../../data/shopping-list"; } from "../../../data/shopping-list";
import { ShoppingListCardConfig } from "./types"; import { ShoppingListCardConfig, SensorCardConfig } from "./types";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
@customElement("hui-shopping-list-card") @customElement("hui-shopping-list-card")
class HuiShoppingListCard extends LitElement implements LovelaceCard { class HuiShoppingListCard extends LitElement implements LovelaceCard {
@ -77,6 +79,26 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard {
} }
} }
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| SensorCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this._config || !this.hass) { if (!this._config || !this.hass) {
return html``; return html``;

View File

@ -16,7 +16,7 @@ import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-icon";
import "../components/hui-warning"; import "../components/hui-warning";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
@ -235,8 +235,16 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| ThermostatCardConfig
| undefined;
if (!oldHass || oldHass.themes !== this.hass.themes) { if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme); applyThemesOnElement(this, this.hass.themes, this._config.theme);
} }

View File

@ -22,6 +22,7 @@ import { WeatherForecastCardConfig } from "./types";
import { computeRTL } from "../../../common/util/compute_rtl"; import { computeRTL } from "../../../common/util/compute_rtl";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { toggleAttribute } from "../../../common/dom/toggle_attribute"; import { toggleAttribute } from "../../../common/dom/toggle_attribute";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
const cardinalDirections = [ const cardinalDirections = [
"N", "N",
@ -92,6 +93,23 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
protected updated(changedProps: PropertyValues): void { protected updated(changedProps: PropertyValues): void {
super.updated(changedProps); super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| WeatherForecastCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
if (changedProps.has("hass")) { if (changedProps.has("hass")) {
toggleAttribute(this, "rtl", computeRTL(this.hass!)); toggleAttribute(this, "rtl", computeRTL(this.hass!));
} }

View File

@ -8,6 +8,7 @@ export interface AlarmPanelCardConfig extends LovelaceCardConfig {
entity: string; entity: string;
name?: string; name?: string;
states?: string[]; states?: string[];
theme?: string;
} }
export interface ConditionalCardConfig extends LovelaceCardConfig { export interface ConditionalCardConfig extends LovelaceCardConfig {
@ -134,6 +135,7 @@ export interface MarkdownCardConfig extends LovelaceCardConfig {
title?: string; title?: string;
card_size?: number; card_size?: number;
entity_ids?: string | string[]; entity_ids?: string | string[];
theme?: string;
} }
export interface MediaControlCardConfig extends LovelaceCardConfig { export interface MediaControlCardConfig extends LovelaceCardConfig {
@ -145,6 +147,7 @@ export interface PictureCardConfig extends LovelaceCardConfig {
tap_action?: ActionConfig; tap_action?: ActionConfig;
hold_action?: ActionConfig; hold_action?: ActionConfig;
double_tap_action?: ActionConfig; double_tap_action?: ActionConfig;
theme?: string;
} }
export interface PictureElementsCardConfig extends LovelaceCardConfig { export interface PictureElementsCardConfig extends LovelaceCardConfig {
@ -157,6 +160,7 @@ export interface PictureElementsCardConfig extends LovelaceCardConfig {
aspect_ratio?: string; aspect_ratio?: string;
entity?: string; entity?: string;
elements: LovelaceElementConfig[]; elements: LovelaceElementConfig[];
theme?: string;
} }
export interface PictureEntityCardConfig extends LovelaceCardConfig { export interface PictureEntityCardConfig extends LovelaceCardConfig {
@ -173,6 +177,7 @@ export interface PictureEntityCardConfig extends LovelaceCardConfig {
double_tap_action?: ActionConfig; double_tap_action?: ActionConfig;
show_name?: boolean; show_name?: boolean;
show_state?: boolean; show_state?: boolean;
theme?: string;
} }
export interface PictureGlanceCardConfig extends LovelaceCardConfig { export interface PictureGlanceCardConfig extends LovelaceCardConfig {
@ -189,6 +194,7 @@ export interface PictureGlanceCardConfig extends LovelaceCardConfig {
hold_action?: ActionConfig; hold_action?: ActionConfig;
double_tap_action?: ActionConfig; double_tap_action?: ActionConfig;
show_state?: boolean; show_state?: boolean;
theme?: string;
} }
export interface PlantAttributeTarget extends EventTarget { export interface PlantAttributeTarget extends EventTarget {
@ -198,6 +204,7 @@ export interface PlantAttributeTarget extends EventTarget {
export interface PlantStatusCardConfig extends LovelaceCardConfig { export interface PlantStatusCardConfig extends LovelaceCardConfig {
name?: string; name?: string;
entity: string; entity: string;
theme?: string;
} }
export interface SensorCardConfig extends LovelaceCardConfig { export interface SensorCardConfig extends LovelaceCardConfig {
@ -213,6 +220,7 @@ export interface SensorCardConfig extends LovelaceCardConfig {
export interface ShoppingListCardConfig extends LovelaceCardConfig { export interface ShoppingListCardConfig extends LovelaceCardConfig {
title?: string; title?: string;
theme?: string;
} }
export interface StackCardConfig extends LovelaceCardConfig { export interface StackCardConfig extends LovelaceCardConfig {

View File

@ -15,6 +15,13 @@ export function hasConfigOrEntityChanged(
return true; return true;
} }
if (
oldHass.themes !== element.hass!.themes ||
oldHass.language !== element.hass!.language
) {
return true;
}
return ( return (
oldHass.states[element._config!.entity] !== oldHass.states[element._config!.entity] !==
element.hass!.states[element._config!.entity] || element.hass!.states[element._config!.entity] ||

View File

@ -17,16 +17,18 @@ import { HomeAssistant } from "../../../../types";
import { LovelaceCardEditor } from "../../types"; import { LovelaceCardEditor } from "../../types";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { configElementStyle } from "./config-elements-style"; import { configElementStyle } from "./config-elements-style";
import { AlarmPanelCardConfig } from "../../cards/types";
import "../../../../components/entity/ha-entity-picker"; import "../../../../components/entity/ha-entity-picker";
import "../../../../components/ha-icon"; import "../../../../components/ha-icon";
import { AlarmPanelCardConfig } from "../../cards/types"; import "../../components/hui-theme-select-editor";
const cardConfigStruct = struct({ const cardConfigStruct = struct({
type: "string", type: "string",
entity: "string?", entity: "string?",
name: "string?", name: "string?",
states: "array?", states: "array?",
theme: "string?",
}); });
@customElement("hui-alarm-panel-card-editor") @customElement("hui-alarm-panel-card-editor")
@ -53,6 +55,10 @@ export class HuiAlarmPanelCardEditor extends LitElement
return this._config!.states || []; return this._config!.states || [];
} }
get _theme(): string {
return this._config!.theme || "Backend-selected";
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -113,6 +119,12 @@ export class HuiAlarmPanelCardEditor extends LitElement
})} })}
</paper-listbox> </paper-listbox>
</paper-dropdown-menu> </paper-dropdown-menu>
<hui-theme-select-editor
.hass="${this.hass}"
.value="${this._theme}"
.configValue="${"theme"}"
@theme-changed="${this._valueChanged}"
></hui-theme-select-editor>
</div> </div>
`; `;
} }

View File

@ -16,10 +16,13 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import { configElementStyle } from "./config-elements-style"; import { configElementStyle } from "./config-elements-style";
import { MarkdownCardConfig } from "../../cards/types"; import { MarkdownCardConfig } from "../../cards/types";
import "../../components/hui-theme-select-editor";
const cardConfigStruct = struct({ const cardConfigStruct = struct({
type: "string", type: "string",
title: "string?", title: "string?",
content: "string", content: "string",
theme: "string?",
}); });
@customElement("hui-markdown-card-editor") @customElement("hui-markdown-card-editor")
@ -42,6 +45,10 @@ export class HuiMarkdownCardEditor extends LitElement
return this._config!.content || ""; return this._config!.content || "";
} }
get _theme(): string {
return this._config!.theme || "Backend-selected";
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -73,6 +80,12 @@ export class HuiMarkdownCardEditor extends LitElement
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
></paper-textarea> ></paper-textarea>
<hui-theme-select-editor
.hass="${this.hass}"
.value="${this._theme}"
.configValue="${"theme"}"
@theme-changed="${this._valueChanged}"
></hui-theme-select-editor>
</div> </div>
`; `;
} }

View File

@ -8,6 +8,7 @@ import {
import "@polymer/paper-input/paper-input"; import "@polymer/paper-input/paper-input";
import "../../components/hui-action-editor"; import "../../components/hui-action-editor";
import "../../components/hui-theme-select-editor";
import { struct } from "../../common/structs/struct"; import { struct } from "../../common/structs/struct";
import { import {
@ -27,6 +28,7 @@ const cardConfigStruct = struct({
image: "string?", image: "string?",
tap_action: struct.optional(actionConfigStruct), tap_action: struct.optional(actionConfigStruct),
hold_action: struct.optional(actionConfigStruct), hold_action: struct.optional(actionConfigStruct),
theme: "string?",
}); });
@customElement("hui-picture-card-editor") @customElement("hui-picture-card-editor")
@ -53,6 +55,10 @@ export class HuiPictureCardEditor extends LitElement
return this._config!.hold_action || { action: "none" }; return this._config!.hold_action || { action: "none" };
} }
get _theme(): string {
return this._config!.theme || "Backend-selected";
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -98,6 +104,12 @@ export class HuiPictureCardEditor extends LitElement
.configValue="${"hold_action"}" .configValue="${"hold_action"}"
@action-changed="${this._valueChanged}" @action-changed="${this._valueChanged}"
></hui-action-editor> ></hui-action-editor>
<hui-theme-select-editor
.hass="${this.hass}"
.value="${this._theme}"
.configValue="${"theme"}"
@theme-changed="${this._valueChanged}"
></hui-theme-select-editor>
</div> </div>
</div> </div>
`; `;

View File

@ -13,6 +13,7 @@ import "@polymer/paper-listbox/paper-listbox";
import "../../components/hui-action-editor"; import "../../components/hui-action-editor";
import "../../components/hui-entity-editor"; import "../../components/hui-entity-editor";
import "../../../../components/ha-switch"; import "../../../../components/ha-switch";
import "../../components/hui-theme-select-editor";
import { struct } from "../../common/structs/struct"; import { struct } from "../../common/structs/struct";
import { import {
@ -39,6 +40,7 @@ const cardConfigStruct = struct({
hold_action: struct.optional(actionConfigStruct), hold_action: struct.optional(actionConfigStruct),
show_name: "boolean?", show_name: "boolean?",
show_state: "boolean?", show_state: "boolean?",
theme: "string?",
}); });
@customElement("hui-picture-entity-card-editor") @customElement("hui-picture-entity-card-editor")
@ -93,6 +95,10 @@ export class HuiPictureEntityCardEditor extends LitElement
return this._config!.show_state || true; return this._config!.show_state || true;
} }
get _theme(): string {
return this._config!.theme || "Backend-selected";
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -225,6 +231,12 @@ export class HuiPictureEntityCardEditor extends LitElement
.configValue="${"hold_action"}" .configValue="${"hold_action"}"
@action-changed="${this._valueChanged}" @action-changed="${this._valueChanged}"
></hui-action-editor> ></hui-action-editor>
<hui-theme-select-editor
.hass="${this.hass}"
.value="${this._theme}"
.configValue="${"theme"}"
@theme-changed="${this._valueChanged}"
></hui-theme-select-editor>
</div> </div>
</div> </div>
`; `;

View File

@ -13,6 +13,7 @@ import "@polymer/paper-listbox/paper-listbox";
import "../../components/hui-action-editor"; import "../../components/hui-action-editor";
import "../../components/hui-entity-editor"; import "../../components/hui-entity-editor";
import "../../../../components/entity/ha-entity-picker"; import "../../../../components/entity/ha-entity-picker";
import "../../components/hui-theme-select-editor";
import { struct } from "../../common/structs/struct"; import { struct } from "../../common/structs/struct";
import { import {
@ -41,6 +42,7 @@ const cardConfigStruct = struct({
tap_action: struct.optional(actionConfigStruct), tap_action: struct.optional(actionConfigStruct),
hold_action: struct.optional(actionConfigStruct), hold_action: struct.optional(actionConfigStruct),
entities: [entitiesConfigStruct], entities: [entitiesConfigStruct],
theme: "string?",
}); });
@customElement("hui-picture-glance-card-editor") @customElement("hui-picture-glance-card-editor")
@ -104,6 +106,10 @@ export class HuiPictureGlanceCardEditor extends LitElement
return this._config!.show_state || false; return this._config!.show_state || false;
} }
get _theme(): string {
return this._config!.theme || "Backend-selected";
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -224,6 +230,12 @@ export class HuiPictureGlanceCardEditor extends LitElement
.entities="${this._configEntities}" .entities="${this._configEntities}"
@entities-changed="${this._valueChanged}" @entities-changed="${this._valueChanged}"
></hui-entity-editor> ></hui-entity-editor>
<hui-theme-select-editor
.hass="${this.hass}"
.value="${this._theme}"
.configValue="${"theme"}"
@theme-changed="${this._valueChanged}"
></hui-theme-select-editor>
</div> </div>
`; `;
} }

View File

@ -9,6 +9,7 @@ import "@polymer/paper-input/paper-input";
import "../../../../components/entity/ha-entity-picker"; import "../../../../components/entity/ha-entity-picker";
import "../../../../components/ha-icon"; import "../../../../components/ha-icon";
import "../../components/hui-theme-select-editor";
import { struct } from "../../common/structs/struct"; import { struct } from "../../common/structs/struct";
import { EntitiesEditorEvent, EditorTarget } from "../types"; import { EntitiesEditorEvent, EditorTarget } from "../types";
@ -22,6 +23,7 @@ const cardConfigStruct = struct({
type: "string", type: "string",
entity: "string", entity: "string",
name: "string?", name: "string?",
theme: "string?",
}); });
@customElement("hui-plant-status-card-editor") @customElement("hui-plant-status-card-editor")
@ -44,6 +46,10 @@ export class HuiPlantStatusCardEditor extends LitElement
return this._config!.name || ""; return this._config!.name || "";
} }
get _theme(): string {
return this._config!.theme || "Backend-selected";
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -75,6 +81,12 @@ export class HuiPlantStatusCardEditor extends LitElement
.configValue="${"name"}" .configValue="${"name"}"
@value-changed="${this._valueChanged}" @value-changed="${this._valueChanged}"
></paper-input> ></paper-input>
<hui-theme-select-editor
.hass="${this.hass}"
.value="${this._theme}"
.configValue="${"theme"}"
@theme-changed="${this._valueChanged}"
></hui-theme-select-editor>
</div> </div>
`; `;
} }

View File

@ -14,9 +14,12 @@ import { LovelaceCardEditor } from "../../types";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { ShoppingListCardConfig } from "../../cards/types"; import { ShoppingListCardConfig } from "../../cards/types";
import "../../components/hui-theme-select-editor";
const cardConfigStruct = struct({ const cardConfigStruct = struct({
type: "string", type: "string",
title: "string?", title: "string?",
theme: "string?",
}); });
@customElement("hui-shopping-list-card-editor") @customElement("hui-shopping-list-card-editor")
@ -35,6 +38,10 @@ export class HuiShoppingListEditor extends LitElement
return this._config!.title || ""; return this._config!.title || "";
} }
get _theme(): string {
return this._config!.theme || "Backend-selected";
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -52,6 +59,12 @@ export class HuiShoppingListEditor extends LitElement
.configValue="${"title"}" .configValue="${"title"}"
@value-changed="${this._valueChanged}" @value-changed="${this._valueChanged}"
></paper-input> ></paper-input>
<hui-theme-select-editor
.hass="${this.hass}"
.value="${this._theme}"
.configValue="${"theme"}"
@theme-changed="${this._valueChanged}"
></hui-theme-select-editor>
</div> </div>
`; `;
} }

View File

@ -7,6 +7,7 @@ import {
} from "lit-element"; } from "lit-element";
import "../../../../components/entity/ha-entity-picker"; import "../../../../components/entity/ha-entity-picker";
import "../../components/hui-theme-select-editor";
import { struct } from "../../common/structs/struct"; import { struct } from "../../common/structs/struct";
import { EntitiesEditorEvent, EditorTarget } from "../types"; import { EntitiesEditorEvent, EditorTarget } from "../types";
@ -20,6 +21,7 @@ const cardConfigStruct = struct({
type: "string", type: "string",
entity: "string?", entity: "string?",
name: "string?", name: "string?",
theme: "string?",
}); });
@customElement("hui-weather-forecast-card-editor") @customElement("hui-weather-forecast-card-editor")
@ -42,6 +44,10 @@ export class HuiWeatherForecastCardEditor extends LitElement
return this._config!.name || ""; return this._config!.name || "";
} }
get _theme(): string {
return this._config!.theme || "Backend-selected";
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -73,6 +79,12 @@ export class HuiWeatherForecastCardEditor extends LitElement
.configValue="${"name"}" .configValue="${"name"}"
@value-changed="${this._valueChanged}" @value-changed="${this._valueChanged}"
></paper-input> ></paper-input>
<hui-theme-select-editor
.hass="${this.hass}"
.value="${this._theme}"
.configValue="${"theme"}"
@theme-changed="${this._valueChanged}"
></hui-theme-select-editor>
</div> </div>
`; `;
} }

View File

@ -5,7 +5,7 @@ import {
UpdatingElement, UpdatingElement,
} from "lit-element"; } from "lit-element";
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCard } from "../types"; import { LovelaceCard } from "../types";

View File

@ -9,7 +9,7 @@ import {
import "../../../components/entity/ha-state-label-badge"; import "../../../components/entity/ha-state-label-badge";
// This one is for types // This one is for types
import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { import {
LovelaceViewConfig, LovelaceViewConfig,

View File

@ -1,4 +1,4 @@
import applyThemesOnElement from "../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../common/dom/apply_themes_on_element";
import { storeState } from "../util/ha-pref-storage"; import { storeState } from "../util/ha-pref-storage";
import { subscribeThemes } from "../data/ws-themes"; import { subscribeThemes } from "../data/ws-themes";
import { HassBaseEl } from "./hass-base-mixin"; import { HassBaseEl } from "./hass-base-mixin";