Implement more attribute icons (#19469)

This commit is contained in:
Bram Kragten 2024-01-19 20:55:16 +01:00 committed by GitHub
parent 77dd2a87d9
commit 646c02d855
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 166 additions and 51 deletions

View File

@ -2,7 +2,7 @@ export default {
"*.?(c|m){js,ts}": [
"eslint --cache --cache-strategy=content --cache-location=node_modules/.cache/eslint/.eslintcache --fix",
"prettier --cache --write",
"lit-analyzer",
"lit-analyzer --quiet",
],
"*.{json,css,md,markdown,html,y?aml}": "prettier --cache --write",
"translations/*/*.json": (files) =>

View File

@ -1,4 +1,5 @@
/** Return an icon representing a attribute. */
import { mdiCircleMedium, mdiCreation } from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket";
import {
computeFanModeIcon,
@ -6,6 +7,7 @@ import {
computePresetModeIcon,
computeSwingModeIcon,
} from "../../data/climate";
import { computeHumidiferModeIcon } from "../../data/humidifier";
import { computeDomain } from "./compute_domain";
const iconGenerators: Record<string, Record<string, (value: any) => string>> = {
@ -15,6 +17,15 @@ const iconGenerators: Record<string, Record<string, (value: any) => string>> = {
preset_mode: computePresetModeIcon,
swing_mode: computeSwingModeIcon,
},
humidifier: {
mode: computeHumidiferModeIcon,
},
light: {
effect: () => mdiCreation,
},
fan: {
preset_mode: () => mdiCircleMedium,
},
};
export const attributeIconPath = (

View File

@ -5,6 +5,7 @@ import {
LitElement,
nothing,
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
@ -17,7 +18,7 @@ import "./ha-svg-icon";
export type ControlSelectOption = {
value: string;
label?: string;
icon?: string;
icon?: TemplateResult;
path?: string;
};
@ -25,7 +26,7 @@ export type ControlSelectOption = {
export class HaControlSelect extends LitElement {
@property({ type: Boolean, reflect: true }) disabled = false;
@property() public options?: ControlSelectOption[];
@property({ attribute: false }) public options?: ControlSelectOption[];
@property() public value?: string;
@ -183,9 +184,7 @@ export class HaControlSelect extends LitElement {
<div class="content">
${option.path
? html`<ha-svg-icon .path=${option.path}></ha-svg-icon>`
: option.icon
? html`<ha-icon .icon=${option.icon}></ha-icon> `
: nothing}
: option.icon || nothing}
${option.label && !this.hideLabel
? html`<span>${option.label}</span>`
: nothing}

View File

@ -14,6 +14,7 @@ import { stopPropagation } from "../../../common/dom/stop_propagation";
import { stateActive } from "../../../common/entity/state_active";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-control-select-menu";
import "../../../components/ha-attribute-icon";
import "../../../components/ha-list-item";
import "../../../components/ha-outlined-icon-button";
import { UNAVAILABLE } from "../../../data/entity";
@ -187,10 +188,30 @@ class MoreInfoFan extends LitElement {
@selected=${this._handlePresetMode}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
${this.stateObj.attributes.preset_mode
? html`<ha-attribute-icon
slot="icon"
.hass=${this.hass}
.stateObj=${this.stateObj}
attribute="preset_mode"
.attributeValue=${this.stateObj.attributes.preset_mode}
></ha-attribute-icon>`
: html`
<ha-svg-icon
slot="icon"
.path=${mdiTuneVariant}
></ha-svg-icon>
`}
${this.stateObj.attributes.preset_modes?.map(
(mode) => html`
<ha-list-item .value=${mode}>
<ha-list-item .value=${mode} graphic="icon">
<ha-attribute-icon
slot="graphic"
.hass=${this.hass}
.stateObj=${this.stateObj}
attribute="preset_mode"
.attributeValue=${mode}
></ha-attribute-icon>
${this.hass.formatEntityAttributeValue(
this.stateObj!,
"preset_mode",

View File

@ -12,11 +12,11 @@ import { stopPropagation } from "../../../common/dom/stop_propagation";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-control-select-menu";
import "../../../components/ha-list-item";
import "../../../components/ha-attribute-icon";
import { UNAVAILABLE } from "../../../data/entity";
import {
HumidifierEntity,
HumidifierEntityFeature,
computeHumidiferModeIcon,
} from "../../../data/humidifier";
import "../../../state-control/humidifier/ha-state-control-humidifier-humidity";
import { HomeAssistant } from "../../../types";
@ -109,14 +109,28 @@ class MoreInfoHumidifier extends LitElement {
@selected=${this._handleModeChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
${stateObj.attributes.mode
? html`<ha-attribute-icon
slot="icon"
.hass=${this.hass}
.stateObj=${stateObj}
attribute="mode"
.attributeValue=${stateObj.attributes.mode}
></ha-attribute-icon>`
: html`<ha-svg-icon
slot="icon"
.path=${mdiTuneVariant}
></ha-svg-icon>`}
${stateObj.attributes.available_modes!.map(
(mode) => html`
<ha-list-item .value=${mode} graphic="icon">
<ha-svg-icon
<ha-attribute-icon
slot="graphic"
.path=${computeHumidiferModeIcon(mode)}
></ha-svg-icon>
.hass=${this.hass}
.stateObj=${stateObj}
attribute="mode"
.attributeValue=${mode}
></ha-attribute-icon>
${this.hass.formatEntityAttributeValue(
stateObj!,
"mode",

View File

@ -19,6 +19,7 @@ import { customElement, property, state } from "lit/decorators";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-attributes";
import "../../../components/ha-attribute-icon";
import "../../../components/ha-control-select-menu";
import "../../../components/ha-icon-button-group";
import "../../../components/ha-icon-button-toggle";
@ -271,10 +272,28 @@ class MoreInfoLight extends LitElement {
@selected=${this._handleEffect}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiCreation}></ha-svg-icon>
${this.stateObj.attributes.effect
? html`<ha-attribute-icon
slot="icon"
.hass=${this.hass}
.stateObj=${this.stateObj}
attribute="effect"
.attributeValue=${this.stateObj.attributes.effect}
></ha-attribute-icon>`
: html`<ha-svg-icon
slot="icon"
.path=${mdiCreation}
></ha-svg-icon>`}
${this.stateObj.attributes.effect_list?.map(
(mode) => html`
<ha-list-item .value=${mode}>
<ha-list-item .value=${mode} graphic="icon">
<ha-attribute-icon
slot="graphic"
.hass=${this.hass}
.stateObj=${this.stateObj}
attribute="effect"
.attributeValue=${mode}
></ha-attribute-icon>
${this.hass.formatEntityAttributeValue(
this.stateObj!,
"effect",

View File

@ -5,15 +5,12 @@ import { customElement, property, query, state } from "lit/decorators";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeDomain } from "../../../common/entity/compute_domain";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-attribute-icon";
import "../../../components/ha-control-select";
import type { ControlSelectOption } from "../../../components/ha-control-select";
import "../../../components/ha-control-select-menu";
import type { HaControlSelectMenu } from "../../../components/ha-control-select-menu";
import {
ClimateEntity,
ClimateEntityFeature,
computeFanModeIcon,
} from "../../../data/climate";
import { ClimateEntity, ClimateEntityFeature } from "../../../data/climate";
import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
@ -136,7 +133,13 @@ class HuiClimateFanModesCardFeature
"fan_mode",
mode
),
path: computeFanModeIcon(mode),
icon: html`<ha-attribute-icon
slot="graphic"
.hass=${this.hass}
.stateObj=${stateObj}
attribute="fan_mode"
.attributeValue=${mode}
></ha-attribute-icon>`,
}));
if (this._config.style === "icons") {
@ -171,12 +174,19 @@ class HuiClimateFanModesCardFeature
@selected=${this._valueChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiFan}></ha-svg-icon>
${this._currentFanMode
? html`<ha-attribute-icon
slot="icon"
.hass=${this.hass}
.stateObj=${stateObj}
attribute="fan_mode"
.attributeValue=${this._currentFanMode}
></ha-attribute-icon>`
: html` <ha-svg-icon slot="icon" .path=${mdiFan}></ha-svg-icon>`}
${options.map(
(option) => html`
<ha-list-item .value=${option.value} graphic="icon">
<ha-svg-icon slot="graphic" .path=${option.path}></ha-svg-icon>
${option.label}
${option.icon}${option.label}
</ha-list-item>
`
)}

View File

@ -6,14 +6,14 @@ import { styleMap } from "lit/directives/style-map";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeDomain } from "../../../common/entity/compute_domain";
import { stateColorCss } from "../../../common/entity/state_color";
import "../../../components/ha-attribute-icon";
import "../../../components/ha-control-select";
import "../../../components/ha-control-select-menu";
import type { ControlSelectOption } from "../../../components/ha-control-select";
import "../../../components/ha-control-select-menu";
import type { HaControlSelectMenu } from "../../../components/ha-control-select-menu";
import {
ClimateEntity,
compareClimateHvacModes,
computeHvacModeIcon,
HvacMode,
} from "../../../data/climate";
import { UNAVAILABLE } from "../../../data/entity";
@ -130,7 +130,13 @@ class HuiClimateHvacModesCardFeature
.map<ControlSelectOption>((mode) => ({
value: mode,
label: this.hass!.formatEntityState(this.stateObj!, mode),
path: computeHvacModeIcon(mode),
icon: html`<ha-attribute-icon
slot="graphic"
.hass=${this.hass}
.stateObj=${this.stateObj}
attribute="hvac_mode"
.attributeValue=${mode}
></ha-attribute-icon>`,
}));
if (this._config.style === "dropdown") {
@ -147,15 +153,22 @@ class HuiClimateHvacModesCardFeature
@selected=${this._valueChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiThermostat}></ha-svg-icon>
${this._currentHvacMode
? html`<ha-attribute-icon
slot="icon"
.hass=${this.hass}
.stateObj=${this.stateObj}
attribute="hvac_mode"
.attributeValue=${this._currentHvacMode}
></ha-attribute-icon>`
: html`<ha-svg-icon
slot="icon"
.path=${mdiThermostat}
></ha-svg-icon>`}
${options.map(
(option) => html`
<ha-list-item .value=${option.value} graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${option.path}
></ha-svg-icon>
${option.label}
${option.icon}${option.label}
</ha-list-item>
`
)}

View File

@ -5,15 +5,12 @@ import { customElement, property, query, state } from "lit/decorators";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeDomain } from "../../../common/entity/compute_domain";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-attribute-icon";
import "../../../components/ha-control-select";
import type { ControlSelectOption } from "../../../components/ha-control-select";
import "../../../components/ha-control-select-menu";
import type { HaControlSelectMenu } from "../../../components/ha-control-select-menu";
import {
ClimateEntity,
ClimateEntityFeature,
computePresetModeIcon,
} from "../../../data/climate";
import { ClimateEntity, ClimateEntityFeature } from "../../../data/climate";
import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
@ -138,7 +135,13 @@ class HuiClimatePresetModesCardFeature
"preset_mode",
mode
),
path: computePresetModeIcon(mode),
icon: html`<ha-attribute-icon
slot="graphic"
.hass=${this.hass}
.stateObj=${stateObj}
attribute="preset_mode"
.attributeValue=${mode}
></ha-attribute-icon>`,
}));
if (this._config.style === "icons") {
@ -176,12 +179,21 @@ class HuiClimatePresetModesCardFeature
@selected=${this._valueChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
${this._currentPresetMode
? html`<ha-attribute-icon
slot="icon"
.hass=${this.hass}
.stateObj=${stateObj}
attribute="preset_mode"
.attributeValue=${this._currentPresetMode}
></ha-attribute-icon>`
: html`
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
`}
${options.map(
(option) => html`
<ha-list-item .value=${option.value} graphic="icon">
<ha-svg-icon slot="graphic" .path=${option.path}></ha-svg-icon>
${option.label}
${option.icon}${option.label}
</ha-list-item>
`
)}

View File

@ -5,16 +5,16 @@ import { customElement, property, query, state } from "lit/decorators";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeDomain } from "../../../common/entity/compute_domain";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-attribute-icon";
import "../../../components/ha-control-select";
import type { ControlSelectOption } from "../../../components/ha-control-select";
import "../../../components/ha-control-select-menu";
import type { HaControlSelectMenu } from "../../../components/ha-control-select-menu";
import {
HumidifierEntityFeature,
HumidifierEntity,
computeHumidiferModeIcon,
} from "../../../data/humidifier";
import { UNAVAILABLE } from "../../../data/entity";
import {
HumidifierEntity,
HumidifierEntityFeature,
} from "../../../data/humidifier";
import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { HumidifierModesCardFeatureConfig } from "./types";
@ -136,7 +136,13 @@ class HuiHumidifierModesCardFeature
"mode",
mode
),
path: computeHumidiferModeIcon(mode),
icon: html`<ha-attribute-icon
slot="graphic"
.hass=${this.hass}
.stateObj=${stateObj}
attribute="mode"
.attributeValue=${mode}
></ha-attribute-icon>`,
}));
if (this._config.style === "icons") {
@ -168,12 +174,22 @@ class HuiHumidifierModesCardFeature
@selected=${this._valueChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
${this._currentMode
? html`<ha-attribute-icon
slot="icon"
.hass=${this.hass}
.stateObj=${stateObj}
attribute="mode"
.attributeValue=${this._currentMode}
></ha-attribute-icon>`
: html`<ha-svg-icon
slot="icon"
.path=${mdiTuneVariant}
></ha-svg-icon>`}
${options.map(
(option) => html`
<ha-list-item .value=${option.value} graphic="icon">
<ha-svg-icon slot="graphic" .path=${option.path}></ha-svg-icon>
${option.label}
${option.icon}${option.label}
</ha-list-item>
`
)}