diff --git a/src/components/ha-combo-box.ts b/src/components/ha-combo-box.ts
index 44e55c55d9..4d07dcba6c 100644
--- a/src/components/ha-combo-box.ts
+++ b/src/components/ha-combo-box.ts
@@ -205,7 +205,7 @@ export class HaComboBox extends LitElement {
role="button"
tabindex="-1"
aria-label=${ifDefined(this.hass?.localize("ui.common.clear"))}
- class="clear-button"
+ class=${`clear-button ${this.label ? "" : "no-label"}`}
.path=${mdiClose}
@click=${this._clearValue}
>`
@@ -215,7 +215,7 @@ export class HaComboBox extends LitElement {
tabindex="-1"
aria-label=${ifDefined(this.label)}
aria-expanded=${this.opened ? "true" : "false"}
- class="toggle-button"
+ class=${`toggle-button ${this.label ? "" : "no-label"}`}
.path=${this.opened ? mdiMenuUp : mdiMenuDown}
?disabled=${this.disabled}
@click=${this._toggleOpen}
@@ -397,6 +397,9 @@ export class HaComboBox extends LitElement {
color: var(--disabled-text-color);
pointer-events: none;
}
+ .toggle-button.no-label {
+ top: -3px;
+ }
.clear-button {
--mdc-icon-size: 20px;
top: -7px;
@@ -405,6 +408,9 @@ export class HaComboBox extends LitElement {
inset-inline-end: 36px;
direction: var(--direction);
}
+ .clear-button.no-label {
+ top: 0;
+ }
ha-input-helper-text {
margin-top: 4px;
}
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 1d98a00eb7..f7afb04bba 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
@@ -10,6 +10,7 @@ import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
+import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../../../common/entity/compute_device_name";
import { groupBy } from "../../../../../common/util/group-by";
@@ -23,6 +24,7 @@ import "../../../../../components/ha-selector/ha-selector-boolean";
import "../../../../../components/ha-settings-row";
import "../../../../../components/ha-svg-icon";
import "../../../../../components/ha-textfield";
+import "../../../../../components/ha-combo-box";
import type {
ZWaveJSNodeCapabilities,
ZWaveJSNodeConfigParam,
@@ -55,7 +57,7 @@ const icons = {
@customElement("zwave_js-node-config")
class ZWaveJSNodeConfig extends LitElement {
- @property({ attribute: false }) public hass!: HomeAssistant;
+ public hass!: HomeAssistant;
@property({ attribute: false }) public route!: Route;
@@ -294,9 +296,10 @@ class ZWaveJSNodeConfig extends LitElement {
? this.hass.localize(
item.metadata.default === 1 ? "ui.common.yes" : "ui.common.no"
)
- : item.configuration_value_type === "enumerated"
- ? item.metadata.states[item.metadata.default] ||
- item.metadata.default
+ : item.metadata.states?.[item.metadata.default]
+ ? item.configuration_value_type === "manual_entry"
+ ? `${item.metadata.default} - ${item.metadata.states[item.metadata.default]}`
+ : item.metadata.states[item.metadata.default]
: item.metadata.default
}`
: "";
@@ -319,8 +322,30 @@ class ZWaveJSNodeConfig extends LitElement {
`;
}
-
if (item.configuration_value_type === "manual_entry") {
+ if (
+ item.metadata.states &&
+ item.metadata.min != null &&
+ item.metadata.max != null &&
+ item.metadata.max - item.metadata.min <= 100
+ ) {
+ return html`
+ ${labelAndDescription}
+
+
+ `;
+ }
return html`${labelAndDescription}
ev.target.max)
@@ -441,6 +475,33 @@ class ZWaveJSNodeConfig extends LitElement {
this._updateConfigParameter(ev.target, value);
}
+ private _getComboBoxOptions = memoizeOne((states: Record) =>
+ Object.entries(states).map(([value, label]) => ({
+ value,
+ label: `${value} - ${label}`,
+ }))
+ );
+
+ private _getComboBoxValueChangedCallback(
+ id: string,
+ item: ZWaveJSNodeConfigParam
+ ) {
+ return (ev: CustomEvent<{ value: number }>) =>
+ this._numericInputChanged({
+ ...ev,
+ target: {
+ ...ev.target,
+ key: id,
+ min: item.metadata.min,
+ max: item.metadata.max,
+ value: ev.detail.value,
+ property: item.property,
+ endpoint: item.endpoint,
+ propertyKey: item.property_key,
+ },
+ });
+ }
+
private async _updateConfigParameter(target, value) {
try {
const result = await setZwaveNodeConfigParameter(
diff --git a/src/translations/en.json b/src/translations/en.json
index 93be6ec206..08f70946b4 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -6072,6 +6072,7 @@
"parameter_is_read_only": "This parameter is read-only.",
"between_min_max": "Between {min} and {max}",
"error_not_in_range": "Value must be between {min} and {max}",
+ "error_not_numeric": "Value must be a number",
"error_required": "{entity} is required",
"error_device_not_found": "Device not found",
"set_param_accepted": "The parameter has been updated.",