diff --git a/src/components/entity/ha-entity-picker.ts b/src/components/entity/ha-entity-picker.ts index 397685a32b..5968b4a103 100644 --- a/src/components/entity/ha-entity-picker.ts +++ b/src/components/entity/ha-entity-picker.ts @@ -317,6 +317,7 @@ export class HaEntityPicker extends LitElement { const secondary = [areaName, entityName ? deviceName : undefined] .filter(Boolean) .join(isRTL ? " ◂ " : " ▸ "); + const a11yLabel = [deviceName, entityName].filter(Boolean).join(" - "); return { id: entityId, @@ -332,6 +333,7 @@ export class HaEntityPicker extends LitElement { friendlyName, entityId, ].filter(Boolean) as string[], + a11y_label: a11yLabel, stateObj: stateObj, }; }); diff --git a/src/components/entity/ha-statistic-picker.ts b/src/components/entity/ha-statistic-picker.ts index 3b6e262fc3..955071a8f2 100644 --- a/src/components/entity/ha-statistic-picker.ts +++ b/src/components/entity/ha-statistic-picker.ts @@ -267,6 +267,7 @@ export class HaStatisticPicker extends LitElement { const secondary = [areaName, entityName ? deviceName : undefined] .filter(Boolean) .join(isRTL ? " ◂ " : " ▸ "); + const a11yLabel = [deviceName, entityName].filter(Boolean).join(" - "); const sortingPrefix = `${TYPE_ORDER.indexOf("entity")}`; output.push({ @@ -274,6 +275,7 @@ export class HaStatisticPicker extends LitElement { statistic_id: id, primary, secondary, + a11y_label: a11yLabel, stateObj: stateObj, type: "entity", sorting_label: [sortingPrefix, deviceName, entityName].join("_"), diff --git a/src/components/ha-combo-box-textfield.ts b/src/components/ha-combo-box-textfield.ts new file mode 100644 index 0000000000..19c87f268c --- /dev/null +++ b/src/components/ha-combo-box-textfield.ts @@ -0,0 +1,24 @@ +import type { PropertyValues } from "lit"; +import { customElement, property } from "lit/decorators"; +import { HaTextField } from "./ha-textfield"; + +@customElement("ha-combo-box-textfield") +export class HaComboBoxTextField extends HaTextField { + @property({ type: Boolean, attribute: "disable-set-value" }) + public disableSetValue = false; + + protected willUpdate(changedProps: PropertyValues): void { + super.willUpdate(changedProps); + if (changedProps.has("value")) { + if (this.disableSetValue) { + this.value = changedProps.get("value") as string; + } + } + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-combo-box-textfield": HaComboBoxTextField; + } +} diff --git a/src/components/ha-combo-box.ts b/src/components/ha-combo-box.ts index 9804ebe774..58ed2e1f51 100644 --- a/src/components/ha-combo-box.ts +++ b/src/components/ha-combo-box.ts @@ -12,11 +12,12 @@ import type { import { registerStyles } from "@vaadin/vaadin-themable-mixin/register-styles"; import type { TemplateResult } from "lit"; import { css, html, LitElement } from "lit"; -import { customElement, property, query } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; import { fireEvent } from "../common/dom/fire_event"; import type { HomeAssistant } from "../types"; import "./ha-combo-box-item"; +import "./ha-combo-box-textfield"; import "./ha-icon-button"; import "./ha-textfield"; import type { HaTextField } from "./ha-textfield"; @@ -108,9 +109,14 @@ export class HaComboBox extends LitElement { @property({ type: Boolean, attribute: "hide-clear-icon" }) public hideClearIcon = false; + @property({ type: Boolean, attribute: "clear-initial-value" }) + public clearInitialValue = false; + @query("vaadin-combo-box-light", true) private _comboBox!: ComboBoxLight; - @query("ha-textfield", true) private _inputElement!: HaTextField; + @query("ha-combo-box-textfield", true) private _inputElement!: HaTextField; + + @state({ type: Boolean }) private _disableSetValue = false; private _overlayMutationObserver?: MutationObserver; @@ -171,7 +177,7 @@ export class HaComboBox extends LitElement { @value-changed=${this._valueChanged} attr-for-value="value" > - - + ${this.value && !this.hideClearIcon ? html` { + this._disableSetValue = false; + }, 100); + } else { + this._disableSetValue = true; + } + } + if (opened) { const overlay = document.querySelector( "vaadin-combo-box-overlay" @@ -342,10 +361,10 @@ export class HaComboBox extends LitElement { position: relative; --vaadin-combo-box-overlay-max-height: calc(45vh - 56px); } - ha-textfield { + ha-combo-box-textfield { width: 100%; } - ha-textfield > ha-icon-button { + ha-combo-box-textfield > ha-icon-button { --mdc-icon-button-size: 24px; padding: 2px; color: var(--secondary-text-color); diff --git a/src/components/ha-generic-picker.ts b/src/components/ha-generic-picker.ts index 38ba4487b1..2c699382fd 100644 --- a/src/components/ha-generic-picker.ts +++ b/src/components/ha-generic-picker.ts @@ -2,6 +2,7 @@ import type { ComboBoxLitRenderer } from "@vaadin/combo-box/lit"; import type { ComboBoxLightOpenedChangedEvent } from "@vaadin/combo-box/vaadin-combo-box-light"; import { css, html, LitElement, nothing, type CSSResultGroup } from "lit"; import { customElement, property, query, state } from "lit/decorators"; +import { ifDefined } from "lit/directives/if-defined"; import { fireEvent } from "../common/dom/fire_event"; import type { HomeAssistant } from "../types"; import "./ha-combo-box-item"; @@ -74,6 +75,7 @@ export class HaGenericPicker extends LitElement { ((item) => ({ ...item, - label: "", + a11y_label: item.a11y_label || item.primary, })); }; @@ -128,7 +129,7 @@ export class HaPickerComboBox extends LitElement { const sortedItems = items .map((item) => ({ ...item, - label: "", + a11y_label: item.a11y_label || item.primary, })) .sort((entityA, entityB) => caseInsensitiveStringCompare( @@ -175,7 +176,8 @@ export class HaPickerComboBox extends LitElement {