diff --git a/src/components/ha-selector/ha-selector-icon.ts b/src/components/ha-selector/ha-selector-icon.ts
index e10969fbcb..1a5d10cf72 100644
--- a/src/components/ha-selector/ha-selector-icon.ts
+++ b/src/components/ha-selector/ha-selector-icon.ts
@@ -1,6 +1,8 @@
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
+import { computeDomain } from "../../common/entity/compute_domain";
+import { domainIcon } from "../../common/entity/domain_icon";
import { IconSelector } from "../../data/selector";
import { HomeAssistant } from "../../types";
import "../ha-icon-picker";
@@ -21,7 +23,22 @@ export class HaIconSelector extends LitElement {
@property({ type: Boolean }) public required = true;
+ @property() public context?: {
+ icon_entity?: string;
+ };
+
protected render() {
+ const iconEntity = this.context?.icon_entity;
+
+ const stateObj = iconEntity ? this.hass.states[iconEntity] : undefined;
+
+ const placeholder =
+ this.selector.icon?.placeholder || stateObj?.attributes.icon;
+ const fallbackPath =
+ !placeholder && stateObj
+ ? domainIcon(computeDomain(iconEntity!), stateObj)
+ : undefined;
+
return html`
`;
diff --git a/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts
index da8436cf5b..5256fe846b 100644
--- a/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts
@@ -1,11 +1,7 @@
-import type { HassEntity } from "home-assistant-js-websocket";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
-import memoizeOne from "memoize-one";
import { assert, assign, boolean, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { computeDomain } from "../../../../common/entity/compute_domain";
-import { domainIcon } from "../../../../common/entity/domain_icon";
import { entityId } from "../../../../common/structs/is-entity-id";
import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
@@ -32,6 +28,52 @@ const cardConfigStruct = assign(
})
);
+const SCHEMA = [
+ { name: "entity", selector: { entity: {} } },
+ {
+ name: "",
+ type: "grid",
+ schema: [
+ { name: "name", selector: { text: {} } },
+ {
+ name: "icon",
+ selector: {
+ icon: {},
+ },
+ context: {
+ icon_entity: "entity",
+ },
+ },
+ ],
+ },
+ {
+ name: "",
+ type: "grid",
+ column_min_width: "100px",
+ schema: [
+ { name: "show_name", selector: { boolean: {} } },
+ { name: "show_state", selector: { boolean: {} } },
+ { name: "show_icon", selector: { boolean: {} } },
+ ],
+ },
+ {
+ name: "",
+ type: "grid",
+ schema: [
+ { name: "icon_height", selector: { text: { suffix: "px" } } },
+ { name: "theme", selector: { theme: {} } },
+ ],
+ },
+ {
+ name: "tap_action",
+ selector: { "ui-action": {} },
+ },
+ {
+ name: "hold_action",
+ selector: { "ui-action": {} },
+ },
+] as const;
+
@customElement("hui-button-card-editor")
export class HuiButtonCardEditor
extends LitElement
@@ -46,76 +88,11 @@ export class HuiButtonCardEditor
this._config = config;
}
- private _schema = memoizeOne(
- (entity?: string, icon?: string, entityState?: HassEntity) =>
- [
- { name: "entity", selector: { entity: {} } },
- {
- name: "",
- type: "grid",
- schema: [
- { name: "name", selector: { text: {} } },
- {
- name: "icon",
- selector: {
- icon: {
- placeholder: icon || entityState?.attributes.icon,
- fallbackPath:
- !icon &&
- !entityState?.attributes.icon &&
- entityState &&
- entity
- ? domainIcon(computeDomain(entity), entityState)
- : undefined,
- },
- },
- },
- ],
- },
- {
- name: "",
- type: "grid",
- column_min_width: "100px",
- schema: [
- { name: "show_name", selector: { boolean: {} } },
- { name: "show_state", selector: { boolean: {} } },
- { name: "show_icon", selector: { boolean: {} } },
- ],
- },
- {
- name: "",
- type: "grid",
- schema: [
- { name: "icon_height", selector: { text: { suffix: "px" } } },
- { name: "theme", selector: { theme: {} } },
- ],
- },
- {
- name: "tap_action",
- selector: { "ui-action": {} },
- },
- {
- name: "hold_action",
- selector: { "ui-action": {} },
- },
- ] as const
- );
-
protected render(): TemplateResult {
if (!this.hass || !this._config) {
return html``;
}
- const entityState = this._config.entity
- ? this.hass.states[this._config.entity]
- : undefined;
-
- const schema = this._schema(
- this._config.entity,
- this._config.icon,
- entityState
- );
-
const data = {
show_name: true,
show_icon: true,
@@ -130,7 +107,7 @@ export class HuiButtonCardEditor
>
- ) => {
+ private _computeHelperCallback = (schema: SchemaUnion) => {
switch (schema.name) {
case "tap_action":
case "hold_action":
@@ -162,9 +137,7 @@ export class HuiButtonCardEditor
}
};
- private _computeLabelCallback = (
- schema: SchemaUnion>
- ) => {
+ private _computeLabelCallback = (schema: SchemaUnion) => {
switch (schema.name) {
case "theme":
case "tap_action":
diff --git a/src/panels/lovelace/editor/config-elements/hui-entity-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entity-card-editor.ts
index 37e3c34874..4b1df3306d 100644
--- a/src/panels/lovelace/editor/config-elements/hui-entity-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-entity-card-editor.ts
@@ -1,11 +1,7 @@
-import type { HassEntity } from "home-assistant-js-websocket/dist/types";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
-import memoizeOne from "memoize-one";
import { assert, assign, boolean, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { computeDomain } from "../../../../common/entity/compute_domain";
-import { domainIcon } from "../../../../common/entity/domain_icon";
import { entityId } from "../../../../common/structs/is-entity-id";
import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
@@ -29,6 +25,38 @@ const cardConfigStruct = assign(
})
);
+const SCHEMA = [
+ { name: "entity", required: true, selector: { entity: {} } },
+ {
+ type: "grid",
+ name: "",
+ schema: [
+ { name: "name", selector: { text: {} } },
+ {
+ name: "icon",
+ selector: {
+ icon: {},
+ },
+ context: {
+ icon_entity: "entity",
+ },
+ },
+ {
+ name: "attribute",
+ selector: {
+ attribute: {},
+ },
+ context: {
+ filter_entity: "entity",
+ },
+ },
+ { name: "unit", selector: { text: {} } },
+ { name: "theme", selector: { theme: {} } },
+ { name: "state_color", selector: { boolean: {} } },
+ ],
+ },
+] as const;
+
@customElement("hui-entity-card-editor")
export class HuiEntityCardEditor
extends LitElement
@@ -43,58 +71,16 @@ export class HuiEntityCardEditor
this._config = config;
}
- private _schema = memoizeOne(
- (entity: string, icon: string, entityState: HassEntity) =>
- [
- { name: "entity", required: true, selector: { entity: {} } },
- {
- type: "grid",
- name: "",
- schema: [
- { name: "name", selector: { text: {} } },
- {
- name: "icon",
- selector: {
- icon: {
- placeholder: icon || entityState?.attributes.icon,
- fallbackPath:
- !icon && !entityState?.attributes.icon && entityState
- ? domainIcon(computeDomain(entity), entityState)
- : undefined,
- },
- },
- },
-
- {
- name: "attribute",
- selector: { attribute: { entity_id: entity } },
- },
- { name: "unit", selector: { text: {} } },
- { name: "theme", selector: { theme: {} } },
- { name: "state_color", selector: { boolean: {} } },
- ],
- },
- ] as const
- );
-
protected render(): TemplateResult {
if (!this.hass || !this._config) {
return html``;
}
- const entityState = this.hass.states[this._config.entity];
-
- const schema = this._schema(
- this._config.entity,
- this._config.icon,
- entityState
- );
-
return html`
@@ -107,9 +93,7 @@ export class HuiEntityCardEditor
fireEvent(this, "config-changed", { config });
}
- private _computeLabelCallback = (
- schema: SchemaUnion>
- ) => {
+ private _computeLabelCallback = (schema: SchemaUnion) => {
if (schema.name === "entity") {
return this.hass!.localize(
"ui.panel.lovelace.editor.card.generic.entity"
diff --git a/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts b/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts
index f02e3a8908..af2598f69d 100644
--- a/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts
@@ -1,13 +1,11 @@
-import "../../../../components/ha-form/ha-form";
-import type { HassEntity } from "home-assistant-js-websocket";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { assert } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
import { computeDomain } from "../../../../common/entity/compute_domain";
-import { domainIcon } from "../../../../common/entity/domain_icon";
import type { LocalizeFunc } from "../../../../common/translations/localize";
+import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
import type { EntitiesCardEntityConfig } from "../../cards/types";
@@ -39,73 +37,56 @@ export class HuiGenericEntityRowEditor
this._config = config;
}
- private _schema = memoizeOne(
- (
- entity: string,
- icon: string | undefined,
- entityState: HassEntity,
- localize: LocalizeFunc
- ) => {
- const domain = computeDomain(entity);
+ private _schema = memoizeOne((entity: string, localize: LocalizeFunc) => {
+ const domain = computeDomain(entity);
- return [
- { name: "entity", required: true, selector: { entity: {} } },
- {
- type: "grid",
- name: "",
- schema: [
- { name: "name", selector: { text: {} } },
- {
- name: "icon",
- selector: {
- icon: {
- placeholder: icon || entityState?.attributes.icon,
- fallbackPath:
- !icon && !entityState?.attributes.icon && entityState
- ? domainIcon(domain, entityState)
- : undefined,
- },
- },
+ return [
+ { name: "entity", required: true, selector: { entity: {} } },
+ {
+ type: "grid",
+ name: "",
+ schema: [
+ { name: "name", selector: { text: {} } },
+ {
+ name: "icon",
+ selector: {
+ icon: {},
},
- ],
- },
- {
- name: "secondary_info",
- selector: {
- select: {
- options: (
- Object.keys(SecondaryInfoValues).filter(
- (info) =>
- !("domains" in SecondaryInfoValues[info]) ||
- ("domains" in SecondaryInfoValues[info] &&
- SecondaryInfoValues[info].domains!.includes(domain))
- ) as Array
- ).map((info) => ({
- value: info,
- label: localize(
- `ui.panel.lovelace.editor.card.entities.secondary_info_values.${info}`
- ),
- })),
+ context: {
+ icon_entity: "entity",
},
},
+ ],
+ },
+ {
+ name: "secondary_info",
+ selector: {
+ select: {
+ options: (
+ Object.keys(SecondaryInfoValues).filter(
+ (info) =>
+ !("domains" in SecondaryInfoValues[info]) ||
+ ("domains" in SecondaryInfoValues[info] &&
+ SecondaryInfoValues[info].domains!.includes(domain))
+ ) as Array
+ ).map((info) => ({
+ value: info,
+ label: localize(
+ `ui.panel.lovelace.editor.card.entities.secondary_info_values.${info}`
+ ),
+ })),
+ },
},
- ] as const;
- }
- );
+ },
+ ] as const;
+ });
protected render(): TemplateResult {
if (!this.hass || !this._config) {
return html``;
}
- const entityState = this.hass.states[this._config.entity];
-
- const schema = this._schema(
- this._config.entity,
- this._config.icon,
- entityState,
- this.hass.localize
- );
+ const schema = this._schema(this._config.entity, this.hass.localize);
return html`
- [
- {
- name: "entity",
- required: true,
- selector: { entity: { domain: "light" } },
- },
- {
- type: "grid",
- name: "",
- schema: [
- { name: "name", selector: { text: {} } },
- {
- name: "icon",
- selector: {
- icon: {
- placeholder: icon || entityState?.attributes.icon,
- fallbackPath:
- !icon && !entityState?.attributes.icon && entityState
- ? domainIcon(computeDomain(entity), entityState)
- : undefined,
- },
- },
- },
- ],
- },
- { name: "theme", selector: { theme: {} } },
- {
- name: "hold_action",
- selector: { "ui-action": {} },
- },
- {
- name: "double_tap_action",
- selector: { "ui-action": {} },
- },
- ] as const
- );
-
protected render(): TemplateResult {
if (!this.hass || !this._config) {
return html``;
}
- const entityState = this.hass.states[this._config.entity];
- const schema = this._schema(
- this._config.entity,
- this._config.icon,
- entityState
- );
-
return html`
@@ -108,9 +91,7 @@ export class HuiLightCardEditor
fireEvent(this, "config-changed", { config: ev.detail.value });
}
- private _computeLabelCallback = (
- schema: SchemaUnion>
- ) => {
+ private _computeLabelCallback = (schema: SchemaUnion) => {
switch (schema.name) {
case "theme":
case "hold_action":
diff --git a/src/panels/lovelace/editor/config-elements/hui-sensor-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-sensor-card-editor.ts
index d9c6d314a7..7f8d0b8dc3 100644
--- a/src/panels/lovelace/editor/config-elements/hui-sensor-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-sensor-card-editor.ts
@@ -1,7 +1,5 @@
-import type { HassEntity } from "home-assistant-js-websocket";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
-import memoizeOne from "memoize-one";
import {
assert,
assign,
@@ -13,8 +11,6 @@ import {
union,
} from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { computeDomain } from "../../../../common/entity/compute_domain";
-import { domainIcon } from "../../../../common/entity/domain_icon";
import { entityId } from "../../../../common/structs/is-entity-id";
import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
@@ -38,6 +34,55 @@ const cardConfigStruct = assign(
})
);
+const SCHEMA = [
+ {
+ name: "entity",
+ selector: {
+ entity: { domain: ["counter", "input_number", "number", "sensor"] },
+ },
+ },
+ { name: "name", selector: { text: {} } },
+ {
+ type: "grid",
+ name: "",
+ schema: [
+ {
+ name: "icon",
+ selector: {
+ icon: {},
+ },
+ context: {
+ icon_entity: "entity",
+ },
+ },
+ {
+ name: "graph",
+ selector: {
+ select: {
+ options: [
+ {
+ value: "none",
+ label: "None",
+ },
+ {
+ value: "line",
+ label: "Line",
+ },
+ ],
+ },
+ },
+ },
+ { name: "unit", selector: { text: {} } },
+ { name: "detail", selector: { boolean: {} } },
+ { name: "theme", selector: { theme: {} } },
+ {
+ name: "hours_to_show",
+ selector: { number: { min: 1, mode: "box" } },
+ },
+ ],
+ },
+] as const;
+
@customElement("hui-sensor-card-editor")
export class HuiSensorCardEditor
extends LitElement
@@ -52,74 +97,11 @@ export class HuiSensorCardEditor
this._config = config;
}
- private _schema = memoizeOne(
- (entity: string, icon: string | undefined, entityState: HassEntity) =>
- [
- {
- name: "entity",
- selector: {
- entity: { domain: ["counter", "input_number", "number", "sensor"] },
- },
- },
- { name: "name", selector: { text: {} } },
- {
- type: "grid",
- name: "",
- schema: [
- {
- name: "icon",
- selector: {
- icon: {
- placeholder: icon || entityState?.attributes.icon,
- fallbackPath:
- !icon && !entityState?.attributes.icon && entityState
- ? domainIcon(computeDomain(entity), entityState)
- : undefined,
- },
- },
- },
- {
- name: "graph",
- selector: {
- select: {
- options: [
- {
- value: "none",
- label: "None",
- },
- {
- value: "line",
- label: "Line",
- },
- ],
- },
- },
- },
- { name: "unit", selector: { text: {} } },
- { name: "detail", selector: { boolean: {} } },
- { name: "theme", selector: { theme: {} } },
- {
- name: "hours_to_show",
- selector: { number: { min: 1, mode: "box" } },
- },
- ],
- },
- ] as const
- );
-
protected render(): TemplateResult {
if (!this.hass || !this._config) {
return html``;
}
- const entityState = this.hass.states[this._config.entity];
-
- const schema = this._schema(
- this._config.entity,
- this._config.icon,
- entityState
- );
-
const data = {
hours_to_show: 24,
graph: "none",
@@ -131,7 +113,7 @@ export class HuiSensorCardEditor
@@ -144,9 +126,7 @@ export class HuiSensorCardEditor
fireEvent(this, "config-changed", { config });
}
- private _computeLabelCallback = (
- schema: SchemaUnion>
- ) => {
+ private _computeLabelCallback = (schema: SchemaUnion) => {
switch (schema.name) {
case "theme":
return `${this.hass!.localize(
diff --git a/src/panels/lovelace/editor/config-elements/hui-statistic-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-statistic-card-editor.ts
index aa89edb420..03e58aecc0 100644
--- a/src/panels/lovelace/editor/config-elements/hui-statistic-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-statistic-card-editor.ts
@@ -1,11 +1,8 @@
-import type { HassEntity } from "home-assistant-js-websocket/dist/types";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { any, assert, assign, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { computeDomain } from "../../../../common/entity/compute_domain";
-import { domainIcon } from "../../../../common/entity/domain_icon";
import { LocalizeFunc } from "../../../../common/translations/localize";
import { deepEqual } from "../../../../common/util/deep-equal";
import "../../../../components/ha-form/ha-form";
@@ -100,10 +97,7 @@ export class HuiStatisticCardEditor
private _schema = memoizeOne(
(
- entity: string,
- icon: string,
selectedPeriodKey: string | undefined,
- entityState: HassEntity,
localize: LocalizeFunc,
metadata?: StatisticsMetaData
) =>
@@ -155,13 +149,10 @@ export class HuiStatisticCardEditor
{
name: "icon",
selector: {
- icon: {
- placeholder: icon || entityState?.attributes.icon,
- fallbackPath:
- !icon && !entityState?.attributes.icon && entityState
- ? domainIcon(computeDomain(entity), entityState)
- : undefined,
- },
+ icon: {},
+ },
+ context: {
+ icon_entity: "entity",
},
},
{ name: "unit", selector: { text: {} } },
@@ -176,15 +167,10 @@ export class HuiStatisticCardEditor
return html``;
}
- const entityState = this.hass.states[this._config.entity];
-
const data = this._data(this._config);
const schema = this._schema(
- this._config.entity,
- this._config.icon,
typeof data.period === "string" ? data.period : undefined,
- entityState,
this.hass.localize,
this._metadata
);
diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
index d62f0e071e..348ace3f33 100644
--- a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
@@ -14,9 +14,8 @@ import {
string,
} from "superstruct";
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
-import { computeDomain } from "../../../../common/entity/compute_domain";
-import { domainIcon } from "../../../../common/entity/domain_icon";
import { entityId } from "../../../../common/structs/is-entity-id";
+import { LocalizeFunc } from "../../../../common/translations/localize";
import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
@@ -65,16 +64,14 @@ export class HuiTileCardEditor
}
private _schema = memoizeOne(
- (entity: string, icon?: string, stateObj?: HassEntity) =>
+ (localize: LocalizeFunc) =>
[
{ name: "entity", selector: { entity: {} } },
{
name: "",
type: "expandable",
iconPath: mdiPalette,
- title: this.hass!.localize(
- `ui.panel.lovelace.editor.card.tile.appearance`
- ),
+ title: localize(`ui.panel.lovelace.editor.card.tile.appearance`),
schema: [
{
name: "",
@@ -84,14 +81,9 @@ export class HuiTileCardEditor
{
name: "icon",
selector: {
- icon: {
- placeholder: icon || stateObj?.attributes.icon,
- fallbackPath:
- !icon && !stateObj?.attributes.icon && stateObj
- ? domainIcon(computeDomain(entity), stateObj)
- : undefined,
- },
+ icon: {},
},
+ context: { icon_entity: "entity" },
},
{
name: "color",
@@ -118,9 +110,7 @@ export class HuiTileCardEditor
{
name: "",
type: "expandable",
- title: this.hass!.localize(
- `ui.panel.lovelace.editor.card.tile.actions`
- ),
+ title: localize(`ui.panel.lovelace.editor.card.tile.actions`),
iconPath: mdiGestureTap,
schema: [
{
@@ -153,11 +143,7 @@ export class HuiTileCardEditor
| HassEntity
| undefined;
- const schema = this._schema(
- this._config.entity,
- this._config.icon,
- stateObj
- );
+ const schema = this._schema(this.hass!.localize);
if (this._subElementEditorConfig) {
return html`