From aec4a061568dc408a212015d2bcc464134f61c80 Mon Sep 17 00:00:00 2001
From: Wendelin <12148533+wendevlin@users.noreply.github.com>
Date: Wed, 4 Feb 2026 14:47:15 +0100
Subject: [PATCH] migrate ha-select to ha-dropdown (#29392)
* migrate ha-select to ha-dropdown
* remove ha-menu
* review
* Fix eslint error
---------
Co-authored-by: Aidan Timson
---
landing-page/src/ha-landing-page.ts | 1 -
package.json | 1 -
src/auth/ha-authorize.ts | 1 -
src/components/ha-assist-pipeline-picker.ts | 68 ++--
src/components/ha-base-time-input.ts | 20 +-
src/components/ha-blueprint-picker.ts | 22 +-
.../ha-conversation-agent-picker.ts | 56 ++-
src/components/ha-language-picker.ts | 3 -
src/components/ha-menu.ts | 45 ---
src/components/ha-mount-picker.ts | 97 +++--
src/components/ha-select.ts | 338 +++++++++--------
.../ha-selector/ha-selector-select.ts | 20 +-
src/components/ha-settings-row.ts | 1 +
src/components/ha-stt-picker.ts | 69 ++--
src/components/ha-theme-picker.ts | 58 ++-
src/components/ha-tts-picker.ts | 69 ++--
src/components/ha-tts-voice-picker.ts | 61 ++-
.../previews/entity-preview-row.ts | 15 +-
.../ha-more-info-siren-advanced-controls.ts | 34 +-
.../more-info/controls/more-info-remote.ts | 30 +-
.../more-info/controls/more-info-vacuum.ts | 30 +-
.../voice-assistant-setup-step-check.ts | 4 +-
.../voice-assistant-setup-step-success.ts | 50 +--
src/onboarding/ha-onboarding.ts | 1 -
.../calendar/ha-recurrence-rule-editor.ts | 105 ++----
.../app-view/config/supervisor-app-audio.ts | 41 +-
.../types/ha-automation-action-condition.ts | 61 +--
.../types/ha-automation-trigger-tag.ts | 22 +-
.../config/cloud/account/cloud-tts-pref.ts | 35 +-
.../cloud/account/dialog-cloud-tts-try.ts | 57 ++-
.../dialog-energy-device-settings-water.ts | 54 ++-
.../dialogs/dialog-energy-device-settings.ts | 56 +--
.../entity-registry-settings-editor.ts | 355 +++++++++---------
.../mqtt/mqtt-config-panel.ts | 21 +-
.../mqtt/mqtt-subscribe-card.ts | 19 +-
.../zha/dialog-zha-change-channel.ts | 28 +-
.../zha/zha-cluster-attributes.ts | 26 +-
.../zha/zha-cluster-commands.ts | 20 +-
.../zha/zha-device-binding.ts | 25 +-
.../zha/zha-group-binding.ts | 22 +-
.../zha/zha-manage-clusters.ts | 20 +-
.../zwave_js-capability-control-door-lock.ts | 41 +-
...js-capability-control-multilevel-switch.ts | 44 ++-
...s-capability-control-thermostat-setback.ts | 71 ++--
.../zwave_js/zwave_js-custom-param.ts | 73 ++--
.../zwave_js/zwave_js-logs.ts | 22 +-
.../zwave_js/zwave_js-node-config.ts | 19 +-
.../config/storage/dialog-move-datadisk.ts | 40 +-
.../lovelace/components/hui-action-editor.ts | 66 ++--
.../hui-picture-elements-card-row-editor.ts | 55 ++-
.../select-view/hui-dialog-select-view.ts | 42 +--
.../hui-input-select-entity-row.ts | 15 +-
.../entity-rows/hui-select-entity-row.ts | 33 +-
src/panels/profile/ha-pick-dashboard-row.ts | 59 ++-
src/panels/profile/ha-pick-date-format-row.ts | 36 +-
.../profile/ha-pick-first-weekday-row.ts | 58 +--
.../profile/ha-pick-number-format-row.ts | 49 +--
src/panels/profile/ha-pick-theme-row.ts | 45 +--
src/panels/profile/ha-pick-time-format-row.ts | 36 +-
src/panels/profile/ha-pick-time-zone-row.ts | 49 +--
src/state-summary/state-card-input_select.ts | 2 +-
src/state-summary/state-card-select.ts | 2 +-
src/state/translations-mixin.ts | 20 +-
yarn.lock | 3 +-
64 files changed, 1339 insertions(+), 1602 deletions(-)
delete mode 100644 src/components/ha-menu.ts
diff --git a/landing-page/src/ha-landing-page.ts b/landing-page/src/ha-landing-page.ts
index b1d64b02e5..d7a6434e16 100644
--- a/landing-page/src/ha-landing-page.ts
+++ b/landing-page/src/ha-landing-page.ts
@@ -100,7 +100,6 @@ class HaLandingPage extends LandingPageBaseElement {
button-style
native-name
@value-changed=${this._languageChanged}
- inline-arrow
>
pipeline.id === this._preferredPipeline
+ )?.name,
+ }),
+ },
+ ];
+
+ if (this.includeLastUsed) {
+ options.unshift({
+ value: LAST_USED,
+ label: this.hass.localize("ui.components.pipeline-picker.last_used"),
+ });
+ }
+
+ options.push(
+ ...this._pipelines.map((pipeline) => ({
+ value: pipeline.id,
+ label: `${pipeline.name} (${formatLanguageCode(pipeline.language, this.hass.locale)})`,
+ }))
+ );
+
return html`
- ${this.includeLastUsed
- ? html`
-
- ${this.hass!.localize(
- "ui.components.pipeline-picker.last_used"
- )}
-
- `
- : null}
-
- ${this.hass!.localize("ui.components.pipeline-picker.preferred", {
- preferred: this._pipelines.find(
- (pipeline) => pipeline.id === this._preferredPipeline
- )?.name,
- })}
-
- ${this._pipelines.map(
- (pipeline) =>
- html`
- ${pipeline.name}
- (${formatLanguageCode(pipeline.language, this.hass.locale)})
- `
- )}
`;
}
@@ -96,17 +94,17 @@ export class HaAssistPipelinePicker extends LitElement {
}
`;
- private _changed(ev): void {
- const target = ev.target as HaSelect;
+ private _changed(ev: CustomEvent<{ value: string }>): void {
+ const value = ev.detail.value;
if (
!this.hass ||
- target.value === "" ||
- target.value === this.value ||
- (this.value === undefined && target.value === this._default)
+ value === "" ||
+ value === this.value ||
+ (this.value === undefined && value === this._default)
) {
return;
}
- this.value = target.value === this._default ? undefined : target.value;
+ this.value = value === this._default ? undefined : value;
fireEvent(this, "value-changed", { value: this.value });
}
}
diff --git a/src/components/ha-base-time-input.ts b/src/components/ha-base-time-input.ts
index 40546aa13a..f24baf637a 100644
--- a/src/components/ha-base-time-input.ts
+++ b/src/components/ha-base-time-input.ts
@@ -4,10 +4,8 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { fireEvent } from "../common/dom/fire_event";
-import { stopPropagation } from "../common/dom/stop_propagation";
import "./ha-icon-button";
import "./ha-input-helper-text";
-import "./ha-list-item";
import "./ha-select";
import "./ha-textfield";
import type { HaTextField } from "./ha-textfield";
@@ -260,14 +258,10 @@ export class HaBaseTimeInput extends LitElement {
.required=${this.required}
.value=${this.amPm}
.disabled=${this.disabled}
- name="amPm"
- naturalMenuWidth
- fixedMenuPosition
+ .name=${"amPm"}
@selected=${this._valueChanged}
- @closed=${stopPropagation}
+ .options=${["AM", "PM"]}
>
- AM
- PM
`}
${this.helper
@@ -282,10 +276,12 @@ export class HaBaseTimeInput extends LitElement {
fireEvent(this, "value-changed");
}
- private _valueChanged(ev: InputEvent) {
+ private _valueChanged(ev: InputEvent | CustomEvent<{ value: string }>): void {
const textField = ev.currentTarget as HaTextField;
this[textField.name] =
- textField.name === "amPm" ? textField.value : Number(textField.value);
+ textField.name === "amPm"
+ ? (ev as CustomEvent<{ value: string }>).detail.value
+ : Number(textField.value);
const value: TimeChangedEvent = {
hours: this.hours,
minutes: this.minutes,
@@ -366,10 +362,6 @@ export class HaBaseTimeInput extends LitElement {
ha-textfield:last-child {
--text-field-border-top-right-radius: var(--mdc-shape-medium);
}
- ha-select {
- --mdc-shape-small: 0;
- width: 85px;
- }
:host([clearable]) .mdc-select__anchor {
padding-inline-end: var(--select-selected-text-padding-end, 12px);
}
diff --git a/src/components/ha-blueprint-picker.ts b/src/components/ha-blueprint-picker.ts
index 5c13ef894e..4cfe2ea1e6 100644
--- a/src/components/ha-blueprint-picker.ts
+++ b/src/components/ha-blueprint-picker.ts
@@ -2,12 +2,10 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../common/dom/fire_event";
-import { stopPropagation } from "../common/dom/stop_propagation";
import { stringCompare } from "../common/string/compare";
import type { Blueprint, BlueprintDomain, Blueprints } from "../data/blueprint";
import { fetchBlueprints } from "../data/blueprint";
import type { HomeAssistant } from "../types";
-import "./ha-list-item";
import "./ha-select";
@customElement("ha-blueprint-picker")
@@ -55,20 +53,16 @@ class HaBluePrintPicker extends LitElement {
- ${this._processedBlueprints(this.blueprints).map(
- (blueprint) => html`
-
- ${blueprint.name}
-
- `
+ .options=${this._processedBlueprints(this.blueprints).map(
+ (blueprint) => ({
+ value: blueprint.path,
+ label: blueprint.name,
+ })
)}
+ >
`;
}
@@ -82,8 +76,8 @@ class HaBluePrintPicker extends LitElement {
}
}
- private _blueprintChanged(ev) {
- const newValue = ev.target.value;
+ private _blueprintChanged(ev: CustomEvent<{ value: string }>) {
+ const newValue = ev.detail.value;
if (newValue !== this.value) {
this.value = newValue;
diff --git a/src/components/ha-conversation-agent-picker.ts b/src/components/ha-conversation-agent-picker.ts
index d29e8dc907..6ce20e2deb 100644
--- a/src/components/ha-conversation-agent-picker.ts
+++ b/src/components/ha-conversation-agent-picker.ts
@@ -3,7 +3,6 @@ import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
-import { stopPropagation } from "../common/dom/stop_propagation";
import { debounce } from "../common/util/debounce";
import type { ConfigEntry, SubEntry } from "../data/config_entries";
import { getConfigEntry, getSubEntries } from "../data/config_entries";
@@ -14,9 +13,8 @@ import { fetchIntegrationManifest } from "../data/integration";
import { showOptionsFlowDialog } from "../dialogs/config-flow/show-dialog-options-flow";
import { showSubConfigFlowDialog } from "../dialogs/config-flow/show-dialog-sub-config-flow";
import type { HomeAssistant } from "../types";
-import "./ha-list-item";
import "./ha-select";
-import type { HaSelect } from "./ha-select";
+import type { HaSelectOption } from "./ha-select";
const NONE = "__NONE_OPTION__";
@@ -73,6 +71,23 @@ export class HaConversationAgentPicker extends LitElement {
value = NONE;
}
+ const options: HaSelectOption[] = this._agents.map((agent) => ({
+ value: agent.id,
+ label: agent.name,
+ disabled:
+ agent.supported_languages !== "*" &&
+ agent.supported_languages.length === 0,
+ }));
+
+ if (!this.required) {
+ options.unshift({
+ value: NONE,
+ label: this.hass.localize(
+ "ui.components.conversation-agent-picker.none"
+ ),
+ });
+ }
+
return html`
- ${!this.required
- ? html`
- ${this.hass!.localize(
- "ui.components.conversation-agent-picker.none"
- )}
- `
- : nothing}
- ${this._agents.map(
- (agent) =>
- html`
- ${agent.name}
- `
- )}${(this._subConfigEntry &&
this._configEntry?.supported_subentry_types[
this._subConfigEntry.subentry_type
@@ -238,17 +234,17 @@ export class HaConversationAgentPicker extends LitElement {
}
`;
- private _changed(ev): void {
- const target = ev.target as HaSelect;
+ private _changed(ev: CustomEvent<{ value: string }>): void {
+ const value = ev.detail.value;
if (
!this.hass ||
- target.value === "" ||
- target.value === this.value ||
- (this.value === undefined && target.value === NONE)
+ value === "" ||
+ value === this.value ||
+ (this.value === undefined && value === NONE)
) {
return;
}
- this.value = target.value === NONE ? undefined : target.value;
+ this.value = value === NONE ? undefined : value;
fireEvent(this, "value-changed", { value: this.value });
fireEvent(this, "supported-languages-changed", {
value: this._agents!.find((agent) => agent.id === this.value)
diff --git a/src/components/ha-language-picker.ts b/src/components/ha-language-picker.ts
index 38807e046a..8725121a15 100644
--- a/src/components/ha-language-picker.ts
+++ b/src/components/ha-language-picker.ts
@@ -107,9 +107,6 @@ export class HaLanguagePicker extends LitElement {
@property({ attribute: "no-sort", type: Boolean }) public noSort = false;
- @property({ attribute: "inline-arrow", type: Boolean })
- public inlineArrow = false;
-
@state() _defaultLanguages: string[] = [];
@query("ha-generic-picker", true) public genericPicker!: HaGenericPicker;
diff --git a/src/components/ha-menu.ts b/src/components/ha-menu.ts
deleted file mode 100644
index 1865bdf23c..0000000000
--- a/src/components/ha-menu.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { MenuBase } from "@material/mwc-menu/mwc-menu-base";
-import { styles } from "@material/mwc-menu/mwc-menu.css";
-import { html } from "lit";
-import { customElement } from "lit/decorators";
-import { classMap } from "lit/directives/class-map";
-import "./ha-list";
-
-@customElement("ha-menu")
-export class HaMenu extends MenuBase {
- protected get listElement() {
- if (!this.listElement_) {
- this.listElement_ = this.renderRoot.querySelector("ha-list");
- return this.listElement_;
- }
-
- return this.listElement_;
- }
-
- protected renderList() {
- const itemRoles = this.innerRole === "menu" ? "menuitem" : "option";
- const classes = this.renderListClasses();
-
- return html`
-
- `;
- }
-
- static styles = styles;
-}
-
-declare global {
- interface HTMLElementTagNameMap {
- "ha-menu": HaMenu;
- }
-}
diff --git a/src/components/ha-mount-picker.ts b/src/components/ha-mount-picker.ts
index 7dfc1495a6..b13e2f8647 100644
--- a/src/components/ha-mount-picker.ts
+++ b/src/components/ha-mount-picker.ts
@@ -5,7 +5,6 @@ import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../common/config/is_component_loaded";
import { fireEvent } from "../common/dom/fire_event";
-import { stopPropagation } from "../common/dom/stop_propagation";
import { caseInsensitiveStringCompare } from "../common/string/compare";
import type { SupervisorMounts } from "../data/supervisor/mounts";
import {
@@ -17,7 +16,7 @@ import type { HomeAssistant } from "../types";
import "./ha-alert";
import "./ha-list-item";
import "./ha-select";
-import type { HaSelect } from "./ha-select";
+import type { HaSelectOption } from "./ha-select";
const _BACKUP_DATA_DISK_ = "/backup";
@@ -52,60 +51,54 @@ class HaMountPicker extends LitElement {
if (!this._mounts) {
return nothing;
}
- const dataDiskOption = html`
-
- ${this.hass.localize("ui.components.mount-picker.use_datadisk") ||
- "Use data disk for backup"}
-
-
- `;
+
+ const options: HaSelectOption[] = this._filterMounts(
+ this._mounts,
+ this.usage
+ ).map((mount) => ({
+ value: mount.name,
+ label: mount.name,
+ secondary: `${mount.server}${mount.port ? `:${mount.port}` : ""}${
+ mount.type === SupervisorMountType.NFS ? mount.path : `:${mount.share}`
+ }`,
+ iconPath:
+ mount.usage === SupervisorMountUsage.MEDIA
+ ? mdiPlayBox
+ : mount.usage === SupervisorMountUsage.SHARE
+ ? mdiFolder
+ : mdiBackupRestore,
+ }));
+
+ if (this.usage === SupervisorMountUsage.BACKUP) {
+ const dataDiskOption = {
+ value: _BACKUP_DATA_DISK_,
+ iconPath: mdiHarddisk,
+ label:
+ this.hass.localize("ui.components.mount-picker.use_datadisk") ||
+ "Use data disk for backup",
+ };
+ if (
+ !this._mounts.default_backup_mount ||
+ this._mounts.default_backup_mount === _BACKUP_DATA_DISK_
+ ) {
+ options.unshift(dataDiskOption);
+ } else {
+ options.push(dataDiskOption);
+ }
+ }
+
return html`
- ${this.usage === SupervisorMountUsage.BACKUP &&
- (!this._mounts.default_backup_mount ||
- this._mounts.default_backup_mount === _BACKUP_DATA_DISK_)
- ? dataDiskOption
- : nothing}
- ${this._filterMounts(this._mounts, this.usage).map(
- (mount) =>
- html`
- ${mount.name}
- ${mount.server}${mount.port
- ? `:${mount.port}`
- : nothing}${mount.type === SupervisorMountType.NFS
- ? mount.path
- : `:${mount.share}`}
-
- `
- )}
- ${this.usage === SupervisorMountUsage.BACKUP &&
- this._mounts.default_backup_mount
- ? dataDiskOption
- : nothing}
`;
}
@@ -153,16 +146,10 @@ class HaMountPicker extends LitElement {
}
}
- private get _value() {
- return this.value || "";
- }
+ private _mountChanged(ev: CustomEvent<{ value: string }>) {
+ const newValue = ev.detail.value;
- private _mountChanged(ev: Event) {
- ev.stopPropagation();
- const target = ev.target as HaSelect;
- const newValue = target.value;
-
- if (newValue !== this._value) {
+ if (newValue !== this.value) {
this._setValue(newValue);
}
}
diff --git a/src/components/ha-select.ts b/src/components/ha-select.ts
index 97b6bb91fd..2a9f369c26 100644
--- a/src/components/ha-select.ts
+++ b/src/components/ha-select.ts
@@ -1,187 +1,209 @@
-import { SelectBase } from "@material/mwc-select/mwc-select-base";
-import { styles } from "@material/mwc-select/mwc-select.css";
-import { mdiClose } from "@mdi/js";
-import { css, html, nothing } from "lit";
-import { customElement, property } from "lit/decorators";
-import { classMap } from "lit/directives/class-map";
-import { debounce } from "../common/util/debounce";
-import { nextRender } from "../common/util/render-status";
-import "./ha-icon-button";
-import "./ha-menu";
+import { css, html, LitElement, nothing } from "lit";
+import { customElement, property, query, state } from "lit/decorators";
+import { ifDefined } from "lit/directives/if-defined";
+import memoizeOne from "memoize-one";
+import { fireEvent } from "../common/dom/fire_event";
+import "./ha-dropdown";
+import "./ha-dropdown-item";
+import "./ha-picker-field";
+import type { HaPickerField } from "./ha-picker-field";
+import "./ha-svg-icon";
+
+export interface HaSelectOption {
+ value: string;
+ label?: string;
+ secondary?: string;
+ iconPath?: string;
+ disabled?: boolean;
+}
@customElement("ha-select")
-export class HaSelect extends SelectBase {
- // @ts-ignore
- @property({ type: Boolean }) public icon = false;
+export class HaSelect extends LitElement {
+ @property({ type: Boolean }) public clearable = false;
- @property({ type: Boolean, reflect: true }) public clearable = false;
+ @property({ attribute: false }) public options?: HaSelectOption[] | string[];
- @property({ attribute: "inline-arrow", type: Boolean })
- public inlineArrow = false;
+ @property() public label?: string;
- @property() public options;
+ @property() public helper?: string;
+
+ @property() public value?: string;
+
+ @property({ type: Boolean }) public required = false;
+
+ @property({ type: Boolean }) public disabled = false;
+
+ @state() private _opened = false;
+
+ @query("ha-picker-field") private _triggerField!: HaPickerField;
+
+ private _getValueLabel = memoizeOne(
+ (
+ options: HaSelectOption[] | string[] | undefined,
+ value: string | undefined
+ ) => {
+ if (!options || !value) {
+ return value;
+ }
+
+ for (const option of options) {
+ if (
+ (typeof option === "string" && option === value) ||
+ (typeof option !== "string" && option.value === value)
+ ) {
+ return typeof option === "string"
+ ? option
+ : option.label || option.value;
+ }
+ }
+
+ return value;
+ }
+ );
protected override render() {
+ if (this.disabled) {
+ return this._renderField();
+ }
+
return html`
- ${super.render()}
- ${this.clearable && !this.required && !this.disabled && this.value
- ? html``
- : nothing}
+
+ ${this._renderField()}
+ ${this.options
+ ? this.options.map(
+ (option) => html`
+
+ ${option.iconPath
+ ? html``
+ : nothing}
+
+ ${typeof option === "string"
+ ? option
+ : option.label || option.value}
+ ${option.secondary
+ ? html`
${option.secondary}
`
+ : nothing}
+
+
+ `
+ )
+ : html``}
+
`;
}
- protected override renderMenu() {
- const classes = this.getMenuClasses();
- return html`
- ${this.renderMenuContent()}
- `;
+ private _renderField() {
+ const valueLabel = this._getValueLabel(this.options, this.value);
+
+ return html`
+
+
+ `;
}
- protected override renderLeadingIcon() {
- if (!this.icon) {
- return nothing;
+ private _handleSelect(ev: CustomEvent<{ item: { value: string } }>) {
+ ev.stopPropagation();
+ const value = ev.detail.item.value;
+ if (value === this.value) {
+ return;
}
-
- return html``;
- }
-
- connectedCallback() {
- super.connectedCallback();
- window.addEventListener("translations-updated", this._translationsUpdated);
- }
-
- protected async firstUpdated() {
- super.firstUpdated();
-
- if (this.inlineArrow) {
- this.shadowRoot
- ?.querySelector(".mdc-select__selected-text-container")
- ?.classList.add("inline-arrow");
- }
- }
-
- protected updated(changedProperties) {
- super.updated(changedProperties);
-
- if (changedProperties.has("inlineArrow")) {
- const textContainerElement = this.shadowRoot?.querySelector(
- ".mdc-select__selected-text-container"
- );
- if (this.inlineArrow) {
- textContainerElement?.classList.add("inline-arrow");
- } else {
- textContainerElement?.classList.remove("inline-arrow");
- }
- }
- if (changedProperties.get("options")) {
- this.layoutOptions();
- this.selectByValue(this.value);
- }
- }
-
- disconnectedCallback() {
- super.disconnectedCallback();
- window.removeEventListener(
- "translations-updated",
- this._translationsUpdated
- );
+ fireEvent(this, "selected", { value });
}
private _clearValue(): void {
if (this.disabled || !this.value) {
return;
}
- this.valueSetDirectly = true;
- this.select(-1);
- this.mdcFoundation.handleChange();
+
+ fireEvent(this, "selected", { value: undefined });
}
- private _translationsUpdated = debounce(async () => {
- await nextRender();
- this.layoutOptions();
- }, 500);
+ private _handleShow() {
+ this.style.setProperty(
+ "--select-menu-width",
+ `${this._triggerField.offsetWidth}px`
+ );
+ this._opened = true;
+ }
- static override styles = [
- styles,
- css`
- :host([clearable]) {
- position: relative;
- }
- .mdc-select:not(.mdc-select--disabled) .mdc-select__icon {
- color: var(--secondary-text-color);
- }
- .mdc-select__anchor {
- width: var(--ha-select-min-width, 200px);
- }
- .mdc-select--filled .mdc-select__anchor {
- height: var(--ha-select-height, 56px);
- }
- .mdc-select--filled .mdc-floating-label {
- inset-inline-start: var(--ha-space-4);
- inset-inline-end: initial;
- direction: var(--direction);
- }
- .mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label {
- inset-inline-start: 48px;
- inset-inline-end: initial;
- direction: var(--direction);
- }
- .mdc-select .mdc-select__anchor {
- padding-inline-start: var(--ha-space-4);
- padding-inline-end: 0px;
- direction: var(--direction);
- }
- .mdc-select__anchor .mdc-floating-label--float-above {
- transform-origin: var(--float-start);
- }
- .mdc-select__selected-text-container {
- padding-inline-end: var(--select-selected-text-padding-end, 0px);
- }
- :host([clearable]) .mdc-select__selected-text-container {
- padding-inline-end: var(
- --select-selected-text-padding-end,
- var(--ha-space-4)
- );
- }
- ha-icon-button {
- position: absolute;
- top: 10px;
- right: 28px;
- --mdc-icon-button-size: 36px;
- --mdc-icon-size: 20px;
- color: var(--secondary-text-color);
- inset-inline-start: initial;
- inset-inline-end: 28px;
- direction: var(--direction);
- }
- .inline-arrow {
- flex-grow: 0;
- }
- `,
- ];
+ private _handleHide() {
+ this._opened = false;
+ }
+
+ static styles = css`
+ :host {
+ position: relative;
+ }
+ ha-picker-field.opened {
+ --mdc-text-field-idle-line-color: var(--primary-color);
+ }
+ ha-dropdown-item.selected:hover {
+ background-color: var(--ha-color-fill-primary-quiet-hover);
+ }
+
+ ha-dropdown-item .content {
+ display: flex;
+ gap: var(--ha-space-1);
+ flex-direction: column;
+ }
+
+ ha-dropdown-item .secondary {
+ font-size: var(--ha-font-size-s);
+ color: var(--ha-color-text-secondary);
+ }
+
+ ha-dropdown::part(menu) {
+ min-width: var(--select-menu-width);
+ }
+
+ :host ::slotted(ha-dropdown-item.selected),
+ ha-dropdown-item.selected {
+ font-weight: var(--ha-font-weight-medium);
+ color: var(--primary-color);
+ background-color: var(--ha-color-fill-primary-quiet-resting);
+ --icon-primary-color: var(--primary-color);
+ }
+ `;
}
declare global {
interface HTMLElementTagNameMap {
"ha-select": HaSelect;
}
+
+ interface HASSDomEvents {
+ selected: { value: string | undefined };
+ }
}
diff --git a/src/components/ha-selector/ha-selector-select.ts b/src/components/ha-selector/ha-selector-select.ts
index 4a93bf095e..8ca3a10f6c 100644
--- a/src/components/ha-selector/ha-selector-select.ts
+++ b/src/components/ha-selector/ha-selector-select.ts
@@ -5,17 +5,16 @@ import { repeat } from "lit/directives/repeat";
import memoizeOne from "memoize-one";
import { ensureArray } from "../../common/array/ensure-array";
import { fireEvent } from "../../common/dom/fire_event";
-import { stopPropagation } from "../../common/dom/stop_propagation";
import { caseInsensitiveStringCompare } from "../../common/string/compare";
import type { SelectOption, SelectSelector } from "../../data/selector";
import type { HomeAssistant } from "../../types";
import "../chips/ha-chip-set";
import "../chips/ha-input-chip";
import "../ha-checkbox";
+import "../ha-dropdown-item";
import "../ha-formfield";
import "../ha-generic-picker";
import "../ha-input-helper-text";
-import "../ha-list-item";
import "../ha-radio";
import "../ha-select";
import "../ha-select-box";
@@ -231,24 +230,15 @@ export class HaSelectSelector extends LitElement {
return html`
- ${options.map(
- (item: SelectOption) => html`
- ${item.label}
- `
- )}
`;
}
@@ -295,7 +285,7 @@ export class HaSelectSelector extends LitElement {
private _valueChanged(ev) {
ev.stopPropagation();
- if (ev.detail?.index === -1 && this.value !== undefined) {
+ if (ev.detail?.value === undefined && this.value !== undefined) {
fireEvent(this, "value-changed", {
value: undefined,
});
@@ -385,7 +375,7 @@ export class HaSelectSelector extends LitElement {
ha-formfield {
display: block;
}
- ha-list-item[disabled] {
+ ha-dropdown-item[disabled] {
--mdc-theme-text-primary-on-background: var(--disabled-text-color);
}
ha-chip-set {
diff --git a/src/components/ha-settings-row.ts b/src/components/ha-settings-row.ts
index fa946d81f8..ed366a39f9 100644
--- a/src/components/ha-settings-row.ts
+++ b/src/components/ha-settings-row.ts
@@ -108,6 +108,7 @@ export class HaSettingsRow extends LitElement {
white-space: normal;
}
.prefix-wrap {
+ flex: 1;
display: var(--settings-row-prefix-display);
}
:host([narrow]) .prefix-wrap {
diff --git a/src/components/ha-stt-picker.ts b/src/components/ha-stt-picker.ts
index 246ba7c650..f0f10609b5 100644
--- a/src/components/ha-stt-picker.ts
+++ b/src/components/ha-stt-picker.ts
@@ -2,16 +2,14 @@ import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
-import { stopPropagation } from "../common/dom/stop_propagation";
+import { computeDomain } from "../common/entity/compute_domain";
import { computeStateName } from "../common/entity/compute_state_name";
import { debounce } from "../common/util/debounce";
import type { STTEngine } from "../data/stt";
import { listSTTEngines } from "../data/stt";
import type { HomeAssistant } from "../types";
-import "./ha-list-item";
import "./ha-select";
-import type { HaSelect } from "./ha-select";
-import { computeDomain } from "../common/entity/compute_domain";
+import type { HaSelectOption } from "./ha-select";
const NONE = "__NONE_OPTION__";
@@ -61,6 +59,30 @@ export class HaSTTPicker extends LitElement {
value = NONE;
}
+ const options: HaSelectOption[] = this._engines
+ .filter((engine) => !engine.deprecated || engine.engine_id !== value)
+ .map((engine) => {
+ let label: string;
+ if (engine.engine_id.includes(".")) {
+ const stateObj = this.hass.states[engine.engine_id];
+ label = stateObj ? computeStateName(stateObj) : engine.engine_id;
+ } else {
+ label = engine.name || engine.engine_id;
+ }
+ return {
+ value: engine.engine_id,
+ label,
+ disabled: engine.supported_languages?.length === 0,
+ };
+ });
+
+ if (this.required || value === NONE) {
+ options.unshift({
+ value: NONE,
+ label: this.hass.localize("ui.components.stt-picker.none") || "None",
+ });
+ }
+
return html`
- ${!this.required
- ? html`
- ${this.hass!.localize("ui.components.stt-picker.none")}
- `
- : nothing}
- ${this._engines.map((engine) => {
- if (engine.deprecated && engine.engine_id !== value) {
- return nothing;
- }
- let label: string;
- if (engine.engine_id.includes(".")) {
- const stateObj = this.hass!.states[engine.engine_id];
- label = stateObj ? computeStateName(stateObj) : engine.engine_id;
- } else {
- label = engine.name || engine.engine_id;
- }
- return html`
- ${label}
- `;
- })}
`;
}
@@ -144,17 +141,17 @@ export class HaSTTPicker extends LitElement {
}
`;
- private _changed(ev): void {
- const target = ev.target as HaSelect;
+ private _changed(ev: CustomEvent<{ value: string }>): void {
+ const value = ev.detail.value;
if (
!this.hass ||
- target.value === "" ||
- target.value === this.value ||
- (this.value === undefined && target.value === NONE)
+ value === "" ||
+ value === this.value ||
+ (this.value === undefined && value === NONE)
) {
return;
}
- this.value = target.value === NONE ? undefined : target.value;
+ this.value = value === NONE ? undefined : value;
fireEvent(this, "value-changed", { value: this.value });
fireEvent(this, "supported-languages-changed", {
value: this._engines!.find((engine) => engine.engine_id === this.value)
diff --git a/src/components/ha-theme-picker.ts b/src/components/ha-theme-picker.ts
index c188e39309..02a220ef75 100644
--- a/src/components/ha-theme-picker.ts
+++ b/src/components/ha-theme-picker.ts
@@ -1,11 +1,10 @@
import type { TemplateResult } from "lit";
-import { css, html, nothing, LitElement } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
-import { stopPropagation } from "../common/dom/stop_propagation";
import type { HomeAssistant } from "../types";
import "./ha-select";
-import "./ha-list-item";
+import type { HaSelectOption } from "./ha-select";
const DEFAULT_THEME = "default";
@@ -25,6 +24,26 @@ export class HaThemePicker extends LitElement {
@property({ type: Boolean }) public required = false;
protected render(): TemplateResult {
+ const options: HaSelectOption[] = Object.keys(
+ this.hass?.themes.themes || {}
+ ).map((theme) => ({
+ value: theme,
+ }));
+
+ if (this.includeDefault) {
+ options.unshift({
+ value: DEFAULT_THEME,
+ label: "Home Assistant",
+ });
+ }
+
+ if (!this.required) {
+ options.unshift({
+ value: "remove",
+ label: this.hass!.localize("ui.components.theme-picker.no_theme"),
+ });
+ }
+
return html`
- ${!this.required
- ? html`
-
- ${this.hass!.localize("ui.components.theme-picker.no_theme")}
-
- `
- : nothing}
- ${this.includeDefault
- ? html`
-
- Home Assistant
-
- `
- : nothing}
- ${Object.keys(this.hass!.themes.themes)
- .sort()
- .map(
- (theme) =>
- html`${theme}`
- )}
-
+ .options=${options}
+ >
`;
}
@@ -67,11 +63,11 @@ export class HaThemePicker extends LitElement {
}
`;
- private _changed(ev): void {
- if (!this.hass || ev.target.value === "") {
+ private _changed(ev: CustomEvent<{ value: string }>): void {
+ if (!this.hass || ev.detail.value === "") {
return;
}
- this.value = ev.target.value === "remove" ? undefined : ev.target.value;
+ this.value = ev.detail.value === "remove" ? undefined : ev.detail.value;
fireEvent(this, "value-changed", { value: this.value });
}
}
diff --git a/src/components/ha-tts-picker.ts b/src/components/ha-tts-picker.ts
index 73bdea15d5..51bcfa91f4 100644
--- a/src/components/ha-tts-picker.ts
+++ b/src/components/ha-tts-picker.ts
@@ -2,16 +2,14 @@ import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
-import { stopPropagation } from "../common/dom/stop_propagation";
+import { computeDomain } from "../common/entity/compute_domain";
import { computeStateName } from "../common/entity/compute_state_name";
import { debounce } from "../common/util/debounce";
import type { TTSEngine } from "../data/tts";
import { listTTSEngines } from "../data/tts";
import type { HomeAssistant } from "../types";
-import "./ha-list-item";
import "./ha-select";
-import type { HaSelect } from "./ha-select";
-import { computeDomain } from "../common/entity/compute_domain";
+import type { HaSelectOption } from "./ha-select";
const NONE = "__NONE_OPTION__";
@@ -61,6 +59,30 @@ export class HaTTSPicker extends LitElement {
value = NONE;
}
+ const options: HaSelectOption[] = this._engines
+ .filter((engine) => !engine.deprecated || engine.engine_id === value)
+ .map((engine) => {
+ let label: string;
+ if (engine.engine_id.includes(".")) {
+ const stateObj = this.hass.states[engine.engine_id];
+ label = stateObj ? computeStateName(stateObj) : engine.engine_id;
+ } else {
+ label = engine.name || engine.engine_id;
+ }
+ return {
+ value: engine.engine_id,
+ label,
+ disabled: engine.supported_languages?.length === 0,
+ };
+ });
+
+ if (!this.required || value === NONE) {
+ options.unshift({
+ value: NONE,
+ label: this.hass.localize("ui.components.tts-picker.none"),
+ });
+ }
+
return html`
- ${!this.required
- ? html`
- ${this.hass!.localize("ui.components.tts-picker.none")}
- `
- : nothing}
- ${this._engines.map((engine) => {
- if (engine.deprecated && engine.engine_id !== value) {
- return nothing;
- }
- let label: string;
- if (engine.engine_id.includes(".")) {
- const stateObj = this.hass!.states[engine.engine_id];
- label = stateObj ? computeStateName(stateObj) : engine.engine_id;
- } else {
- label = engine.name || engine.engine_id;
- }
- return html`
- ${label}
- `;
- })}
`;
}
@@ -144,17 +141,17 @@ export class HaTTSPicker extends LitElement {
}
`;
- private _changed(ev): void {
- const target = ev.target as HaSelect;
+ private _changed(ev: CustomEvent<{ value: string }>): void {
+ const value = ev.detail.value;
if (
!this.hass ||
- target.value === "" ||
- target.value === this.value ||
- (this.value === undefined && target.value === NONE)
+ value === "" ||
+ value === this.value ||
+ (this.value === undefined && value === NONE)
) {
return;
}
- this.value = target.value === NONE ? undefined : target.value;
+ this.value = value === NONE ? undefined : value;
fireEvent(this, "value-changed", { value: this.value });
fireEvent(this, "supported-languages-changed", {
value: this._engines!.find((engine) => engine.engine_id === this.value)
diff --git a/src/components/ha-tts-voice-picker.ts b/src/components/ha-tts-voice-picker.ts
index c5ee4ac21a..0aad98de80 100644
--- a/src/components/ha-tts-voice-picker.ts
+++ b/src/components/ha-tts-voice-picker.ts
@@ -1,15 +1,13 @@
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
-import { customElement, property, query, state } from "lit/decorators";
+import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
-import { stopPropagation } from "../common/dom/stop_propagation";
import { debounce } from "../common/util/debounce";
import type { TTSVoice } from "../data/tts";
import { listTTSVoices } from "../data/tts";
import type { HomeAssistant } from "../types";
-import "./ha-list-item";
import "./ha-select";
-import type { HaSelect } from "./ha-select";
+import type { HaSelectOption } from "./ha-select";
const NONE = "__NONE_OPTION__";
@@ -31,14 +29,25 @@ export class HaTTSVoicePicker extends LitElement {
@state() _voices?: TTSVoice[] | null;
- @query("ha-select") private _select?: HaSelect;
-
protected render() {
if (!this._voices) {
return nothing;
}
const value =
this.value ?? (this.required ? this._voices[0]?.voice_id : NONE);
+
+ const options: HaSelectOption[] = (this._voices || []).map((voice) => ({
+ value: voice.voice_id,
+ label: voice.name,
+ }));
+
+ if (!this.required || !this.value) {
+ options.unshift({
+ value: NONE,
+ label: this.hass!.localize("ui.components.tts-voice-picker.none"),
+ });
+ }
+
return html`
- ${!this.required
- ? html`
- ${this.hass!.localize("ui.components.tts-voice-picker.none")}
- `
- : nothing}
- ${this._voices.map(
- (voice) =>
- html`
- ${voice.name}
- `
- )}
`;
}
@@ -102,34 +98,25 @@ export class HaTTSVoicePicker extends LitElement {
}
}
- protected updated(changedProperties: PropertyValues) {
- super.updated(changedProperties);
- if (
- changedProperties.has("_voices") &&
- this._select?.value !== this.value
- ) {
- this._select?.layoutOptions();
- fireEvent(this, "value-changed", { value: this._select?.value });
- }
- }
-
static styles = css`
ha-select {
width: 100%;
+ text-align: start;
+ display: block;
}
`;
- private _changed(ev): void {
- const target = ev.target as HaSelect;
+ private _changed(ev: CustomEvent<{ value: string }>): void {
+ const value = ev.detail.value;
if (
!this.hass ||
- target.value === "" ||
- target.value === this.value ||
- (this.value === undefined && target.value === NONE)
+ value === "" ||
+ value === this.value ||
+ (this.value === undefined && value === NONE)
) {
return;
}
- this.value = target.value === NONE ? undefined : target.value;
+ this.value = value === NONE ? undefined : value;
fireEvent(this, "value-changed", { value: this.value });
}
}
diff --git a/src/dialogs/config-flow/previews/entity-preview-row.ts b/src/dialogs/config-flow/previews/entity-preview-row.ts
index 7449c9325e..cfabdd8440 100644
--- a/src/dialogs/config-flow/previews/entity-preview-row.ts
+++ b/src/dialogs/config-flow/previews/entity-preview-row.ts
@@ -13,7 +13,6 @@ import "../../../components/ha-cover-controls";
import "../../../components/ha-cover-tilt-controls";
import "../../../components/ha-date-input";
import "../../../components/ha-humidifier-state";
-import "../../../components/ha-list-item";
import "../../../components/ha-select";
import "../../../components/ha-slider";
import "../../../components/ha-time-input";
@@ -296,17 +295,11 @@ class EntityPreviewRow extends LitElement {
.label=${computeStateName(stateObj)}
.value=${stateObj.state}
.disabled=${isUnavailableState(stateObj.state)}
- naturalMenuWidth
+ .options=${stateObj.attributes.options?.map((option) => ({
+ value: option,
+ label: this.hass!.formatEntityState(stateObj, option),
+ })) || []}
>
- ${stateObj.attributes.options
- ? stateObj.attributes.options.map(
- (option) => html`
-
- ${this.hass!.formatEntityState(stateObj, option)}
-
- `
- )
- : ""}
`;
}
diff --git a/src/dialogs/more-info/components/siren/ha-more-info-siren-advanced-controls.ts b/src/dialogs/more-info/components/siren/ha-more-info-siren-advanced-controls.ts
index ce0735bde7..349e74ad9f 100644
--- a/src/dialogs/more-info/components/siren/ha-more-info-siren-advanced-controls.ts
+++ b/src/dialogs/more-info/components/siren/ha-more-info-siren-advanced-controls.ts
@@ -4,16 +4,15 @@ import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { supportsFeature } from "../../../../common/entity/supports-feature";
import "../../../../components/ha-button";
import "../../../../components/ha-control-button";
import "../../../../components/ha-dialog-footer";
import "../../../../components/ha-icon-button";
import "../../../../components/ha-list-item";
-import "../../../../components/ha-wa-dialog";
import "../../../../components/ha-select";
import "../../../../components/ha-textfield";
+import "../../../../components/ha-wa-dialog";
import { SirenEntityFeature } from "../../../../data/siren";
import { haStyle } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types";
@@ -77,24 +76,19 @@ class MoreInfoSirenAdvancedControls extends LitElement {
? html`
({
+ value: Array.isArray(
+ this._stateObj!.attributes.available_tones
+ )
+ ? toneName
+ : toneId,
+ label: toneName,
+ }))}
>
- ${Object.entries(
- this._stateObj.attributes.available_tones
- ).map(
- ([toneId, toneName]) => html`
- ${toneName}
- `
- )}
`
: nothing}
@@ -152,8 +146,8 @@ class MoreInfoSirenAdvancedControls extends LitElement {
`;
}
- private _handleToneChange(ev) {
- this._tone = ev.target.value;
+ private _handleToneChange(ev: CustomEvent<{ value: string }>) {
+ this._tone = ev.detail.value;
}
private _handleVolumeChange(ev) {
diff --git a/src/dialogs/more-info/controls/more-info-remote.ts b/src/dialogs/more-info/controls/more-info-remote.ts
index 662ae4eb7c..fd425420f9 100644
--- a/src/dialogs/more-info/controls/more-info-remote.ts
+++ b/src/dialogs/more-info/controls/more-info-remote.ts
@@ -1,12 +1,10 @@
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
-import { stopPropagation } from "../../../common/dom/stop_propagation";
import { supportsFeature } from "../../../common/entity/supports-feature";
+import "../../../components/ha-select";
import type { RemoteEntity } from "../../../data/remote";
import { REMOTE_SUPPORT_ACTIVITY } from "../../../data/remote";
import type { HomeAssistant } from "../../../types";
-import "../../../components/ha-select";
-import "../../../components/ha-list-item";
@customElement("more-info-remote")
class MoreInfoRemote extends LitElement {
@@ -30,30 +28,24 @@ class MoreInfoRemote extends LitElement {
)}
.value=${stateObj.attributes.current_activity || ""}
@selected=${this._handleActivityChanged}
- fixedMenuPosition
- naturalMenuWidth
- @closed=${stopPropagation}
+ .options=${stateObj.attributes.activity_list?.map((activity) => ({
+ value: activity,
+ label: this.hass!.formatEntityAttributeValue(
+ stateObj,
+ "activity",
+ activity
+ ),
+ }))}
>
- ${stateObj.attributes.activity_list?.map(
- (activity) => html`
-
- ${this.hass.formatEntityAttributeValue(
- stateObj,
- "activity",
- activity
- )}
-
- `
- )}
`
: nothing}
`;
}
- private _handleActivityChanged(ev) {
+ private _handleActivityChanged(ev: CustomEvent<{ value: string }>) {
const oldVal = this.stateObj!.attributes.current_activity;
- const newVal = ev.target.value;
+ const newVal = ev.detail.value;
if (!newVal || oldVal === newVal) {
return;
diff --git a/src/dialogs/more-info/controls/more-info-vacuum.ts b/src/dialogs/more-info/controls/more-info-vacuum.ts
index 4a68280b05..97593410d1 100644
--- a/src/dialogs/more-info/controls/more-info-vacuum.ts
+++ b/src/dialogs/more-info/controls/more-info-vacuum.ts
@@ -11,13 +11,11 @@ import {
import { LitElement, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
-import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/entity/ha-battery-icon";
import "../../../components/ha-icon";
import "../../../components/ha-icon-button";
-import "../../../components/ha-list-item";
import "../../../components/ha-select";
import { UNAVAILABLE } from "../../../data/entity/entity";
import type { EntityRegistryDisplayEntry } from "../../../data/entity/entity_registry";
@@ -172,21 +170,17 @@ class MoreInfoVacuum extends LitElement {
.disabled=${stateObj.state === UNAVAILABLE}
.value=${stateObj.attributes.fan_speed}
@selected=${this._handleFanSpeedChanged}
- fixedMenuPosition
- naturalMenuWidth
- @closed=${stopPropagation}
- >
- ${stateObj.attributes.fan_speed_list!.map(
- (mode) => html`
-
- ${this.hass.formatEntityAttributeValue(
- stateObj,
- "fan_speed",
- mode
- )}
-
- `
+ .options=${stateObj.attributes.fan_speed_list!.map(
+ (mode) => ({
+ value: mode,
+ label: this.hass!.formatEntityAttributeValue(
+ stateObj,
+ "fan_speed",
+ mode
+ ),
+ })
)}
+ >
) {
const oldVal = this.stateObj!.attributes.fan_speed;
- const newVal = ev.target.value;
+ const newVal = ev.detail.value;
if (!newVal || oldVal === newVal) {
return;
diff --git a/src/dialogs/voice-assistant-setup/voice-assistant-setup-step-check.ts b/src/dialogs/voice-assistant-setup/voice-assistant-setup-step-check.ts
index e3dc60e5c3..07760dd358 100644
--- a/src/dialogs/voice-assistant-setup/voice-assistant-setup-step-check.ts
+++ b/src/dialogs/voice-assistant-setup/voice-assistant-setup-step-check.ts
@@ -5,8 +5,8 @@ import "../../components/ha-button";
import "../../components/ha-spinner";
import { testAssistSatelliteConnection } from "../../data/assist_satellite";
import type { HomeAssistant } from "../../types";
-import { AssistantSetupStyles } from "./styles";
import { documentationUrl } from "../../util/documentation-url";
+import { AssistantSetupStyles } from "./styles";
@customElement("ha-voice-assistant-setup-step-check")
export class HaVoiceAssistantSetupStepCheck extends LitElement {
@@ -58,7 +58,7 @@ export class HaVoiceAssistantSetupStepCheck extends LitElement {
"/voice_control/troubleshooting/#i-dont-get-a-voice-response"
)}
>
- >${this.hass.localize(
+ ${this.hass.localize(
"ui.panel.config.voice_assistants.satellite_wizard.check.help"
)}
diff --git a/src/dialogs/voice-assistant-setup/voice-assistant-setup-step-success.ts b/src/dialogs/voice-assistant-setup/voice-assistant-setup-step-success.ts
index c636ff916f..2bf15e4c07 100644
--- a/src/dialogs/voice-assistant-setup/voice-assistant-setup-step-success.ts
+++ b/src/dialogs/voice-assistant-setup/voice-assistant-setup-step-success.ts
@@ -8,7 +8,6 @@ import {
computeDeviceName,
computeDeviceNameDisplay,
} from "../../common/entity/compute_device_name";
-import "../../components/ha-list-item";
import "../../components/ha-select";
import "../../components/ha-tts-voice-picker";
import type { AssistPipeline } from "../../data/assist_pipeline";
@@ -115,19 +114,15 @@ export class HaVoiceAssistantSetupStepSuccess extends LitElement {
.label=${this.hass.localize(
"ui.panel.config.voice_assistants.assistants.pipeline.detail.form.wake_word_id"
)}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
.value=${this.assistConfiguration.active_wake_words[0]}
@selected=${this._wakeWordPicked}
- >
- ${this.assistConfiguration.available_wake_words.map(
- (wakeword) =>
- html`
- ${wakeword.wake_word}
- `
+ .options=${this.assistConfiguration.available_wake_words.map(
+ (wakeword) => ({
+ value: wakeword.id,
+ label: wakeword.wake_word,
+ })
)}
-
+ >
- ${pipelineEntity?.attributes.options.map(
- (pipeline) =>
- html`
- ${this.hass.formatEntityState(pipelineEntity, pipeline)}
- `
+ .options=${pipelineEntity?.attributes.options.map(
+ (pipeline) => ({
+ value: pipeline,
+ label: this.hass.formatEntityState(
+ pipelineEntity,
+ pipeline
+ ),
+ })
)}
+ >
) {
+ const option = ev.detail.value;
+ if (this.assistConfiguration) {
+ this.assistConfiguration.active_wake_words = [option];
+ }
await setWakeWords(this.hass, this.assistEntityId!, [option]);
}
- private _pipelinePicked(ev) {
+ private _pipelinePicked(ev: CustomEvent<{ value: string }>) {
const stateObj = this.hass!.states[
this.assistConfiguration!.pipeline_entity_id
] as InputSelectEntity;
- const option = ev.target.value;
+ const option = ev.detail.value;
if (
option === stateObj.state ||
!stateObj.attributes.options.includes(option)
@@ -384,6 +383,11 @@ export class HaVoiceAssistantSetupStepSuccess extends LitElement {
.row ha-button {
width: 82px;
}
+
+ ha-select {
+ display: block;
+ text-align: start;
+ }
`,
];
}
diff --git a/src/onboarding/ha-onboarding.ts b/src/onboarding/ha-onboarding.ts
index ce19271d23..65f0167a6f 100644
--- a/src/onboarding/ha-onboarding.ts
+++ b/src/onboarding/ha-onboarding.ts
@@ -144,7 +144,6 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
.label=${""}
native-name
@value-changed=${this._languageChanged}
- inline-arrow
>
{
- selectElement.select(changedProps.has("dtstart") ? 0 : oldSelected);
- });
- }
}
if (
@@ -184,35 +170,16 @@ export class RecurrenceRuleEditor extends LitElement {
id="freq"
label=${this.hass.localize("ui.components.calendar.event.repeat.label")}
@selected=${this._onRepeatSelected}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
.value=${this._freq}
- >
-
- ${this.hass.localize("ui.components.calendar.event.repeat.freq.none")}
-
-
- ${this.hass.localize(
- "ui.components.calendar.event.repeat.freq.yearly"
- )}
-
-
- ${this.hass.localize(
- "ui.components.calendar.event.repeat.freq.monthly"
- )}
-
-
- ${this.hass.localize(
- "ui.components.calendar.event.repeat.freq.weekly"
- )}
-
-
- ${this.hass.localize(
- "ui.components.calendar.event.repeat.freq.daily"
- )}
-
-
+ .options=${["none", "yearly", "monthly", "weekly", "daily"].map(
+ (freq) => ({
+ value: freq,
+ label: this.hass.localize(
+ `ui.components.calendar.event.repeat.freq.${freq}` as LocalizeKeys
+ ),
+ })
+ )}
+ >
`;
}
@@ -227,18 +194,8 @@ export class RecurrenceRuleEditor extends LitElement {
)}
@selected=${this._onMonthlyDetailSelected}
.value=${this._monthlyRepeat || this._monthlyRepeatItems[0]?.value}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
- >
- ${this._monthlyRepeatItems!.map(
- (item) => html`
-
- ${item.label}
-
- `
- )}
- `
+ .options=${this._monthlyRepeatItems}
+ >`
: nothing}
`;
}
@@ -299,19 +256,13 @@ export class RecurrenceRuleEditor extends LitElement {
)}
.value=${this._end}
@selected=${this._onEndSelected}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${["never", "after", "on"].map((end) => ({
+ value: end,
+ label: this.hass.localize(
+ `ui.components.calendar.event.repeat.end.${end as RepeatEnd}`
+ ),
+ }))}
>
-
- ${this.hass.localize("ui.components.calendar.event.repeat.end.never")}
-
-
- ${this.hass.localize("ui.components.calendar.event.repeat.end.after")}
-
-
- ${this.hass.localize("ui.components.calendar.event.repeat.end.on")}
-
${this._end === "after"
? html`
@@ -360,8 +311,8 @@ export class RecurrenceRuleEditor extends LitElement {
this._interval = (e.target! as any).value;
}
- private _onRepeatSelected(e: CustomEvent>) {
- this._freq = (e.target as HaSelect).value as RepeatFrequency;
+ private _onRepeatSelected(e: CustomEvent<{ value: string }>) {
+ this._freq = e.detail.value as RepeatFrequency;
if (this._freq === "yearly") {
this._interval = 1;
@@ -370,12 +321,12 @@ export class RecurrenceRuleEditor extends LitElement {
this._weekday.clear();
this._computeWeekday();
}
- e.stopPropagation();
}
- private _onMonthlyDetailSelected(e: CustomEvent>) {
- e.stopPropagation();
- const selectedItem = this._monthlyRepeatItems[e.detail.index];
+ private _onMonthlyDetailSelected(e: CustomEvent<{ value: string }>) {
+ const selectedItem = this._monthlyRepeatItems.find(
+ (item) => item.value === e.detail.value
+ );
if (!selectedItem) {
return;
}
@@ -395,8 +346,8 @@ export class RecurrenceRuleEditor extends LitElement {
this.requestUpdate("_weekday");
}
- private _onEndSelected(e: CustomEvent>) {
- const end = (e.target as HaSelect).value as RepeatEnd;
+ private _onEndSelected(e: CustomEvent<{ value: string }>) {
+ const end = e.detail.value as RepeatEnd;
if (end === this._end) {
return;
}
diff --git a/src/panels/config/apps/app-view/config/supervisor-app-audio.ts b/src/panels/config/apps/app-view/config/supervisor-app-audio.ts
index 8c39d11d4e..a29ce05a64 100644
--- a/src/panels/config/apps/app-view/config/supervisor-app-audio.ts
+++ b/src/panels/config/apps/app-view/config/supervisor-app-audio.ts
@@ -1,11 +1,9 @@
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
-import { stopPropagation } from "../../../../../common/dom/stop_propagation";
import "../../../../../components/buttons/ha-progress-button";
import "../../../../../components/ha-alert";
import "../../../../../components/ha-card";
-import "../../../../../components/ha-list-item";
import "../../../../../components/ha-select";
import type {
HassioAddonDetails,
@@ -16,8 +14,8 @@ import type { HassioHardwareAudioDevice } from "../../../../../data/hassio/hardw
import { fetchHassioHardwareAudio } from "../../../../../data/hassio/hardware";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant } from "../../../../../types";
-import { suggestSupervisorAppRestart } from "../dialogs/suggestSupervisorAppRestart";
import { supervisorAppsStyle } from "../../resources/supervisor-apps-style";
+import { suggestSupervisorAppRestart } from "../dialogs/suggestSupervisorAppRestart";
@customElement("supervisor-app-audio")
class SupervisorAppAudio extends LitElement {
@@ -55,19 +53,13 @@ class SupervisorAppAudio extends LitElement {
"ui.panel.config.apps.configuration.audio.input"
)}
@selected=${this._setInputDevice}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
.value=${this._selectedInput!}
.disabled=${this.disabled}
+ .options=${this._inputDevices.map((item) => ({
+ value: item.device || "",
+ label: item.name,
+ }))}
>
- ${this._inputDevices.map(
- (item) => html`
-
- ${item.name}
-
- `
- )}
`}
${this._outputDevices &&
html` ({
+ value: item.device || "",
+ label: item.name,
+ }))}
>
- ${this._outputDevices.map(
- (item) => html`
- ${item.name}
- `
- )}
`}
@@ -116,6 +102,7 @@ class SupervisorAppAudio extends LitElement {
}
ha-select {
width: 100%;
+ display: block;
}
ha-select:last-child {
margin-top: var(--ha-space-2);
@@ -131,13 +118,13 @@ class SupervisorAppAudio extends LitElement {
}
}
- private _setInputDevice(ev): void {
- const device = ev.target.value;
+ private _setInputDevice(ev: CustomEvent<{ value: string }>): void {
+ const device = ev.detail.value;
this._selectedInput = device;
}
- private _setOutputDevice(ev): void {
- const device = ev.target.value;
+ private _setOutputDevice(ev: CustomEvent<{ value: string }>): void {
+ const device = ev.detail.value;
this._selectedOutput = device;
}
diff --git a/src/panels/config/automation/action/types/ha-automation-action-condition.ts b/src/panels/config/automation/action/types/ha-automation-action-condition.ts
index 9c99aceb1d..a1caca0371 100644
--- a/src/panels/config/automation/action/types/ha-automation-action-condition.ts
+++ b/src/panels/config/automation/action/types/ha-automation-action-condition.ts
@@ -2,13 +2,11 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../../common/dom/fire_event";
-import { stopPropagation } from "../../../../../common/dom/stop_propagation";
import { stringCompare } from "../../../../../common/string/compare";
import type { LocalizeFunc } from "../../../../../common/translations/localize";
import { CONDITION_ICONS } from "../../../../../components/ha-condition-icon";
-import "../../../../../components/ha-list-item";
+import "../../../../../components/ha-dropdown-item";
import "../../../../../components/ha-select";
-import type { HaSelect } from "../../../../../components/ha-select";
import {
DYNAMIC_PREFIX,
getValueFromDynamic,
@@ -85,37 +83,47 @@ export class HaConditionAction
this.action.condition
);
+ const value =
+ this.action.condition in this._conditionDescriptions
+ ? `${DYNAMIC_PREFIX}${this.action.condition}`
+ : this.action.condition;
+
+ let valueLabel = value;
+
+ const items = html`${this._processedTypes(
+ this._conditionDescriptions,
+ this.hass.localize
+ ).map(([opt, label, condition]) => {
+ const selected = value === opt;
+
+ if (selected) {
+ valueLabel = label;
+ }
+
+ return html`
+
+
+ ${label}
+
+ `;
+ })}`;
+
return html`
${this.inSidebar || (!this.inSidebar && !this.indent)
? html`
- ${this._processedTypes(
- this._conditionDescriptions,
- this.hass.localize
- ).map(
- ([opt, label, condition]) => html`
-
- ${label}
-
-
- `
- )}
+ ${items}
`
: nothing}
@@ -192,8 +200,8 @@ export class HaConditionAction
});
}
- private _typeChanged(ev: CustomEvent) {
- const type = (ev.target as HaSelect).value;
+ private _typeChanged(ev: CustomEvent<{ value: string }>) {
+ const type = ev.detail.value;
if (!type) {
return;
@@ -242,6 +250,7 @@ export class HaConditionAction
static styles = css`
ha-select {
margin-bottom: 24px;
+ display: block;
}
`;
}
diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-tag.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-tag.ts
index 224b9903d1..0119fe1002 100644
--- a/src/panels/config/automation/trigger/types/ha-automation-trigger-tag.ts
+++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-tag.ts
@@ -4,7 +4,6 @@ import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { caseInsensitiveStringCompare } from "../../../../../common/string/compare";
import "../../../../../components/ha-select";
-import "../../../../../components/ha-list-item";
import type { TagTrigger } from "../../../../../data/automation";
import type { Tag } from "../../../../../data/tag";
import { fetchTags } from "../../../../../data/tag";
@@ -42,16 +41,11 @@ export class HaTagTrigger extends LitElement implements TriggerElement {
.disabled=${this.disabled || this._tags.length === 0}
.value=${this.trigger.tag_id}
@selected=${this._tagChanged}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${this._tags.map((tag) => ({
+ value: tag.id,
+ label: tag.name || tag.id,
+ }))}
>
- ${this._tags.map(
- (tag) => html`
-
- ${tag.name || tag.id}
-
- `
- )}
`;
}
@@ -66,18 +60,18 @@ export class HaTagTrigger extends LitElement implements TriggerElement {
);
}
- private _tagChanged(ev) {
+ private _tagChanged(ev: CustomEvent<{ value: string }>) {
if (
- !ev.target.value ||
+ !ev.detail.value ||
!this._tags ||
- this.trigger.tag_id === ev.target.value
+ this.trigger.tag_id === ev.detail.value
) {
return;
}
fireEvent(this, "value-changed", {
value: {
...this.trigger,
- tag_id: ev.target.value,
+ tag_id: ev.detail.value,
},
});
}
diff --git a/src/panels/config/cloud/account/cloud-tts-pref.ts b/src/panels/config/cloud/account/cloud-tts-pref.ts
index 959fbb0fc6..b0602cfd93 100644
--- a/src/panels/config/cloud/account/cloud-tts-pref.ts
+++ b/src/panels/config/cloud/account/cloud-tts-pref.ts
@@ -1,12 +1,12 @@
-import { css, html, LitElement, nothing } from "lit";
import { mdiContentCopy } from "@mdi/js";
+import { css, 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 "../../../../components/ha-card";
+import { copyToClipboard } from "../../../../common/util/copy-clipboard";
import "../../../../components/ha-button";
+import "../../../../components/ha-card";
import "../../../../components/ha-language-picker";
-import "../../../../components/ha-list-item";
import "../../../../components/ha-select";
import "../../../../components/ha-svg-icon";
import "../../../../components/ha-switch";
@@ -19,9 +19,8 @@ import {
} from "../../../../data/cloud/tts";
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../../types";
-import { showTryTtsDialog } from "./show-dialog-cloud-tts-try";
-import { copyToClipboard } from "../../../../common/util/copy-clipboard";
import { showToast } from "../../../../util/toast";
+import { showTryTtsDialog } from "./show-dialog-cloud-tts-try";
export const getCloudTtsSupportedVoices = (
language: string,
@@ -96,13 +95,11 @@ export class CloudTTSPref extends LitElement {
.disabled=${this.savingPreferences}
.value=${defaultVoice[1]}
@selected=${this._handleVoiceChange}
+ .options=${voices.map((voice) => ({
+ value: voice.voiceId,
+ label: voice.voiceName,
+ }))}
>
- ${voices.map(
- (voice) =>
- html`
- ${voice.voiceName}
- `
- )}
@@ -134,16 +131,6 @@ export class CloudTTSPref extends LitElement {
`;
}
- protected updated(changedProps) {
- if (
- changedProps.has("cloudStatus") &&
- this.cloudStatus?.prefs.tts_default_voice?.[0] !==
- changedProps.get("cloudStatus")?.prefs.tts_default_voice?.[0]
- ) {
- this.renderRoot.querySelector("ha-select")?.layoutOptions();
- }
- }
-
protected willUpdate(changedProps) {
super.willUpdate(changedProps);
if (!this.hasUpdated) {
@@ -195,13 +182,13 @@ export class CloudTTSPref extends LitElement {
}
}
- private async _handleVoiceChange(ev) {
- if (ev.target.value === this.cloudStatus!.prefs.tts_default_voice[1]) {
+ private async _handleVoiceChange(ev: CustomEvent<{ value: string }>) {
+ if (ev.detail.value === this.cloudStatus!.prefs.tts_default_voice[1]) {
return;
}
this.savingPreferences = true;
const language = this.cloudStatus!.prefs.tts_default_voice[0];
- const voice = ev.target.value;
+ const voice = ev.detail.value;
try {
await updateCloudPref(this.hass, {
diff --git a/src/panels/config/cloud/account/dialog-cloud-tts-try.ts b/src/panels/config/cloud/account/dialog-cloud-tts-try.ts
index 1d0ecbdb0e..35f22fa16e 100644
--- a/src/panels/config/cloud/account/dialog-cloud-tts-try.ts
+++ b/src/panels/config/cloud/account/dialog-cloud-tts-try.ts
@@ -4,14 +4,13 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { storage } from "../../../../common/decorators/storage";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { computeStateDomain } from "../../../../common/entity/compute_state_domain";
import { computeStateName } from "../../../../common/entity/compute_state_name";
import { supportsFeature } from "../../../../common/entity/supports-feature";
-import { createCloseHeading } from "../../../../components/ha-dialog";
-import "../../../../components/ha-list-item";
-import "../../../../components/ha-select";
import "../../../../components/ha-button";
+import { createCloseHeading } from "../../../../components/ha-dialog";
+import "../../../../components/ha-select";
+import type { HaSelectOption } from "../../../../components/ha-select";
import "../../../../components/ha-textarea";
import type { HaTextArea } from "../../../../components/ha-textarea";
import { showAutomationEditor } from "../../../../data/automation";
@@ -60,6 +59,25 @@ export class DialogTryTts extends LitElement {
return nothing;
}
const target = this._target || "browser";
+
+ const targetOptions: HaSelectOption[] = Object.values(this.hass.states)
+ .filter(
+ (entity) =>
+ computeStateDomain(entity) === "media_player" &&
+ supportsFeature(entity, MediaPlayerEntityFeature.PLAY_MEDIA)
+ )
+ .map((entity) => ({
+ value: entity.entity_id,
+ label: computeStateName(entity),
+ }));
+
+ targetOptions.unshift({
+ value: "browser",
+ label: this.hass.localize(
+ "ui.panel.config.cloud.account.tts.dialog.target_browser"
+ ),
+ });
+
return html`
-
- ${this.hass.localize(
- "ui.panel.config.cloud.account.tts.dialog.target_browser"
- )}
-
- ${Object.values(this.hass.states)
- .filter(
- (entity) =>
- computeStateDomain(entity) === "media_player" &&
- supportsFeature(entity, MediaPlayerEntityFeature.PLAY_MEDIA)
- )
- .map(
- (entity) => html`
-
- ${computeStateName(entity)}
-
- `
- )}
) {
+ this._target = ev.detail.value;
this.requestUpdate("_target");
}
@@ -227,10 +225,9 @@ export class DialogTryTts extends LitElement {
}
ha-textarea,
ha-select {
- width: 100%;
- }
- ha-select {
+ display: block;
margin-top: 8px;
+ width: 100%;
}
`,
];
diff --git a/src/panels/config/energy/dialogs/dialog-energy-device-settings-water.ts b/src/panels/config/energy/dialogs/dialog-energy-device-settings-water.ts
index 7e2d625469..1d3c90145b 100644
--- a/src/panels/config/energy/dialogs/dialog-energy-device-settings-water.ts
+++ b/src/panels/config/energy/dialogs/dialog-energy-device-settings-water.ts
@@ -3,14 +3,12 @@ import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { stopPropagation } from "../../../../common/dom/stop_propagation";
import "../../../../components/entity/ha-entity-picker";
import "../../../../components/entity/ha-statistic-picker";
+import "../../../../components/ha-button";
import "../../../../components/ha-dialog";
import "../../../../components/ha-radio";
-import "../../../../components/ha-button";
import "../../../../components/ha-select";
-import "../../../../components/ha-list-item";
import type { DeviceConsumptionEnergyPreference } from "../../../../data/energy";
import { energyStatisticHelpUrl } from "../../../../data/energy";
import { getStatisticLabel } from "../../../../data/recorder";
@@ -95,6 +93,27 @@ export class DialogEnergyDeviceSettingsWater
const pickableUnit = this._volume_units?.join(", ") || "";
+ const includedInDeviceOptions = !this._possibleParents.length
+ ? [
+ {
+ value: "-",
+ disabled: true,
+ label: this.hass.localize(
+ "ui.panel.config.energy.device_consumption_water.dialog.no_upstream_devices"
+ ),
+ },
+ ]
+ : this._possibleParents.map((stat) => ({
+ value: stat.stat_consumption,
+ label:
+ stat.name ||
+ getStatisticLabel(
+ this.hass,
+ stat.stat_consumption,
+ this._params?.statsMetadata?.[stat.stat_consumption]
+ ),
+ }));
+
return html`
- ${!this._possibleParents.length
- ? html`
- ${this.hass.localize(
- "ui.panel.config.energy.device_consumption_water.dialog.no_upstream_devices"
- )}
- `
- : this._possibleParents.map(
- (stat) => html`
- ${stat.name ||
- getStatisticLabel(
- this.hass,
- stat.stat_consumption,
- this._params?.statsMetadata?.[stat.stat_consumption]
- )}
- `
- )}
) {
const newDevice = {
...this._device!,
- included_in_stat: ev.target!.value,
+ included_in_stat: ev.detail.value,
} as DeviceConsumptionEnergyPreference;
if (!newDevice.included_in_stat) {
delete newDevice.included_in_stat;
@@ -249,6 +246,7 @@ export class DialogEnergyDeviceSettingsWater
width: 100%;
}
ha-select {
+ display: block;
margin-top: 16px;
width: 100%;
}
diff --git a/src/panels/config/energy/dialogs/dialog-energy-device-settings.ts b/src/panels/config/energy/dialogs/dialog-energy-device-settings.ts
index afc2d732ae..9865f7c361 100644
--- a/src/panels/config/energy/dialogs/dialog-energy-device-settings.ts
+++ b/src/panels/config/energy/dialogs/dialog-energy-device-settings.ts
@@ -3,14 +3,13 @@ import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { stopPropagation } from "../../../../common/dom/stop_propagation";
import "../../../../components/entity/ha-entity-picker";
import "../../../../components/entity/ha-statistic-picker";
+import "../../../../components/ha-button";
import "../../../../components/ha-dialog";
import "../../../../components/ha-radio";
-import "../../../../components/ha-button";
import "../../../../components/ha-select";
-import "../../../../components/ha-list-item";
+import type { HaSelectOption } from "../../../../components/ha-select";
import type { DeviceConsumptionEnergyPreference } from "../../../../data/energy";
import { energyStatisticHelpUrl } from "../../../../data/energy";
import { getStatisticLabel } from "../../../../data/recorder";
@@ -104,6 +103,28 @@ export class DialogEnergyDeviceSettings
return nothing;
}
+ const includedInDeviceOptions: HaSelectOption[] = this._possibleParents
+ .length
+ ? this._possibleParents.map((stat) => ({
+ value: stat.stat_consumption,
+ label:
+ stat.name ||
+ getStatisticLabel(
+ this.hass,
+ stat.stat_consumption,
+ this._params?.statsMetadata?.[stat.stat_consumption]
+ ),
+ }))
+ : [
+ {
+ value: "-",
+ disabled: true,
+ label: this.hass.localize(
+ "ui.panel.config.energy.device_consumption.dialog.no_upstream_devices"
+ ),
+ },
+ ];
+
return html`
- ${!this._possibleParents.length
- ? html`
- ${this.hass.localize(
- "ui.panel.config.energy.device_consumption.dialog.no_upstream_devices"
- )}
- `
- : this._possibleParents.map(
- (stat) => html`
- ${stat.name ||
- getStatisticLabel(
- this.hass,
- stat.stat_consumption,
- this._params?.statsMetadata?.[stat.stat_consumption]
- )}
- `
- )}
) {
const newDevice = {
...this._device!,
- included_in_stat: ev.target!.value,
+ included_in_stat: ev.detail.value,
} as DeviceConsumptionEnergyPreference;
if (!newDevice.included_in_stat) {
delete newDevice.included_in_stat;
@@ -289,6 +288,7 @@ export class DialogEnergyDeviceSettings
width: 100%;
}
ha-select {
+ display: block;
margin-top: var(--ha-space-4);
width: 100%;
}
diff --git a/src/panels/config/entities/entity-registry-settings-editor.ts b/src/panels/config/entities/entity-registry-settings-editor.ts
index 18c9f179c1..599eabce1a 100644
--- a/src/panels/config/entities/entity-registry-settings-editor.ts
+++ b/src/panels/config/entities/entity-registry-settings-editor.ts
@@ -1,3 +1,4 @@
+import "@home-assistant/webawesome/dist/components/divider/divider";
import { mdiContentCopy, mdiRestore } from "@mdi/js";
import type { HassEntity } from "home-assistant-js-websocket";
import type { CSSResultGroup, PropertyValues } from "lit";
@@ -7,7 +8,6 @@ import { until } from "lit/directives/until";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { fireEvent } from "../../../common/dom/fire_event";
-import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeObjectId } from "../../../common/entity/compute_object_id";
import { supportsFeature } from "../../../common/entity/supports-feature";
@@ -22,6 +22,7 @@ import { copyToClipboard } from "../../../common/util/copy-clipboard";
import "../../../components/ha-alert";
import "../../../components/ha-area-picker";
import "../../../components/ha-color-picker";
+import "../../../components/ha-dropdown-item";
import "../../../components/ha-icon";
import "../../../components/ha-icon-button-next";
import "../../../components/ha-icon-picker";
@@ -424,34 +425,46 @@ export class EntityRegistrySettingsEditor extends LitElement {
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.device_class"
)}
- naturalMenuWidth
- fixedMenuPosition
@selected=${this._switchAsDomainChanged}
- @closed=${stopPropagation}
+ value=${this._switchAsLabel(
+ this._switchAsDomain,
+ this._deviceClass
+ )}
>
-
${domainToName(this.hass.localize, "switch")}
-
-
+
${this.hass.localize(
"ui.dialogs.entity_registry.editor.device_classes.switch.outlet"
)}
-
-
+
+
${this._switchAsDomainsSorted(
SWITCH_AS_DOMAINS,
this.hass.localize
).map(
(entry) => html`
-
+
${entry.label}
-
+
`
)}
`
@@ -460,19 +473,22 @@ export class EntityRegistrySettingsEditor extends LitElement {
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.switch_as_x"
)}
- .value=${this._switchAsDomain}
- naturalMenuWidth
- fixedMenuPosition
+ .value=${this._switchAsLabel(this._switchAsDomain)}
@selected=${this._switchAsDomainChanged}
- @closed=${stopPropagation}
>
-
+
${domainToName(this.hass.localize, "switch")}
-
-
+
+
${domainToName(this.hass.localize, domain)}
-
-
+
+
${this._switchAsDomainsSorted(
SWITCH_AS_DOMAINS,
this.hass.localize
@@ -480,9 +496,14 @@ export class EntityRegistrySettingsEditor extends LitElement {
domain === entry.domain
? nothing
: html`
-
+
${entry.label}
-
+
`
)}
@@ -513,12 +534,13 @@ export class EntityRegistrySettingsEditor extends LitElement {
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.device_class"
)}
- .value=${this._deviceClass}
- naturalMenuWidth
- fixedMenuPosition
+ .value=${this._deviceClass
+ ? this.hass.localize(
+ `ui.dialogs.entity_registry.editor.device_classes.${domain}.${this._deviceClass}`
+ )
+ : undefined}
clearable
@selected=${this._deviceClassChanged}
- @closed=${stopPropagation}
>
${this._deviceClassesSorted(
domain,
@@ -526,29 +548,39 @@ export class EntityRegistrySettingsEditor extends LitElement {
this.hass.localize
).map(
(entry) => html`
-
+
${entry.label}
-
+
`
)}
${this._deviceClassOptions[0].length &&
this._deviceClassOptions[1].length
- ? html``
- : ""}
+ ? html``
+ : nothing}
${this._deviceClassesSorted(
domain,
this._deviceClassOptions[1],
this.hass.localize
).map(
(entry) => html`
-
+
${entry.label}
-
+
`
)}
`
- : ""}
+ : nothing}
${domain === "number" &&
this._deviceClass &&
stateObj?.attributes.unit_of_measurement &&
@@ -560,20 +592,14 @@ export class EntityRegistrySettingsEditor extends LitElement {
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.unit_of_measurement"
)}
- .value=${stateObj.attributes.unit_of_measurement}
- naturalMenuWidth
- fixedMenuPosition
+ .value=${this._unit_of_measurement ||
+ stateObj.attributes.unit_of_measurement}
@selected=${this._unitChanged}
- @closed=${stopPropagation}
+ .options=${this._numberDeviceClassConvertibleUnits}
>
- ${this._numberDeviceClassConvertibleUnits.map(
- (unit: string) => html`
- ${unit}
- `
- )}
`
- : ""}
+ : nothing}
${domain === "lock"
? html`
`
- : ""}
+ : nothing}
${domain === "alarm_control_panel"
? html`
`
- : ""}
+ : nothing}
${domain === "calendar"
? html`
`
- : ""}
+ : nothing}
${domain === "sensor" &&
this._deviceClass &&
stateObj?.attributes.unit_of_measurement &&
@@ -628,20 +654,14 @@ export class EntityRegistrySettingsEditor extends LitElement {
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.unit_of_measurement"
)}
- .value=${stateObj.attributes.unit_of_measurement}
- naturalMenuWidth
- fixedMenuPosition
+ .value=${this._unit_of_measurement ||
+ stateObj.attributes.unit_of_measurement}
@selected=${this._unitChanged}
- @closed=${stopPropagation}
+ .options=${this._sensorDeviceClassConvertibleUnits}
>
- ${this._sensorDeviceClassConvertibleUnits.map(
- (unit: string) => html`
- ${unit}
- `
- )}
`
- : ""}
+ : nothing}
${domain === "sensor" &&
// Allow customizing the precision for a sensor with numerical device class,
// a unit of measurement or state class
@@ -657,116 +677,78 @@ export class EntityRegistrySettingsEditor extends LitElement {
.value=${this._precision == null
? "default"
: this._precision.toString()}
- naturalMenuWidth
- fixedMenuPosition
@selected=${this._precisionChanged}
- @closed=${stopPropagation}
+ .options=${[
+ {
+ value: "default",
+ label: this.hass.localize(
+ "ui.dialogs.entity_registry.editor.precision_default",
+ {
+ value: this._precisionLabel(
+ defaultPrecision,
+ stateObj?.state
+ ),
+ }
+ ),
+ },
+ ...PRECISIONS.map((precision) => ({
+ value: precision.toString(),
+ label: this._precisionLabel(precision, stateObj?.state),
+ })),
+ ]}
>
- ${this.hass.localize(
- "ui.dialogs.entity_registry.editor.precision_default",
- {
- value: this._precisionLabel(
- defaultPrecision,
- stateObj?.state
- ),
- }
- )}
- ${PRECISIONS.map(
- (precision) => html`
-
- ${this._precisionLabel(precision, stateObj?.state)}
-
- `
- )}
`
- : ""}
+ : nothing}
${domain === "weather"
? html`
- ${this._weatherConvertibleUnits?.precipitation_unit.map(
- (unit: string) => html`
- ${unit}
- `
- )}
- ${this._weatherConvertibleUnits?.pressure_unit.map(
- (unit: string) => html`
- ${unit}
- `
- )}
- ${this._weatherConvertibleUnits?.temperature_unit.map(
- (unit: string) => html`
- ${unit}
- `
- )}
- ${this._weatherConvertibleUnits?.visibility_unit.map(
- (unit: string) => html`
- ${unit}
- `
- )}
- ${this._weatherConvertibleUnits?.wind_speed_unit.map(
- (unit: string) => html`
- ${unit}
- `
- )}
`
- : ""}
+ : nothing}
`
- : ""}
+ : nothing}
({
+ value: num.toString(),
+ label: this.hass.localize(
+ ("ui.dialogs.entity_registry.editor.stream.stream_orientation_" +
+ num.toString()) as LocalizeKeys
+ ),
+ }))}
+ .value=${this._cameraPrefs.orientation.toString()}
>
- ${CAMERA_ORIENTATIONS.map((num) => {
- const localizeStr =
- "ui.dialogs.entity_registry.editor.stream.stream_orientation_" +
- num.toString();
- return html`
-
- ${this.hass.localize(localizeStr as LocalizeKeys)}
-
- `;
- })}
`
- : ""}
+ : nothing}
${this.helperConfigEntry &&
this.helperConfigEntry.supports_options &&
this.helperConfigEntry.domain !== "switch_as_x"
@@ -899,7 +876,7 @@ export class EntityRegistrySettingsEditor extends LitElement {
`
- : ""}
+ : nothing}
@@ -137,8 +131,8 @@ class DialogZHAChangeChannel extends LitElement implements HassDialog {
`;
}
- private _newChannelChosen(evt: Event): void {
- const value: string = (evt.target! as HTMLSelectElement).value;
+ private _newChannelChosen(ev: CustomEvent<{ value: string }>): void {
+ const value: string = ev.detail.value;
this._newChannel = value === "auto" ? "auto" : parseInt(value, 10);
}
diff --git a/src/panels/config/integrations/integration-panels/zha/zha-cluster-attributes.ts b/src/panels/config/integrations/integration-panels/zha/zha-cluster-attributes.ts
index fed4bd7589..cce81a9452 100644
--- a/src/panels/config/integrations/integration-panels/zha/zha-cluster-attributes.ts
+++ b/src/panels/config/integrations/integration-panels/zha/zha-cluster-attributes.ts
@@ -1,11 +1,9 @@
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
-import { stopPropagation } from "../../../../../common/dom/stop_propagation";
import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/buttons/ha-progress-button";
import "../../../../../components/ha-card";
-import "../../../../../components/ha-list-item";
import "../../../../../components/ha-select";
import "../../../../../components/ha-textfield";
import { forwardHaptic } from "../../../../../data/haptics";
@@ -22,7 +20,7 @@ import {
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant } from "../../../../../types";
import { formatAsPaddedHex } from "./functions";
-import type { ItemSelectedEvent, SetAttributeServiceData } from "./types";
+import type { SetAttributeServiceData } from "./types";
@customElement("zha-cluster-attributes")
export class ZHAClusterAttributes extends LitElement {
@@ -70,22 +68,16 @@ export class ZHAClusterAttributes extends LitElement {
class="menu"
.value=${String(this._selectedAttributeId)}
@selected=${this._selectedAttributeChanged}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${this._attributes.map((entry) => ({
+ value: String(entry.id),
+ label: `${entry.name} (id: ${formatAsPaddedHex(entry.id)})`,
+ }))}
>
- ${this._attributes.map(
- (entry) => html`
-
- ${`${entry.name} (id: ${formatAsPaddedHex(entry.id)})`}
-
- `
- )}
${this._selectedAttributeId !== undefined
? this._renderAttributeInteractions()
- : ""}
+ : nothing}
`;
}
@@ -221,8 +213,10 @@ export class ZHAClusterAttributes extends LitElement {
}
}
- private _selectedAttributeChanged(event: ItemSelectedEvent): void {
- this._selectedAttributeId = Number(event.target!.value);
+ private _selectedAttributeChanged(
+ event: CustomEvent<{ value: string }>
+ ): void {
+ this._selectedAttributeId = Number(event.detail.value);
this._attributeValue = "";
}
diff --git a/src/panels/config/integrations/integration-panels/zha/zha-cluster-commands.ts b/src/panels/config/integrations/integration-panels/zha/zha-cluster-commands.ts
index 688a8588cb..c8cfd8cc5b 100644
--- a/src/panels/config/integrations/integration-panels/zha/zha-cluster-commands.ts
+++ b/src/panels/config/integrations/integration-panels/zha/zha-cluster-commands.ts
@@ -1,11 +1,9 @@
import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
-import { stopPropagation } from "../../../../../common/dom/stop_propagation";
import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/ha-card";
import "../../../../../components/ha-form/ha-form";
-import "../../../../../components/ha-list-item";
import "../../../../../components/ha-select";
import "../../../../../components/ha-textfield";
import type { Cluster, Command, ZHADevice } from "../../../../../data/zha";
@@ -64,17 +62,11 @@ export class ZHAClusterCommands extends LitElement {
class="menu"
.value=${String(this._selectedCommandId)}
@selected=${this._selectedCommandChanged}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${this._commands.map((entry) => ({
+ value: String(entry.id),
+ label: `${entry.name} (id: ${formatAsPaddedHex(entry.id)})`,
+ }))}
>
- ${this._commands.map(
- (entry) => html`
-
- ${entry.name} (id: ${formatAsPaddedHex(entry.id)})
-
- `
- )}
${this._selectedCommandId !== undefined
@@ -179,8 +171,8 @@ export class ZHAClusterCommands extends LitElement {
this._computeIssueClusterCommandServiceData();
}
- private _selectedCommandChanged(event): void {
- this._selectedCommandId = Number(event.target.value);
+ private _selectedCommandChanged(event: CustomEvent<{ value: string }>): void {
+ this._selectedCommandId = Number(event.detail.value);
this._issueClusterCommandServiceData =
this._computeIssueClusterCommandServiceData();
}
diff --git a/src/panels/config/integrations/integration-panels/zha/zha-device-binding.ts b/src/panels/config/integrations/integration-panels/zha/zha-device-binding.ts
index f2e17027ed..98507d8597 100644
--- a/src/panels/config/integrations/integration-panels/zha/zha-device-binding.ts
+++ b/src/panels/config/integrations/integration-panels/zha/zha-device-binding.ts
@@ -1,16 +1,13 @@
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
-import { stopPropagation } from "../../../../../common/dom/stop_propagation";
import "../../../../../components/buttons/ha-progress-button";
import "../../../../../components/ha-card";
import "../../../../../components/ha-select";
-import "../../../../../components/ha-list-item";
import type { ZHADevice } from "../../../../../data/zha";
import { bindDevices, unbindDevices } from "../../../../../data/zha";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant } from "../../../../../types";
-import type { ItemSelectedEvent } from "./types";
@customElement("zha-device-binding-control")
export class ZHADeviceBindingControl extends LitElement {
@@ -44,19 +41,13 @@ export class ZHADeviceBindingControl extends LitElement {
class="menu"
.value=${String(this._bindTargetIndex)}
@selected=${this._bindTargetIndexChanged}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${this.bindableDevices.map((device, idx) => ({
+ value: String(idx),
+ label: device.user_given_name
+ ? device.user_given_name
+ : device.name,
+ }))}
>
- ${this.bindableDevices.map(
- (device, idx) => html`
-
- ${device.user_given_name
- ? device.user_given_name
- : device.name}
-
- `
- )}
@@ -81,8 +72,8 @@ export class ZHADeviceBindingControl extends LitElement {
`;
}
- private _bindTargetIndexChanged(event: ItemSelectedEvent): void {
- this._bindTargetIndex = Number(event.target!.value);
+ private _bindTargetIndexChanged(event: CustomEvent<{ value: string }>): void {
+ this._bindTargetIndex = Number(event.detail.value);
this._deviceToBind =
this._bindTargetIndex === -1
? undefined
diff --git a/src/panels/config/integrations/integration-panels/zha/zha-group-binding.ts b/src/panels/config/integrations/integration-panels/zha/zha-group-binding.ts
index 59142d155a..3b57f46237 100644
--- a/src/panels/config/integrations/integration-panels/zha/zha-group-binding.ts
+++ b/src/panels/config/integrations/integration-panels/zha/zha-group-binding.ts
@@ -1,13 +1,11 @@
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
-import { customElement, property, state, query } from "lit/decorators";
+import { customElement, property, query, state } from "lit/decorators";
import type { HASSDomEvent } from "../../../../../common/dom/fire_event";
-import { stopPropagation } from "../../../../../common/dom/stop_propagation";
import "../../../../../components/buttons/ha-progress-button";
import type { SelectionChangedEvent } from "../../../../../components/data-table/ha-data-table";
import "../../../../../components/ha-card";
import "../../../../../components/ha-select";
-import "../../../../../components/ha-list-item";
import type { Cluster, ZHADevice, ZHAGroup } from "../../../../../data/zha";
import {
bindDeviceToGroup,
@@ -16,7 +14,6 @@ import {
} from "../../../../../data/zha";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant } from "../../../../../types";
-import type { ItemSelectedEvent } from "./types";
import "./zha-clusters-data-table";
import type { ZHAClustersDataTable } from "./zha-clusters-data-table";
@@ -64,16 +61,11 @@ export class ZHAGroupBindingControl extends LitElement {
class="menu"
.value=${String(this._bindTargetIndex)}
@selected=${this._bindTargetIndexChanged}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${this.groups.map((group, idx) => ({
+ value: String(idx),
+ label: group.name,
+ }))}
>
- ${this.groups.map(
- (group, idx) =>
- html`${group.name} `
- )}
@@ -109,8 +101,8 @@ export class ZHAGroupBindingControl extends LitElement {
`;
}
- private _bindTargetIndexChanged(event: ItemSelectedEvent): void {
- this._bindTargetIndex = Number(event.target!.value);
+ private _bindTargetIndexChanged(event: CustomEvent<{ value: string }>): void {
+ this._bindTargetIndex = Number(event.detail.value);
this._groupToBind =
this._bindTargetIndex === -1
? undefined
diff --git a/src/panels/config/integrations/integration-panels/zha/zha-manage-clusters.ts b/src/panels/config/integrations/integration-panels/zha/zha-manage-clusters.ts
index 8f8cc46c70..814345de70 100644
--- a/src/panels/config/integrations/integration-panels/zha/zha-manage-clusters.ts
+++ b/src/panels/config/integrations/integration-panels/zha/zha-manage-clusters.ts
@@ -2,9 +2,7 @@ import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { cache } from "lit/directives/cache";
-import { stopPropagation } from "../../../../../common/dom/stop_propagation";
import "../../../../../components/ha-card";
-import "../../../../../components/ha-list-item";
import "../../../../../components/ha-select";
import "../../../../../components/ha-tab-group";
import "../../../../../components/ha-tab-group-tab";
@@ -77,17 +75,11 @@ export class ZHAManageClusters extends LitElement {
class="menu"
.value=${String(this._selectedClusterIndex)}
@selected=${this._selectedClusterChanged}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${this._clusters.map((entry, idx) => ({
+ value: String(idx),
+ label: computeClusterKey(entry),
+ }))}
>
- ${this._clusters.map(
- (entry, idx) => html`
- ${computeClusterKey(entry)}
- `
- )}
${this._selectedCluster
@@ -155,8 +147,8 @@ export class ZHAManageClusters extends LitElement {
this._currTab = newTab;
}
- private _selectedClusterChanged(event): void {
- this._selectedClusterIndex = Number(event.target!.value);
+ private _selectedClusterChanged(event: CustomEvent<{ value: string }>): void {
+ this._selectedClusterIndex = Number(event.detail.value);
this._selectedCluster = this._clusters[this._selectedClusterIndex];
}
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-door-lock.ts b/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-door-lock.ts
index 530d7b17b8..b1f99beb6c 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-door-lock.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-door-lock.ts
@@ -5,7 +5,6 @@ import type { HaProgressButton } from "../../../../../../components/buttons/ha-p
import "../../../../../../components/ha-alert";
import "../../../../../../components/ha-button";
import "../../../../../../components/ha-formfield";
-import "../../../../../../components/ha-list-item";
import "../../../../../../components/ha-select";
import "../../../../../../components/ha-spinner";
import "../../../../../../components/ha-switch";
@@ -126,16 +125,13 @@ class ZWaveJSCapabilityDoorLock extends LitElement {
)}
.value=${this._currentDoorLockMode?.toString() ?? ""}
@selected=${this._doorLockModeChanged}
+ .options=${supportedDoorLockModes.map((mode) => ({
+ value: mode.toString(),
+ label: this.hass.localize(
+ `ui.panel.config.zwave_js.node_installer.capability_controls.door_lock.modes.${mode}`
+ ),
+ }))}
>
- ${supportedDoorLockModes.map(
- (mode) => html`
-
- ${this.hass.localize(
- `ui.panel.config.zwave_js.node_installer.capability_controls.door_lock.modes.${mode}`
- )}
-
- `
- )}
@@ -145,16 +141,13 @@ class ZWaveJSCapabilityDoorLock extends LitElement {
)}
.value=${this._configuration.operationType.toString()}
@selected=${this._operationTypeChanged}
+ .options=${this._capabilities.supportedOperationTypes.map((type) => ({
+ value: type.toString(),
+ label: this.hass.localize(
+ `ui.panel.config.zwave_js.node_installer.capability_controls.door_lock.operation_types.${type}`
+ ),
+ }))}
>
- ${this._capabilities.supportedOperationTypes.map(
- (type) => html`
-
- ${this.hass.localize(
- `ui.panel.config.zwave_js.node_installer.capability_controls.door_lock.operation_types.${type}`
- )}
-
- `
- )}
@@ -346,9 +339,8 @@ class ZWaveJSCapabilityDoorLock extends LitElement {
);
}
- private _operationTypeChanged(ev: CustomEvent) {
- const target = ev.target as HTMLSelectElement;
- const newType = parseInt(target.value);
+ private _operationTypeChanged(ev: CustomEvent<{ value: string }>) {
+ const newType = parseInt(ev.detail.value);
if (this._configuration) {
this._configuration = {
...this._configuration,
@@ -393,9 +385,8 @@ class ZWaveJSCapabilityDoorLock extends LitElement {
}
}
- private _doorLockModeChanged(ev: CustomEvent) {
- const target = ev.target as HTMLSelectElement;
- this._currentDoorLockMode = parseInt(target.value) as DoorLockMode;
+ private _doorLockModeChanged(ev: CustomEvent<{ value: string }>) {
+ this._currentDoorLockMode = parseInt(ev.detail.value) as DoorLockMode;
}
private async _saveConfig(ev: CustomEvent) {
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-multilevel-switch.ts b/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-multilevel-switch.ts
index 60371c449f..8ba633b078 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-multilevel-switch.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-multilevel-switch.ts
@@ -1,12 +1,10 @@
-import { LitElement, css, html } from "lit";
+import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../../../components/buttons/ha-progress-button";
import type { HaProgressButton } from "../../../../../../components/buttons/ha-progress-button";
import "../../../../../../components/ha-alert";
import "../../../../../../components/ha-formfield";
-import "../../../../../../components/ha-list-item";
import "../../../../../../components/ha-select";
-import type { HaSelect } from "../../../../../../components/ha-select";
import "../../../../../../components/ha-switch";
import type { HaSwitch } from "../../../../../../components/ha-switch";
import "../../../../../../components/ha-textfield";
@@ -35,6 +33,8 @@ class ZWaveJSCapabilityMultiLevelSwitch extends LitElement {
@state() private _error?: string;
+ @state() private _direction = "up";
+
protected render() {
return html`
@@ -44,23 +44,28 @@ class ZWaveJSCapabilityMultiLevelSwitch extends LitElement {
${this._error
? html`${this._error}`
- : ""}
+ : nothing}
- ${this.hass.localize(
- "ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.up"
- )}
- ${this.hass.localize(
- "ui.panel.config.zwave_js.node_installer.capability_controls.multilevel_switch.down"
- )}
) {
+ this._direction = ev.detail.value;
+ }
+
static styles = css`
ha-select,
ha-formfield,
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-thermostat-setback.ts b/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-thermostat-setback.ts
index 53c7689ad2..152cce7941 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-thermostat-setback.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/capability-controls/zwave_js-capability-control-thermostat-setback.ts
@@ -1,12 +1,10 @@
-import { LitElement, css, html } from "lit";
+import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import "../../../../../../components/buttons/ha-progress-button";
import type { HaProgressButton } from "../../../../../../components/buttons/ha-progress-button";
import "../../../../../../components/ha-alert";
import "../../../../../../components/ha-button";
-import "../../../../../../components/ha-list-item";
import "../../../../../../components/ha-select";
-import type { HaSelect } from "../../../../../../components/ha-select";
import "../../../../../../components/ha-textfield";
import type { HaTextField } from "../../../../../../components/ha-textfield";
import type { DeviceRegistryEntry } from "../../../../../../data/device/device_registry";
@@ -37,13 +35,12 @@ class ZWaveJSCapabilityThermostatSetback extends LitElement {
@state() private _disableSetbackState = false;
- @query("#setback_type") private _setbackTypeInput!: HaSelect;
+ @state() private _setbackType = "0";
+
+ @state() private _setbackSpecialType?: string;
@query("#setback_state") private _setbackStateInput!: HaTextField;
- @query("#setback_special_state")
- private _setbackSpecialStateSelect!: HaSelect;
-
@state() private _error?: string;
@state() private _loading = true;
@@ -57,23 +54,21 @@ class ZWaveJSCapabilityThermostatSetback extends LitElement {
${this._error
? html`${this._error}`
- : ""}
+ : nothing}
({
+ value: String(index),
+ label: this.hass.localize(
+ `ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_type.${translationKey}`
+ ),
+ }))}
>
- ${SETBACK_TYPE_OPTIONS.map(
- (translationKey, index) =>
- html`
- ${this.hass.localize(
- `ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_type.${translationKey}`
- )}
- `
- )}
-
- ${Object.entries(SpecialState).map(
- ([translationKey, value]) =>
- html`
- ${this.hass.localize(
- `ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_special_state.${translationKey}`
- )}
- `
+ .value=${this._setbackSpecialType}
+ clearable
+ .options=${Object.entries(SpecialState).map(
+ ([translationKey, value]) => ({
+ value: value,
+ label: this.hass.localize(
+ `ui.panel.config.zwave_js.node_installer.capability_controls.thermostat_setback.setback_special_state.${translationKey}`
+ ),
+ })
)}
+ >
@@ -144,12 +140,12 @@ class ZWaveJSCapabilityThermostatSetback extends LitElement {
true
)) as { setbackType: number; setbackState: number | SpecialState };
- this._setbackTypeInput.value = String(setbackType);
+ this._setbackType = String(setbackType);
if (typeof setbackState === "number") {
this._setbackStateInput.value = String(setbackState);
- this._setbackSpecialStateSelect.value = "";
+ this._setbackSpecialType = undefined;
} else {
- this._setbackSpecialStateSelect.value = setbackState;
+ this._setbackSpecialType = setbackState;
}
} catch (err) {
this._error = this.hass.localize(
@@ -161,8 +157,9 @@ class ZWaveJSCapabilityThermostatSetback extends LitElement {
this._loading = false;
}
- private _changeSpecialState() {
- this._disableSetbackState = !!this._setbackSpecialStateSelect.value;
+ private _changeSpecialState(ev: CustomEvent<{ value: string }>) {
+ this._disableSetbackState = !ev.detail.value;
+ this._setbackSpecialType = ev.detail.value;
}
private async _saveSetback(ev: CustomEvent) {
@@ -170,11 +167,11 @@ class ZWaveJSCapabilityThermostatSetback extends LitElement {
button.progress = true;
this._error = undefined;
- const setbackType = this._setbackTypeInput.value;
+ const setbackType = this._setbackType;
let setbackState: number | string = Number(this._setbackStateInput.value);
- if (this._setbackSpecialStateSelect.value) {
- setbackState = this._setbackSpecialStateSelect.value;
+ if (this._setbackSpecialType) {
+ setbackState = this._setbackSpecialType;
}
try {
@@ -204,6 +201,10 @@ class ZWaveJSCapabilityThermostatSetback extends LitElement {
this._loadSetback();
}
+ private _setbackTypeChanged(ev: CustomEvent<{ value: string }>) {
+ this._setbackType = ev.detail.value;
+ }
+
static styles = css`
:host {
display: flex;
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-custom-param.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-custom-param.ts
index 948864acf0..3002ebb335 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-custom-param.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-custom-param.ts
@@ -1,17 +1,16 @@
-import { LitElement, html, css, nothing } from "lit";
-import { customElement, property, state } from "lit/decorators";
import { mdiCloseCircle } from "@mdi/js";
-import "../../../../../components/ha-textfield";
-import "../../../../../components/ha-select";
+import { LitElement, css, html, nothing } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import { fireEvent } from "../../../../../common/dom/fire_event";
import "../../../../../components/ha-button";
+import "../../../../../components/ha-select";
import "../../../../../components/ha-spinner";
-import "../../../../../components/ha-list-item";
-import type { HomeAssistant } from "../../../../../types";
+import "../../../../../components/ha-textfield";
import {
getZwaveNodeRawConfigParameter,
setZwaveNodeRawConfigParameter,
} from "../../../../../data/zwave_js";
-import { fireEvent } from "../../../../../common/dom/fire_event";
+import type { HomeAssistant } from "../../../../../types";
@customElement("zwave_js-custom-param")
class ZWaveJSCustomParam extends LitElement {
@@ -48,10 +47,8 @@ class ZWaveJSCustomParam extends LitElement {
)}
.value=${String(this._valueSize)}
@selected=${this._customValueSizeChanged}
+ .options=${["1", "2", "4"]}
>
- 1
- 2
- 4
- ${this.hass.localize(
- "ui.panel.config.zwave_js.node_config.signed"
- )}
- ${this.hass.localize(
- "ui.panel.config.zwave_js.node_config.unsigned"
- )}
- ${this.hass.localize(
- "ui.panel.config.zwave_js.node_config.enumerated"
- )}
- ${this.hass.localize(
- "ui.panel.config.zwave_js.node_config.bitfield"
- )}
@@ -129,18 +132,16 @@ class ZWaveJSCustomParam extends LitElement {
);
}
- private _customValueSizeChanged(ev: Event) {
- this._valueSize =
- this._tryParseNumber((ev.target as HTMLSelectElement).value) ?? 1;
+ private _customValueSizeChanged(ev: CustomEvent<{ value: string }>) {
+ this._valueSize = this._tryParseNumber(ev.detail.value) ?? 1;
}
private _customValueChanged(ev: Event) {
this._value = this._tryParseNumber((ev.target as HTMLInputElement).value);
}
- private _customValueFormatChanged(ev: Event) {
- this._valueFormat =
- this._tryParseNumber((ev.target as HTMLSelectElement).value) ?? 0;
+ private _customValueFormatChanged(ev: CustomEvent<{ value: string }>) {
+ this._valueFormat = this._tryParseNumber(ev.detail.value) ?? 0;
}
private async _getCustomConfigValue() {
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-logs.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-logs.ts
index 9621277490..a327cd2369 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-logs.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-logs.ts
@@ -5,7 +5,6 @@ import { css, html, LitElement } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { capitalizeFirstLetter } from "../../../../../common/string/capitalize-first-letter";
import "../../../../../components/ha-icon-button";
-import "../../../../../components/ha-list-item";
import "../../../../../components/ha-select";
import type { ZWaveJSLogConfig } from "../../../../../data/zwave_js";
import {
@@ -84,13 +83,18 @@ class ZWaveJSLogs extends SubscribeMixin(LitElement) {
)}
.value=${this._logConfig.level}
@selected=${this._dropdownSelected}
+ .options=${[
+ "error",
+ "warn",
+ "info",
+ "verbose",
+ "debug",
+ "silly",
+ ].map((level) => ({
+ value: level,
+ label: capitalizeFirstLetter(level),
+ }))}
>
- Error
- Warn
- Info
- Verbose
- Debug
- Silly
`
: ""}
@@ -133,11 +137,11 @@ class ZWaveJSLogs extends SubscribeMixin(LitElement) {
);
}
- private _dropdownSelected(ev) {
+ private _dropdownSelected(ev: CustomEvent<{ value: string }>) {
if (ev.target === undefined || this._logConfig === undefined) {
return;
}
- const selected = ev.target.value;
+ const selected = ev.detail.value;
if (this._logConfig.level === selected) {
return;
}
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts
index de215f4fc8..eedea0ab47 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts
@@ -17,7 +17,6 @@ import type { HaProgressButton } from "../../../../../components/buttons/ha-prog
import "../../../../../components/ha-alert";
import "../../../../../components/ha-card";
import "../../../../../components/ha-generic-picker";
-import "../../../../../components/ha-list-item";
import type { PickerComboBoxItem } from "../../../../../components/ha-picker-combo-box";
import "../../../../../components/ha-select";
import "../../../../../components/ha-selector/ha-selector-boolean";
@@ -374,7 +373,6 @@ class ZWaveJSNodeConfig extends LitElement {
return html`
${labelAndDescription}
- ${Object.entries(item.metadata.states).map(
- ([key, entityState]) => html`
- ${entityState}
- `
+ .options=${Object.entries(item.metadata.states).map(
+ ([key, entityState]) => ({
+ value: key,
+ label: entityState,
+ })
)}
+ >
`;
}
@@ -457,8 +456,8 @@ class ZWaveJSNodeConfig extends LitElement {
this._updateConfigParameter(ev.target, ev.detail.value ? 1 : 0);
}
- private _dropdownSelected(ev) {
- this._handleEnumeratedPickerValueChanged(ev, ev.target.value);
+ private _dropdownSelected(ev: CustomEvent<{ value: string }>) {
+ this._handleEnumeratedPickerValueChanged(ev, ev.detail.value);
}
private _pickerValueChanged(ev) {
@@ -469,7 +468,7 @@ class ZWaveJSNodeConfig extends LitElement {
if (ev.target === undefined || this._config![ev.target.key] === undefined) {
return;
}
- if (this._config![ev.target.key].value?.toString() === value) {
+ if (this._config![ev.target.key].value === value) {
return;
}
this._setResult(ev.target.key, undefined);
diff --git a/src/panels/config/storage/dialog-move-datadisk.ts b/src/panels/config/storage/dialog-move-datadisk.ts
index b6ff482365..aabb280814 100644
--- a/src/panels/config/storage/dialog-move-datadisk.ts
+++ b/src/panels/config/storage/dialog-move-datadisk.ts
@@ -3,10 +3,8 @@ import { css, 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 { stopPropagation } from "../../../common/dom/stop_propagation";
-import "../../../components/ha-dialog";
import "../../../components/ha-button";
-import "../../../components/ha-list-item";
+import "../../../components/ha-dialog";
import "../../../components/ha-select";
import "../../../components/ha-spinner";
import {
@@ -132,26 +130,18 @@ class MoveDatadiskDialog extends LitElement {
"ui.panel.config.storage.datadisk.select_device"
)}
@selected=${this._selectDevice}
- @closed=${stopPropagation}
- dialogInitialFocus
- fixedMenuPosition
- >
- ${this._disks.map(
- (disk) =>
- html`
- ${disk.vendor} ${disk.model}
-
- ${this.hass.localize(
- "ui.panel.config.storage.datadisk.extra_information",
- {
- size: bytesToString(disk.size),
- serial: disk.serial,
- }
- )}
-
- `
- )}
-
+ .options=${this._disks.map((disk) => ({
+ value: disk.id,
+ label: `${disk.vendor} ${disk.model}`,
+ secondary: this.hass.localize(
+ "ui.panel.config.storage.datadisk.extra_information",
+ {
+ size: bytesToString(disk.size),
+ serial: disk.serial,
+ }
+ ),
+ }))}
+ >
): void {
+ this._selectedDevice = ev.detail.value;
}
private async _moveDatadisk() {
diff --git a/src/panels/lovelace/components/hui-action-editor.ts b/src/panels/lovelace/components/hui-action-editor.ts
index dbac50d2d0..2dcfdeb33d 100644
--- a/src/panels/lovelace/components/hui-action-editor.ts
+++ b/src/panels/lovelace/components/hui-action-editor.ts
@@ -1,19 +1,15 @@
-import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
-import { customElement, property, query } from "lit/decorators";
-import { refine } from "superstruct";
+import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
+import { refine } from "superstruct";
import { fireEvent } from "../../../common/dom/fire_event";
-import { stopPropagation } from "../../../common/dom/stop_propagation";
import "../../../components/ha-assist-pipeline-picker";
import type {
HaFormSchema,
SchemaUnion,
} from "../../../components/ha-form/types";
import "../../../components/ha-help-tooltip";
-import "../../../components/ha-list-item";
import "../../../components/ha-navigation-picker";
-import type { HaSelect } from "../../../components/ha-select";
import "../../../components/ha-service-control";
import type {
ActionConfig,
@@ -92,8 +88,6 @@ export class HuiActionEditor extends LitElement {
@property({ attribute: false })
public context?: ActionRelatedContext;
- @query("ha-select") private _select!: HaSelect;
-
get _navigation_path(): string {
const config = this.config as NavigateActionConfig | undefined;
return config?.navigation_path || "";
@@ -136,15 +130,6 @@ export class HuiActionEditor extends LitElement {
]
);
- protected updated(changedProperties: PropertyValues) {
- super.updated(changedProperties);
- if (changedProperties.has("defaultAction")) {
- if (changedProperties.get("defaultAction") !== this.defaultAction) {
- this._select.layoutOptions();
- }
- }
- }
-
protected render() {
if (!this.hass) {
return nothing;
@@ -165,29 +150,28 @@ export class HuiActionEditor extends LitElement {
.configValue=${"action"}
@selected=${this._actionPicked}
.value=${action}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${[
+ {
+ value: "default",
+ label: `${this.hass!.localize(
+ "ui.panel.lovelace.editor.action-editor.actions.default_action"
+ )}
+ ${
+ this.defaultAction
+ ? ` (${this.hass!.localize(
+ `ui.panel.lovelace.editor.action-editor.actions.${this.defaultAction}`
+ ).toLowerCase()})`
+ : ""
+ }`,
+ },
+ ...actions.map((actn) => ({
+ value: actn,
+ label: this.hass!.localize(
+ `ui.panel.lovelace.editor.action-editor.actions.${actn}`
+ ),
+ })),
+ ]}
>
-
- ${this.hass!.localize(
- "ui.panel.lovelace.editor.action-editor.actions.default_action"
- )}
- ${this.defaultAction
- ? ` (${this.hass!.localize(
- `ui.panel.lovelace.editor.action-editor.actions.${this.defaultAction}`
- ).toLowerCase()})`
- : nothing}
-
- ${actions.map(
- (actn) => html`
-
- ${this.hass!.localize(
- `ui.panel.lovelace.editor.action-editor.actions.${actn}`
- )}
-
- `
- )}
${this.tooltipText
? html`
@@ -249,7 +233,7 @@ export class HuiActionEditor extends LitElement {
`;
}
- private _actionPicked(ev): void {
+ private _actionPicked(ev: CustomEvent<{ value: string }>): void {
ev.stopPropagation();
if (!this.hass) {
return;
@@ -260,7 +244,7 @@ export class HuiActionEditor extends LitElement {
action = "perform-action";
}
- const value = ev.target.value;
+ const value = ev.detail.value;
if (action === value) {
return;
diff --git a/src/panels/lovelace/editor/hui-picture-elements-card-row-editor.ts b/src/panels/lovelace/editor/hui-picture-elements-card-row-editor.ts
index 0db7f1e74e..d285cf51e0 100644
--- a/src/panels/lovelace/editor/hui-picture-elements-card-row-editor.ts
+++ b/src/panels/lovelace/editor/hui-picture-elements-card-row-editor.ts
@@ -1,13 +1,18 @@
-import { mdiClose, mdiContentDuplicate, mdiPencil } from "@mdi/js";
+import {
+ mdiClose,
+ mdiContentDuplicate,
+ mdiPencil,
+ mdiPlaylistPlus,
+} from "@mdi/js";
import deepClone from "deep-clone-simple";
import { LitElement, css, html, nothing } from "lit";
-import { customElement, property, query } from "lit/decorators";
+import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../common/dom/fire_event";
-import { stopPropagation } from "../../../common/dom/stop_propagation";
+import "../../../components/ha-button";
+import "../../../components/ha-dropdown";
+import type { HaDropdownSelectEvent } from "../../../components/ha-dropdown";
+import "../../../components/ha-dropdown-item";
import "../../../components/ha-icon-button";
-import "../../../components/ha-list-item";
-import "../../../components/ha-select";
-import type { HaSelect } from "../../../components/ha-select";
import "../../../components/ha-svg-icon";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../types";
@@ -47,8 +52,6 @@ export class HuiPictureElementsCardRowEditor extends LitElement {
@property({ attribute: false }) public elements?: LovelaceElementConfig[];
- @query("ha-select") private _select!: HaSelect;
-
protected render() {
if (!this.elements || !this.hass) {
return nothing;
@@ -104,26 +107,23 @@ export class HuiPictureElementsCardRowEditor extends LitElement {
`
)}
-
+
+
+
+ ${this.hass.localize(
+ "ui.panel.lovelace.editor.card.picture-elements.new_element"
+ )}
+
${elementTypes.map(
(element) => html`
- ${this.hass?.localize(
+
+ ${this.hass?.localize(
`ui.panel.lovelace.editor.card.picture-elements.element_types.${element}`
- )}
+ ) || element}
+
`
)}
-
+
`;
}
@@ -177,8 +177,8 @@ export class HuiPictureElementsCardRowEditor extends LitElement {
return element.title ?? "Unknown type";
}
- private async _addElement(ev): Promise {
- const value = ev.target!.value;
+ private async _addElement(ev: HaDropdownSelectEvent): Promise {
+ const value = ev.detail.item.value;
if (value === "") {
return;
}
@@ -191,7 +191,6 @@ export class HuiPictureElementsCardRowEditor extends LitElement {
)
);
fireEvent(this, "elements-changed", { elements: newElements });
- this._select.select(-1);
}
private _removeRow(ev: CustomEvent): void {
@@ -269,10 +268,6 @@ export class HuiPictureElementsCardRowEditor extends LitElement {
font-size: var(--ha-font-size-s);
color: var(--secondary-text-color);
}
-
- ha-select {
- width: 100%;
- }
`;
}
diff --git a/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts b/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts
index 5acea78670..7c92e0c62f 100644
--- a/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts
+++ b/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts
@@ -2,13 +2,11 @@ import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
-import { stopPropagation } from "../../../../common/dom/stop_propagation";
import "../../../../components/ha-alert";
import "../../../../components/ha-button";
import { createCloseHeading } from "../../../../components/ha-dialog";
import "../../../../components/ha-icon";
import "../../../../components/ha-list";
-import "../../../../components/ha-list-item";
import "../../../../components/ha-radio-list-item";
import "../../../../components/ha-select";
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
@@ -82,29 +80,23 @@ export class HuiDialogSelectView extends LitElement {
.disabled=${!this._dashboards.length}
.value=${this._urlPath || defaultPanel}
@selected=${this._dashboardChanged}
- @closed=${stopPropagation}
- fixedMenuPosition
- naturalMenuWidth
+ .options=${this._dashboards
+ .map((dashboard) => ({
+ value: dashboard.url_path,
+ label: `${dashboard.title}${dashboard.id === "lovelace" ? ` (${this.hass.localize("ui.common.default")})` : ""}`,
+ disabled: dashboard.mode !== "storage",
+ }))
+ .sort((a, b) =>
+ a.value === "lovelace"
+ ? -1
+ : b.value === "lovelace"
+ ? 1
+ : a.label.localeCompare(b.label)
+ )}
dialogInitialFocus
>
-
- Default
-
- ${this._dashboards.map(
- (dashboard) => html`
- ${dashboard.title}
- `
- )}
`
- : ""}
+ : nothing}
${!this._config || (this._config.views || []).length < 1
? html`${this.hass.localize(
@@ -142,7 +134,7 @@ export class HuiDialogSelectView extends LitElement {
})}
`
- : ""}
+ : nothing}
) {
+ let urlPath: string | null = ev.detail.value;
if (urlPath === this._urlPath) {
return;
}
diff --git a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts
index dfd8f7ec8d..6eb8b06969 100644
--- a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts
+++ b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts
@@ -1,8 +1,6 @@
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
-import { stopPropagation } from "../../../common/dom/stop_propagation";
-import "../../../components/ha-list-item";
import "../../../components/ha-select";
import { UNAVAILABLE } from "../../../data/entity/entity";
import { forwardHaptic } from "../../../data/haptics";
@@ -70,17 +68,8 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {
.disabled=${
stateObj.state === UNAVAILABLE /* UNKNOWN state is allowed */
}
- naturalMenuWidth
@selected=${this._selectedChanged}
- @click=${stopPropagation}
- @closed=${stopPropagation}
>
- ${stateObj.attributes.options
- ? stateObj.attributes.options.map(
- (option) =>
- html`${option}`
- )
- : ""}
`;
@@ -97,11 +86,11 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {
}
`;
- private _selectedChanged(ev): void {
+ private _selectedChanged(ev: CustomEvent<{ value: string }>): void {
const stateObj = this.hass!.states[
this._config!.entity
] as InputSelectEntity;
- const option = ev.target.value;
+ const option = ev.detail.value;
if (
option === stateObj.state ||
!stateObj.attributes.options.includes(option)
diff --git a/src/panels/lovelace/entity-rows/hui-select-entity-row.ts b/src/panels/lovelace/entity-rows/hui-select-entity-row.ts
index 99e3f24cbb..fcdf36898c 100644
--- a/src/panels/lovelace/entity-rows/hui-select-entity-row.ts
+++ b/src/panels/lovelace/entity-rows/hui-select-entity-row.ts
@@ -1,8 +1,6 @@
import type { PropertyValues } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
-import { stopPropagation } from "../../../common/dom/stop_propagation";
-import "../../../components/ha-list-item";
import "../../../components/ha-select";
import { UNAVAILABLE } from "../../../data/entity/entity";
import { forwardHaptic } from "../../../data/haptics";
@@ -22,6 +20,8 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
@state() private _config?: EntitiesCardEntityConfig;
+ @state() private _selectedEntityRow?: string;
+
public setConfig(config: EntitiesCardEntityConfig): void {
if (!config || !config.entity) {
throw new Error("Entity must be specified");
@@ -65,23 +65,14 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
>
({
+ value: option,
+ label: this.hass!.formatEntityState(stateObj, option),
+ }))}
.disabled=${stateObj.state === UNAVAILABLE}
- naturalMenuWidth
- @action=${this._handleAction}
- @click=${stopPropagation}
- @closed=${stopPropagation}
+ @selected=${this._handleAction}
>
- ${stateObj.attributes.options
- ? stateObj.attributes.options.map(
- (option) => html`
-
- ${this.hass!.formatEntityState(stateObj, option)}
-
- `
- )
- : ""}
`;
@@ -98,10 +89,10 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
}
`;
- private _handleAction(ev): void {
+ private _handleAction(ev: CustomEvent<{ value: string }>): void {
const stateObj = this.hass!.states[this._config!.entity] as SelectEntity;
- const option = ev.target.value;
+ const option = ev.detail.value;
if (
option === stateObj.state ||
@@ -120,9 +111,7 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
setTimeout(() => {
const newStateObj = this.hass!.states[this._config!.entity];
if (newStateObj === stateObj) {
- const select = this.shadowRoot?.querySelector("ha-select");
- const index = select?.options.indexOf(stateObj.state) ?? -1;
- select?.select(index);
+ this._selectedEntityRow = stateObj.state;
}
}, 2000)
);
diff --git a/src/panels/profile/ha-pick-dashboard-row.ts b/src/panels/profile/ha-pick-dashboard-row.ts
index e3c41e439b..765f665732 100644
--- a/src/panels/profile/ha-pick-dashboard-row.ts
+++ b/src/panels/profile/ha-pick-dashboard-row.ts
@@ -1,9 +1,10 @@
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
+import memoizeOne from "memoize-one";
import "../../components/ha-divider";
+import "../../components/ha-dropdown-item";
import "../../components/ha-icon";
-import "../../components/ha-list-item";
import "../../components/ha-select";
import "../../components/ha-settings-row";
import "../../components/ha-spinner";
@@ -46,13 +47,15 @@ class HaPickDashboardRow extends LitElement {
.label=${this.hass.localize(
"ui.panel.profile.dashboard.dropdown_label"
)}
- .value=${value}
+ .value=${this._valueLabel(value)}
@selected=${this._dashboardChanged}
- naturalMenuWidth
>
-
+
${this.hass.localize("ui.panel.profile.dashboard.system")}
-
+
${PANEL_DASHBOARDS.map((panel) => {
const panelInfo = this.hass.panels[panel] as
@@ -62,13 +65,16 @@ class HaPickDashboardRow extends LitElement {
return nothing;
}
return html`
-
+
${getPanelTitle(this.hass, panelInfo)}
-
+
`;
})}
${this._dashboards.length
@@ -82,16 +88,18 @@ class HaPickDashboardRow extends LitElement {
return "";
}
return html`
-
${dashboard.title}
-
+
`;
})}
`
@@ -109,8 +117,8 @@ class HaPickDashboardRow extends LitElement {
this._dashboards = await fetchDashboards(this.hass);
}
- private _dashboardChanged(ev) {
- const value = ev.target.value as string;
+ private _dashboardChanged(ev: CustomEvent<{ value: string }>): void {
+ const value = ev.detail.value;
if (!value) {
return;
}
@@ -124,6 +132,24 @@ class HaPickDashboardRow extends LitElement {
});
}
+ private _valueLabel = memoizeOne((value: string) => {
+ if (value === USE_SYSTEM_VALUE) {
+ return this.hass.localize("ui.panel.profile.dashboard.system");
+ }
+ if (value === "lovelace") {
+ return this.hass.localize("ui.panel.profile.dashboard.lovelace");
+ }
+ const panelInfo = this.hass.panels[value] as PanelInfo | undefined;
+ if (panelInfo) {
+ return getPanelTitle(this.hass, panelInfo);
+ }
+ const dashboard = this._dashboards?.find((dash) => dash.url_path === value);
+ if (dashboard) {
+ return dashboard.title;
+ }
+ return value;
+ });
+
static get styles(): CSSResultGroup {
return [
css`
@@ -134,6 +160,11 @@ class HaPickDashboardRow extends LitElement {
height: 56px;
width: 200px;
}
+
+ ha-select {
+ display: block;
+ width: 100%;
+ }
`,
];
}
diff --git a/src/panels/profile/ha-pick-date-format-row.ts b/src/panels/profile/ha-pick-date-format-row.ts
index ead7a7cf0f..14744a3fea 100644
--- a/src/panels/profile/ha-pick-date-format-row.ts
+++ b/src/panels/profile/ha-pick-date-format-row.ts
@@ -1,10 +1,9 @@
import type { TemplateResult } from "lit";
-import { html, LitElement } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { formatDateNumeric } from "../../common/datetime/format_date";
import { fireEvent } from "../../common/dom/fire_event";
import "../../components/ha-card";
-import "../../components/ha-list-item";
import "../../components/ha-select";
import "../../components/ha-settings-row";
import { DateFormat } from "../../data/translation";
@@ -33,33 +32,36 @@ class DateFormatRow extends LitElement {
.disabled=${this.hass.locale === undefined}
.value=${this.hass.locale.date_format}
@selected=${this._handleFormatSelection}
- naturalMenuWidth
- >
- ${Object.values(DateFormat).map((format) => {
- const formattedDate = formatDateNumeric(
+ .options=${Object.values(DateFormat).map((format) => ({
+ value: format.toString(),
+ label: this.hass.localize(
+ `ui.panel.profile.date_format.formats.${format}`
+ ),
+ secondary: formatDateNumeric(
date,
{
...this.hass.locale,
date_format: format,
},
this.hass.config
- );
- const value = this.hass.localize(
- `ui.panel.profile.date_format.formats.${format}`
- );
- return html`
- ${value}
- ${formattedDate}
- `;
- })}
+ ),
+ }))}
+ >
`;
}
- private async _handleFormatSelection(ev) {
- fireEvent(this, "hass-date-format-select", ev.target.value);
+ private async _handleFormatSelection(ev: CustomEvent<{ value: string }>) {
+ fireEvent(this, "hass-date-format-select", ev.detail.value as DateFormat);
}
+
+ static styles = css`
+ ha-select {
+ display: block;
+ width: 100%;
+ }
+ `;
}
declare global {
diff --git a/src/panels/profile/ha-pick-first-weekday-row.ts b/src/panels/profile/ha-pick-first-weekday-row.ts
index e793c93151..ef03d8d107 100644
--- a/src/panels/profile/ha-pick-first-weekday-row.ts
+++ b/src/panels/profile/ha-pick-first-weekday-row.ts
@@ -1,9 +1,8 @@
import type { TemplateResult } from "lit";
-import { html, LitElement } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { firstWeekday } from "../../common/datetime/first_weekday";
import { fireEvent } from "../../common/dom/fire_event";
-import "../../components/ha-list-item";
import "../../components/ha-select";
import "../../components/ha-settings-row";
import { FirstWeekday } from "../../data/translation";
@@ -31,43 +30,44 @@ class FirstWeekdayRow extends LitElement {
.disabled=${this.hass.locale === undefined}
.value=${this.hass.locale.first_weekday}
@selected=${this._handleFormatSelection}
- naturalMenuWidth
- >
- ${[
+ .options=${[
FirstWeekday.language,
FirstWeekday.monday,
FirstWeekday.saturday,
FirstWeekday.sunday,
- ].map((day) => {
- const value = this.hass.localize(
+ ].map((day) => ({
+ value: day.toString(),
+ label: this.hass.localize(
`ui.panel.profile.first_weekday.values.${day}`
- );
- const twoLine = day === FirstWeekday.language;
- return html`
-
- ${value}
- ${twoLine
- ? html`
- ${this.hass.localize(
- `ui.panel.profile.first_weekday.values.${firstWeekday(
- this.hass.locale
- )}`
- )}
- `
- : ""}
-
- `;
- })}
-
+ ),
+ secondary:
+ day === FirstWeekday.language
+ ? this.hass.localize(
+ `ui.panel.profile.first_weekday.values.${firstWeekday(
+ this.hass.locale
+ )}`
+ )
+ : undefined,
+ }))}
+ >
`;
}
- private async _handleFormatSelection(ev) {
- fireEvent(this, "hass-first-weekday-select", ev.target.value);
+ private async _handleFormatSelection(ev: CustomEvent<{ value: string }>) {
+ fireEvent(
+ this,
+ "hass-first-weekday-select",
+ ev.detail.value as FirstWeekday
+ );
}
+
+ static styles = css`
+ ha-select {
+ display: block;
+ width: 100%;
+ }
+ `;
}
declare global {
diff --git a/src/panels/profile/ha-pick-number-format-row.ts b/src/panels/profile/ha-pick-number-format-row.ts
index 356fd6122f..69d58d1909 100644
--- a/src/panels/profile/ha-pick-number-format-row.ts
+++ b/src/panels/profile/ha-pick-number-format-row.ts
@@ -1,10 +1,9 @@
import type { TemplateResult } from "lit";
-import { html, LitElement } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import { formatNumber } from "../../common/number/format_number";
import "../../components/ha-card";
-import "../../components/ha-list-item";
import "../../components/ha-select";
import "../../components/ha-settings-row";
import { NumberFormat } from "../../data/translation";
@@ -32,34 +31,42 @@ class NumberFormatRow extends LitElement {
.disabled=${this.hass.locale === undefined}
.value=${this.hass.locale.number_format}
@selected=${this._handleFormatSelection}
- naturalMenuWidth
- >
- ${Object.values(NumberFormat).map((format) => {
- const formattedNumber = formatNumber(1234567.89, {
- ...this.hass.locale,
- number_format: format,
- });
- const value = this.hass.localize(
+ .options=${Object.values(NumberFormat).map((format) => {
+ const label = this.hass.localize(
`ui.panel.profile.number_format.formats.${format}`
);
- const twoLine = value.slice(value.length - 2) !== "89"; // Display explicit number formats on one line
- return html`
-
- ${value}
- ${twoLine
- ? html`${formattedNumber}`
- : ""}
-
- `;
+ return {
+ value: format,
+ label,
+ secondary:
+ label.slice(label.length - 2) !== "89"
+ ? formatNumber(1234567.89, {
+ ...this.hass.locale,
+ number_format: format,
+ })
+ : undefined,
+ };
})}
+ >
`;
}
- private async _handleFormatSelection(ev) {
- fireEvent(this, "hass-number-format-select", ev.target.value);
+ private async _handleFormatSelection(ev: CustomEvent<{ value: string }>) {
+ fireEvent(
+ this,
+ "hass-number-format-select",
+ ev.detail.value as NumberFormat
+ );
}
+
+ static styles = css`
+ ha-select {
+ display: block;
+ width: 100%;
+ }
+ `;
}
declare global {
diff --git a/src/panels/profile/ha-pick-theme-row.ts b/src/panels/profile/ha-pick-theme-row.ts
index 0ed5a41f59..341eaba375 100644
--- a/src/panels/profile/ha-pick-theme-row.ts
+++ b/src/panels/profile/ha-pick-theme-row.ts
@@ -3,23 +3,22 @@ import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { normalizeLuminance } from "../../common/color/palette";
import { fireEvent } from "../../common/dom/fire_event";
-import "../../components/ha-formfield";
-import "../../components/ha-list-item";
-import "../../components/ha-radio";
import "../../components/ha-button";
+import "../../components/ha-formfield";
+import "../../components/ha-radio";
import type { HaRadio } from "../../components/ha-radio";
import "../../components/ha-select";
import "../../components/ha-settings-row";
import "../../components/ha-textfield";
-import {
- DefaultAccentColor,
- DefaultPrimaryColor,
-} from "../../resources/theme/color/color.globals";
import {
saveThemePreferences,
subscribeThemePreferences,
} from "../../data/theme";
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
+import {
+ DefaultAccentColor,
+ DefaultPrimaryColor,
+} from "../../resources/theme/color/color.globals";
import type { HomeAssistant, ThemeSettings } from "../../types";
import { documentationUrl } from "../../util/documentation-url";
import { clearSelectedThemeState } from "../../util/ha-pref-storage";
@@ -93,19 +92,18 @@ export class HaPickThemeRow extends SubscribeMixin(LitElement) {
.disabled=${!hasThemes}
.value=${this.hass.selectedTheme?.theme || USE_DEFAULT_THEME}
@selected=${this._handleThemeSelection}
- naturalMenuWidth
+ .options=${[
+ {
+ value: USE_DEFAULT_THEME,
+ label: this.hass.localize("ui.panel.profile.themes.use_default"),
+ },
+ { value: HOME_ASSISTANT_THEME, label: "Home Assistant" },
+ ...this._themeNames.map((theme) => ({
+ value: theme,
+ label: theme,
+ })),
+ ]}
>
-
- ${this.hass.localize("ui.panel.profile.themes.use_default")}
-
-
- Home Assistant
-
- ${this._themeNames.map(
- (theme) => html`
- ${theme}
- `
- )}
${curTheme === HOME_ASSISTANT_THEME ||
@@ -261,8 +259,8 @@ export class HaPickThemeRow extends SubscribeMixin(LitElement) {
fireEvent(this, "settheme", { dark });
}
- private _handleThemeSelection(ev) {
- const theme = ev.target.value;
+ private _handleThemeSelection(ev: CustomEvent<{ value: string }>) {
+ const theme = ev.detail.value;
if (theme === this.hass.selectedTheme?.theme) {
return;
}
@@ -334,6 +332,11 @@ export class HaPickThemeRow extends SubscribeMixin(LitElement) {
flex-grow: 1;
margin: 0 4px;
}
+
+ ha-select {
+ display: block;
+ width: 100%;
+ }
`;
}
diff --git a/src/panels/profile/ha-pick-time-format-row.ts b/src/panels/profile/ha-pick-time-format-row.ts
index 17644a7975..54a0755ea3 100644
--- a/src/panels/profile/ha-pick-time-format-row.ts
+++ b/src/panels/profile/ha-pick-time-format-row.ts
@@ -1,10 +1,9 @@
import type { TemplateResult } from "lit";
-import { html, LitElement } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { formatTime } from "../../common/datetime/format_time";
import { fireEvent } from "../../common/dom/fire_event";
import "../../components/ha-card";
-import "../../components/ha-list-item";
import "../../components/ha-select";
import "../../components/ha-settings-row";
import { TimeFormat } from "../../data/translation";
@@ -33,33 +32,36 @@ class TimeFormatRow extends LitElement {
.disabled=${this.hass.locale === undefined}
.value=${this.hass.locale.time_format}
@selected=${this._handleFormatSelection}
- naturalMenuWidth
- >
- ${Object.values(TimeFormat).map((format) => {
- const formattedTime = formatTime(
+ .options=${Object.values(TimeFormat).map((format) => ({
+ value: format.toString(),
+ label: this.hass.localize(
+ `ui.panel.profile.time_format.formats.${format}`
+ ),
+ secondary: formatTime(
date,
{
...this.hass.locale,
time_format: format,
},
this.hass.config
- );
- const value = this.hass.localize(
- `ui.panel.profile.time_format.formats.${format}`
- );
- return html`
- ${value}
- ${formattedTime}
- `;
- })}
+ ),
+ }))}
+ >
`;
}
- private async _handleFormatSelection(ev) {
- fireEvent(this, "hass-time-format-select", ev.target.value);
+ private async _handleFormatSelection(ev: CustomEvent<{ value: string }>) {
+ fireEvent(this, "hass-time-format-select", ev.detail.value as TimeFormat);
}
+
+ static styles = css`
+ ha-select {
+ display: block;
+ width: 100%;
+ }
+ `;
}
declare global {
diff --git a/src/panels/profile/ha-pick-time-zone-row.ts b/src/panels/profile/ha-pick-time-zone-row.ts
index a237eb6ec9..24fa7bfd12 100644
--- a/src/panels/profile/ha-pick-time-zone-row.ts
+++ b/src/panels/profile/ha-pick-time-zone-row.ts
@@ -1,11 +1,10 @@
import type { TemplateResult } from "lit";
-import { html, LitElement } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { formatDateTimeNumeric } from "../../common/datetime/format_date_time";
import { resolveTimeZone } from "../../common/datetime/resolve-time-zone";
import { fireEvent } from "../../common/dom/fire_event";
import "../../components/ha-card";
-import "../../components/ha-list-item";
import "../../components/ha-select";
import "../../components/ha-settings-row";
import { TimeZone } from "../../data/translation";
@@ -34,40 +33,42 @@ class TimeZoneRow extends LitElement {
.disabled=${this.hass.locale === undefined}
.value=${this.hass.locale.time_zone}
@selected=${this._handleFormatSelection}
- naturalMenuWidth
- >
- ${Object.values(TimeZone).map((format) => {
- const formattedTime = formatDateTimeNumeric(
+ .options=${Object.values(TimeZone).map((format) => ({
+ value: format.toString(),
+ label: this.hass.localize(
+ `ui.panel.profile.time_zone.options.${format}`,
+ {
+ timezone: resolveTimeZone(
+ format,
+ this.hass.config.time_zone
+ ).replace("_", " "),
+ }
+ ),
+ secondary: formatDateTimeNumeric(
date,
{
...this.hass.locale,
time_zone: format,
},
this.hass.config
- );
- return html`
- ${this.hass.localize(
- `ui.panel.profile.time_zone.options.${format}`,
- {
- timezone: resolveTimeZone(
- format,
- this.hass.config.time_zone
- ).replace("_", " "),
- }
- )}
- ${formattedTime}
- `;
- })}
+ ),
+ }))}
+ >
`;
}
- private async _handleFormatSelection(ev) {
- fireEvent(this, "hass-time-zone-select", ev.target.value);
+ private async _handleFormatSelection(ev: CustomEvent<{ value: string }>) {
+ fireEvent(this, "hass-time-zone-select", ev.detail.value as TimeZone);
}
+
+ static styles = css`
+ ha-select {
+ display: block;
+ width: 100%;
+ }
+ `;
}
declare global {
diff --git a/src/state-summary/state-card-input_select.ts b/src/state-summary/state-card-input_select.ts
index 2a52cd9eb2..87a626e0b7 100644
--- a/src/state-summary/state-card-input_select.ts
+++ b/src/state-summary/state-card-input_select.ts
@@ -2,9 +2,9 @@ import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { computeStateName } from "../common/entity/compute_state_name";
-import type { HaDropdownSelectEvent } from "../components/ha-dropdown";
import "../components/entity/state-badge";
import "../components/ha-control-select-menu";
+import type { HaDropdownSelectEvent } from "../components/ha-dropdown";
import { UNAVAILABLE } from "../data/entity/entity";
import type { InputSelectEntity } from "../data/input_select";
import { setInputSelectOption } from "../data/input_select";
diff --git a/src/state-summary/state-card-select.ts b/src/state-summary/state-card-select.ts
index 083ac7966e..0956f280f3 100644
--- a/src/state-summary/state-card-select.ts
+++ b/src/state-summary/state-card-select.ts
@@ -2,9 +2,9 @@ import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { computeStateName } from "../common/entity/compute_state_name";
-import type { HaDropdownSelectEvent } from "../components/ha-dropdown";
import "../components/entity/state-badge";
import "../components/ha-control-select-menu";
+import type { HaDropdownSelectEvent } from "../components/ha-dropdown";
import { UNAVAILABLE } from "../data/entity/entity";
import type { SelectEntity } from "../data/select";
import { setSelectOption } from "../data/select";
diff --git a/src/state/translations-mixin.ts b/src/state/translations-mixin.ts
index 2b587acadb..4aca311817 100644
--- a/src/state/translations-mixin.ts
+++ b/src/state/translations-mixin.ts
@@ -37,21 +37,11 @@ declare global {
"hass-language-select": {
language: string;
};
- "hass-number-format-select": {
- number_format: NumberFormat;
- };
- "hass-time-format-select": {
- time_format: TimeFormat;
- };
- "hass-date-format-select": {
- date_format: DateFormat;
- };
- "hass-time-zone-select": {
- time_zone: TimeZone;
- };
- "hass-first-weekday-select": {
- first_weekday: FirstWeekday;
- };
+ "hass-number-format-select": NumberFormat;
+ "hass-time-format-select": TimeFormat;
+ "hass-date-format-select": DateFormat;
+ "hass-time-zone-select": TimeZone;
+ "hass-first-weekday-select": FirstWeekday;
"translations-updated": undefined;
}
}
diff --git a/yarn.lock b/yarn.lock
index 01eaef5c47..a64192c225 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2903,7 +2903,7 @@ __metadata:
languageName: node
linkType: hard
-"@material/mwc-menu@npm:0.27.0, @material/mwc-menu@npm:^0.27.0":
+"@material/mwc-menu@npm:^0.27.0":
version: 0.27.0
resolution: "@material/mwc-menu@npm:0.27.0"
dependencies:
@@ -9103,7 +9103,6 @@ __metadata:
"@material/mwc-icon-button": "npm:0.27.0"
"@material/mwc-linear-progress": "npm:0.27.0"
"@material/mwc-list": "patch:@material/mwc-list@npm%3A0.27.0#~/.yarn/patches/@material-mwc-list-npm-0.27.0-5344fc9de4.patch"
- "@material/mwc-menu": "npm:0.27.0"
"@material/mwc-radio": "npm:0.27.0"
"@material/mwc-select": "npm:0.27.0"
"@material/mwc-snackbar": "npm:0.27.0"