diff --git a/src/panels/lovelace/editor/config-elements/hui-climate-preset-modes-tile-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-climate-preset-modes-tile-feature-editor.ts new file mode 100644 index 000000000000..a2fa83907143 --- /dev/null +++ b/src/panels/lovelace/editor/config-elements/hui-climate-preset-modes-tile-feature-editor.ts @@ -0,0 +1,101 @@ +import { html, LitElement, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../../../../common/dom/fire_event"; +import { LocalizeFunc } from "../../../../common/translations/localize"; +import "../../../../components/ha-form/ha-form"; +import type { + HaFormSchema, + SchemaUnion, +} from "../../../../components/ha-form/types"; +import type { HomeAssistant } from "../../../../types"; +import { + ClimatePresetModesTileFeatureConfig, + LovelaceTileFeatureContext, +} from "../../tile-features/types"; +import type { LovelaceTileFeatureEditor } from "../../types"; + +@customElement("hui-climate-preset-modes-tile-feature-editor") +export class HuiClimatePresetModesTileFeatureEditor + extends LitElement + implements LovelaceTileFeatureEditor +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public context?: LovelaceTileFeatureContext; + + @state() private _config?: ClimatePresetModesTileFeatureConfig; + + public setConfig(config: ClimatePresetModesTileFeatureConfig): void { + this._config = config; + } + + private _schema = memoizeOne( + (localize: LocalizeFunc) => + [ + { + name: "style", + selector: { + select: { + multiple: false, + mode: "list", + options: ["dropdown", "icons"].map((mode) => ({ + value: mode, + label: localize( + `ui.panel.lovelace.editor.card.tile.features.types.climate-preset-modes.style_list.${mode}` + ), + })), + }, + }, + }, + ] as const satisfies readonly HaFormSchema[] + ); + + protected render() { + if (!this.hass || !this._config) { + return nothing; + } + + const data: ClimatePresetModesTileFeatureConfig = { + style: "dropdown", + ...this._config, + }; + + const schema = this._schema(this.hass.localize); + + return html` + + `; + } + + private _valueChanged(ev: CustomEvent): void { + fireEvent(this, "config-changed", { config: ev.detail.value }); + } + + private _computeLabelCallback = ( + schema: SchemaUnion> + ) => { + switch (schema.name) { + case "style": + return this.hass!.localize( + `ui.panel.lovelace.editor.card.tile.features.types.climate-preset-modes.${schema.name}` + ); + default: + return this.hass!.localize( + `ui.panel.lovelace.editor.card.generic.${schema.name}` + ); + } + }; +} + +declare global { + interface HTMLElementTagNameMap { + "hui-climate-preset-modes-tile-feature-editor": HuiClimatePresetModesTileFeatureEditor; + } +} diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts index 0d4c0ed9f9c8..9498dcbe73f2 100644 --- a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts @@ -72,6 +72,7 @@ const EDITABLES_FEATURE_TYPES = new Set([ "climate-hvac-modes", "water-heater-operation-modes", "lawn-mower-commands", + "climate-preset-modes", ]); const SUPPORTS_FEATURE_TYPES: Record< diff --git a/src/panels/lovelace/tile-features/hui-climate-preset-modes-tile-feature.ts b/src/panels/lovelace/tile-features/hui-climate-preset-modes-tile-feature.ts index 62edbddf8d42..485986dcd413 100644 --- a/src/panels/lovelace/tile-features/hui-climate-preset-modes-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-climate-preset-modes-tile-feature.ts @@ -5,6 +5,8 @@ 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-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 { @@ -14,7 +16,7 @@ import { } from "../../../data/climate"; import { UNAVAILABLE } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; -import { LovelaceTileFeature } from "../types"; +import { LovelaceTileFeature, LovelaceTileFeatureEditor } from "../types"; import { ClimatePresetModesTileFeatureConfig } from "./types"; export const supportsClimatePresetModesTileFeature = (stateObj: HassEntity) => { @@ -39,7 +41,7 @@ class HuiClimatePresetModeTileFeature @state() _currentPresetMode?: string; @query("ha-control-select-menu", true) - private _haSelect!: HaControlSelectMenu; + private _haSelect?: HaControlSelectMenu; static getStubConfig(): ClimatePresetModesTileFeatureConfig { return { @@ -47,6 +49,15 @@ class HuiClimatePresetModeTileFeature }; } + public static async getConfigElement(): Promise { + await import( + "../editor/config-elements/hui-climate-preset-modes-tile-feature-editor" + ); + return document.createElement( + "hui-climate-preset-modes-tile-feature-editor" + ); + } + public setConfig(config: ClimatePresetModesTileFeatureConfig): void { if (!config) { throw new Error("Invalid configuration"); @@ -63,7 +74,7 @@ class HuiClimatePresetModeTileFeature protected updated(changedProps: PropertyValues) { super.updated(changedProps); - if (changedProps.has("hass")) { + if (this._haSelect && changedProps.has("hass")) { const oldHass = changedProps.get("hass") as HomeAssistant | undefined; if ( this.hass && @@ -76,7 +87,8 @@ class HuiClimatePresetModeTileFeature } private async _valueChanged(ev: CustomEvent) { - const presetMode = (ev.target as any).value as string; + const presetMode = + (ev.detail as any).value ?? ((ev.target as any).value as string); const oldPresetMode = this.stateObj!.attributes.preset_mode; @@ -110,6 +122,37 @@ class HuiClimatePresetModeTileFeature const stateObj = this.stateObj; + const modes = stateObj.attributes.preset_modes || []; + + const options = modes.map((mode) => ({ + value: mode, + label: this.hass!.formatEntityAttributeValue( + this.stateObj!, + "preset_mode", + mode + ), + path: computePresetModeIcon(mode), + })); + + if (this._config.style === "icons") { + return html` +
+ + +
+ `; + } + return html`
- ${stateObj.attributes.preset_modes?.map( - (mode) => html` - - - ${this.hass!.formatEntityAttributeValue( - stateObj, - "preset_mode", - mode - )} + ${options.map( + (option) => html` + + + ${option.label} ` )} @@ -157,6 +193,13 @@ class HuiClimatePresetModeTileFeature display: block; width: 100%; } + ha-control-select { + --control-select-color: var(--tile-color); + --control-select-padding: 0; + --control-select-thickness: 40px; + --control-select-border-radius: 10px; + --control-select-button-border-radius: 10px; + } .container { padding: 0 12px 12px 12px; width: auto; diff --git a/src/panels/lovelace/tile-features/types.ts b/src/panels/lovelace/tile-features/types.ts index 6f103b604011..981cfd1d6d36 100644 --- a/src/panels/lovelace/tile-features/types.ts +++ b/src/panels/lovelace/tile-features/types.ts @@ -42,6 +42,7 @@ export interface ClimateHvacModesTileFeatureConfig { export interface ClimatePresetModesTileFeatureConfig { type: "climate-preset-modes"; + style?: "dropdown" | "icons"; } export interface SelectOptionsTileFeatureConfig { diff --git a/src/translations/en.json b/src/translations/en.json index ce8d3b062c5c..533369f88b93 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -5039,7 +5039,12 @@ "hvac_modes": "HVAC modes" }, "climate-preset-modes": { - "label": "Climate preset modes" + "label": "Climate preset modes", + "style": "Style", + "style_list": { + "dropdown": "Dropdown", + "icons": "Icons" + } }, "target-temperature": { "label": "Target temperature" @@ -5142,7 +5147,8 @@ "types": { "header": "Header editor", "footer": "Footer editor", - "row": "Entity row editor" + "row": "Entity row editor", + "tile-feature": "Tile feature editor" } } },