use ha-combo-box

This commit is contained in:
Petar Petrov 2025-07-07 18:49:38 +03:00
parent 96ae78927b
commit 7fbcba75d3
3 changed files with 68 additions and 25 deletions

View File

@ -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}
></ha-svg-icon>`
@ -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;
}

View File

@ -23,6 +23,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 +56,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;
@ -230,26 +231,8 @@ class ZWaveJSNodeConfig extends LitElement {
item: ZWaveJSNodeConfigParam
): TemplateResult {
const result = this._results[id];
let type = item.configuration_value_type;
if (
type === "manual_entry" &&
item.metadata.states &&
item.metadata.min != null &&
item.metadata.max != null &&
item.metadata.max - item.metadata.min <= 100
) {
// https://github.com/zwave-js/backlog/issues/59
type = "enumerated";
for (let i = item.metadata.min; i <= item.metadata.max; i++) {
if (i in item.metadata.states) {
continue;
}
item.metadata.states[i] = i.toString();
}
}
const isTypeBoolean = type === "boolean" || this._isEnumeratedBool(item);
const isTypeBoolean = item.configuration_value_type === "boolean" || this._isEnumeratedBool(item);
const labelAndDescription = html`
<span slot="prefix" class="prefix">
@ -310,7 +293,7 @@ class ZWaveJSNodeConfig extends LitElement {
? this.hass.localize(
item.metadata.default === 1 ? "ui.common.yes" : "ui.common.no"
)
: type === "enumerated"
: item.configuration_value_type === "enumerated"
? item.metadata.states[item.metadata.default] ||
item.metadata.default
: item.metadata.default
@ -335,7 +318,31 @@ class ZWaveJSNodeConfig extends LitElement {
</div>
`;
}
if (type === "manual_entry") {
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}
<ha-combo-box
.hass=${this.hass}
.value=${item.value?.toString()}
allow-custom-value
hide-clear-icon
.items=${Object.entries(item.metadata.states).map(
([value, label]) => ({ value, label })
)}
.disabled=${!item.metadata.writeable}
.placeholder=${item.metadata.unit}
.helper=${`${this.hass.localize("ui.panel.config.zwave_js.node_config.between_min_max", { min: item.metadata.min, max: item.metadata.max })}${defaultLabel ? `, ${defaultLabel}` : ""}`}
@value-changed=${this._getComboBoxValueChangedCallback(id, item)}
>
</ha-combo-box>
`;
}
return html`${labelAndDescription}
<ha-textfield
type="number"
@ -355,7 +362,7 @@ class ZWaveJSNodeConfig extends LitElement {
</ha-textfield>`;
}
if (type === "enumerated") {
if (item.configuration_value_type === "enumerated") {
return html`
${labelAndDescription}
<ha-select
@ -439,6 +446,15 @@ class ZWaveJSNodeConfig extends LitElement {
if (Number(this._config![ev.target.key].value) === value) {
return;
}
if (isNaN(value)) {
this._setError(
ev.target.key,
this.hass.localize(
"ui.panel.config.zwave_js.node_config.error_not_numeric"
)
);
return;
}
if (
(ev.target.min !== undefined && value < ev.target.min) ||
(ev.target.max !== undefined && value > ev.target.max)
@ -456,6 +472,26 @@ class ZWaveJSNodeConfig extends LitElement {
this._updateConfigParameter(ev.target, value);
}
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(

View File

@ -6061,6 +6061,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.",