Merge 5e3a8d7232
into 634e1dbde8
commit
793f485a95
|
@ -20,6 +20,8 @@ class HaEntityStatePicker extends LitElement {
|
|||
|
||||
@property({ attribute: false }) public extraOptions?: any[];
|
||||
|
||||
@property({ attribute: false }) public excludeOptions?: string[];
|
||||
|
||||
// eslint-disable-next-line lit/no-native-attributes
|
||||
@property({ type: Boolean }) public autofocus = false;
|
||||
|
||||
|
@ -49,7 +51,8 @@ class HaEntityStatePicker extends LitElement {
|
|||
(changedProps.has("_opened") && this._opened) ||
|
||||
changedProps.has("entityId") ||
|
||||
changedProps.has("attribute") ||
|
||||
changedProps.has("extraOptions")
|
||||
changedProps.has("extraOptions") ||
|
||||
changedProps.has("excludeOptions")
|
||||
) {
|
||||
const stateObj = this.entityId
|
||||
? this.hass.states[this.entityId]
|
||||
|
@ -68,7 +71,7 @@ class HaEntityStatePicker extends LitElement {
|
|||
),
|
||||
}))
|
||||
: []),
|
||||
];
|
||||
].filter((item) => !(this.excludeOptions || []).includes(item.value));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
import type { PropertyValues } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { keyed } from "lit/directives/keyed";
|
||||
import { repeat } from "lit/directives/repeat";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { ensureArray } from "../../common/array/ensure-array";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import "./ha-entity-state-picker";
|
||||
|
||||
@customElement("ha-entity-states-picker")
|
||||
export class HaEntityStatesPicker extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public entityId?: string;
|
||||
|
||||
@property() public attribute?: string;
|
||||
|
||||
@property({ attribute: false }) public extraOptions?: any[];
|
||||
|
||||
@property({ type: Boolean, attribute: "allow-custom-value" })
|
||||
public allowCustomValue;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@property({ type: Array }) public value?: string[];
|
||||
|
||||
@property() public helper?: string;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@property({ type: Boolean }) public required = false;
|
||||
|
||||
private _keys: string[] = [];
|
||||
|
||||
private _getKey(index: number) {
|
||||
if (!this._keys[index]) {
|
||||
this._keys[index] = Math.random().toString();
|
||||
}
|
||||
return this._keys[index];
|
||||
}
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
super.willUpdate(changedProps);
|
||||
if (changedProps.has("value")) {
|
||||
this.value = ensureArray(this.value);
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this.hass) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const value = this.value || [];
|
||||
|
||||
return html`
|
||||
${repeat(
|
||||
value,
|
||||
(_state, index) => this._getKey(index),
|
||||
(state, index) => html`
|
||||
<div>
|
||||
<ha-entity-state-picker
|
||||
.index=${index}
|
||||
.hass=${this.hass}
|
||||
.entityId=${this.entityId}
|
||||
.attribute=${this.attribute}
|
||||
.extraOptions=${this.extraOptions}
|
||||
.excludeOptions=${value.filter((v) => v !== state)}
|
||||
.allowCustomValue=${this.allowCustomValue}
|
||||
.label=${this.label}
|
||||
.value=${state}
|
||||
.disabled=${this.disabled}
|
||||
.helper=${this.disabled && index === value.length - 1
|
||||
? this.helper
|
||||
: undefined}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-entity-state-picker>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
<div>
|
||||
${this.disabled && value.length
|
||||
? nothing
|
||||
: keyed(
|
||||
value.length,
|
||||
html`<ha-entity-state-picker
|
||||
.hass=${this.hass}
|
||||
.entityId=${this.entityId}
|
||||
.attribute=${this.attribute}
|
||||
.extraOptions=${this.extraOptions}
|
||||
.excludeOptions=${value}
|
||||
.allowCustomValue=${this.allowCustomValue}
|
||||
.label=${this.label}
|
||||
.helper=${this.helper}
|
||||
.disabled=${this.disabled}
|
||||
.required=${this.required && !value.length}
|
||||
@value-changed=${this._addValue}
|
||||
></ha-entity-state-picker>`
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _valueChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
const newState = ev.detail.value;
|
||||
const newValue = [...this.value!];
|
||||
const index = (ev.currentTarget as any)?.index;
|
||||
if (!index) {
|
||||
return;
|
||||
}
|
||||
if (newState === undefined) {
|
||||
newValue.splice(index, 1);
|
||||
this._keys.splice(index, 1);
|
||||
fireEvent(this, "value-changed", {
|
||||
value: newValue,
|
||||
});
|
||||
return;
|
||||
}
|
||||
newValue[index] = newState;
|
||||
fireEvent(this, "value-changed", {
|
||||
value: newValue,
|
||||
});
|
||||
}
|
||||
|
||||
private _addValue(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
fireEvent(this, "value-changed", {
|
||||
value: [...(this.value || []), ev.detail.value],
|
||||
});
|
||||
}
|
||||
|
||||
static override styles = css`
|
||||
div {
|
||||
margin-top: 8px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-entity-states-picker": HaEntityStatesPicker;
|
||||
}
|
||||
}
|
|
@ -208,6 +208,7 @@ export class HaComboBox extends LitElement {
|
|||
aria-label=${ifDefined(this.hass?.localize("ui.common.clear"))}
|
||||
class="clear-button"
|
||||
.path=${mdiClose}
|
||||
?disabled=${this.disabled}
|
||||
@click=${this._clearValue}
|
||||
></ha-svg-icon>`
|
||||
: ""}
|
||||
|
@ -386,7 +387,8 @@ export class HaComboBox extends LitElement {
|
|||
:host([opened]) .toggle-button {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.toggle-button[disabled] {
|
||||
.toggle-button[disabled],
|
||||
.clear-button[disabled] {
|
||||
color: var(--disabled-text-color);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
|
|
@ -106,6 +106,8 @@ export const computeInitialHaFormData = (
|
|||
data[field.name] = [];
|
||||
} else if ("media" in selector || "target" in selector) {
|
||||
data[field.name] = {};
|
||||
} else if ("state" in selector) {
|
||||
data[field.name] = selector.state?.multiple ? [] : "";
|
||||
} else {
|
||||
throw new Error(
|
||||
`Selector ${Object.keys(selector)[0]} not supported in initial form data`
|
||||
|
|
|
@ -112,6 +112,10 @@ const SELECTOR_SCHEMAS = {
|
|||
name: "entity_id",
|
||||
selector: { entity: {} },
|
||||
},
|
||||
{
|
||||
name: "multiple",
|
||||
selector: { boolean: {} },
|
||||
},
|
||||
] as const,
|
||||
target: [] as const,
|
||||
template: [] as const,
|
||||
|
|
|
@ -4,6 +4,7 @@ import type { StateSelector } from "../../data/selector";
|
|||
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import "../entity/ha-entity-state-picker";
|
||||
import "../entity/ha-entity-states-picker";
|
||||
|
||||
@customElement("ha-selector-state")
|
||||
export class HaSelectorState extends SubscribeMixin(LitElement) {
|
||||
|
@ -27,6 +28,24 @@ export class HaSelectorState extends SubscribeMixin(LitElement) {
|
|||
};
|
||||
|
||||
protected render() {
|
||||
if (this.selector.state?.multiple) {
|
||||
return html`
|
||||
<ha-entity-states-picker
|
||||
.hass=${this.hass}
|
||||
.entityId=${this.selector.state?.entity_id ||
|
||||
this.context?.filter_entity}
|
||||
.attribute=${this.selector.state?.attribute ||
|
||||
this.context?.filter_attribute}
|
||||
.extraOptions=${this.selector.state?.extra_options}
|
||||
.value=${this.value}
|
||||
.label=${this.label}
|
||||
.helper=${this.helper}
|
||||
.disabled=${this.disabled}
|
||||
.required=${this.required}
|
||||
allow-custom-value
|
||||
></ha-entity-states-picker>
|
||||
`;
|
||||
}
|
||||
return html`
|
||||
<ha-entity-state-picker
|
||||
.hass=${this.hass}
|
||||
|
|
|
@ -380,6 +380,7 @@ export interface StateSelector {
|
|||
extra_options?: { label: string; value: any }[];
|
||||
entity_id?: string;
|
||||
attribute?: string;
|
||||
multiple?: boolean;
|
||||
} | null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue