diff --git a/src/panels/config/automation/action/ha-automation-action.ts b/src/panels/config/automation/action/ha-automation-action.ts index 6afb46f152..d33825c0e7 100644 --- a/src/panels/config/automation/action/ha-automation-action.ts +++ b/src/panels/config/automation/action/ha-automation-action.ts @@ -3,13 +3,10 @@ import deepClone from "deep-clone-simple"; import type { HassServiceTarget } from "home-assistant-js-websocket"; import type { PropertyValues } from "lit"; import { html, LitElement, nothing } from "lit"; -import { customElement, property, queryAll, state } from "lit/decorators"; +import { customElement, property, queryAll } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import { ensureArray } from "../../../../common/array/ensure-array"; -import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; import { stopPropagation } from "../../../../common/dom/stop_propagation"; -import { nextRender } from "../../../../common/util/render-status"; import "../../../../components/ha-button"; import "../../../../components/ha-sortable"; import "../../../../components/ha-svg-icon"; @@ -17,57 +14,41 @@ import { ACTION_BUILDING_BLOCKS, VIRTUAL_ACTIONS, } from "../../../../data/action"; -import { - getValueFromDynamic, - isDynamic, - type AutomationClipboard, -} from "../../../../data/automation"; +import { getValueFromDynamic, isDynamic } from "../../../../data/automation"; import type { Action } from "../../../../data/script"; -import type { HomeAssistant } from "../../../../types"; import { PASTE_VALUE, showAddAutomationElementDialog, } from "../show-add-automation-element-dialog"; +import { AutomationSortableListMixin } from "../ha-automation-sortable-list-mixin"; import { automationRowsStyles } from "../styles"; import type HaAutomationActionRow from "./ha-automation-action-row"; import { getAutomationActionType } from "./ha-automation-action-row"; @customElement("ha-automation-action") -export default class HaAutomationAction extends LitElement { - @property({ attribute: false }) public hass!: HomeAssistant; - - @property({ type: Boolean }) public narrow = false; - - @property({ type: Boolean }) public disabled = false; - +export default class HaAutomationAction extends AutomationSortableListMixin( + LitElement +) { @property({ type: Boolean }) public root = false; @property({ attribute: false }) public actions!: Action[]; @property({ attribute: false }) public highlightedActions?: Action[]; - @property({ type: Boolean, attribute: "sidebar" }) public optionsInSidebar = - false; - - @state() private _rowSortSelected?: number; - - @state() - @storage({ - key: "automationClipboard", - state: true, - subscribe: true, - storage: "sessionStorage", - }) - public _clipboard?: AutomationClipboard; - @queryAll("ha-automation-action-row") private _actionRowElements?: HaAutomationActionRow[]; - private _focusLastActionOnChange = false; + protected get items(): Action[] { + return this.actions; + } - private _focusActionIndexOnChange?: number; + protected set items(items: Action[]) { + this.actions = items; + } - private _actionKeys = new WeakMap(); + protected setHighlightedItems(items: Action[]) { + this.highlightedActions = items; + } protected render() { return html` @@ -77,14 +58,14 @@ export default class HaAutomationAction extends LitElement { .disabled=${this.disabled} group="actions" invert-swap - @item-moved=${this._actionMoved} - @item-added=${this._actionAdded} - @item-removed=${this._actionRemoved} + @item-moved=${this.itemMoved} + @item-added=${this.itemAdded} + @item-removed=${this.itemRemoved} >
${repeat( this.actions, - (action) => this._getKey(action), + (action) => this.getKey(action), (action, idx) => html` ${!this.disabled ? html`
@@ -150,17 +131,16 @@ export default class HaAutomationAction extends LitElement { if ( changedProps.has("actions") && - (this._focusLastActionOnChange || - this._focusActionIndexOnChange !== undefined) + (this.focusLastItemOnChange || this.focusItemIndexOnChange !== undefined) ) { - const mode = this._focusLastActionOnChange ? "new" : "moved"; + const mode = this.focusLastItemOnChange ? "new" : "moved"; const row = this.shadowRoot!.querySelector( - `ha-automation-action-row:${mode === "new" ? "last-of-type" : `nth-of-type(${this._focusActionIndexOnChange! + 1})`}` + `ha-automation-action-row:${mode === "new" ? "last-of-type" : `nth-of-type(${this.focusItemIndexOnChange! + 1})`}` )!; - this._focusLastActionOnChange = false; - this._focusActionIndexOnChange = undefined; + this.focusLastItemOnChange = false; + this.focusItemIndexOnChange = undefined; row.updateComplete.then(() => { // on new condition open the settings in the sidebar, except for building blocks @@ -234,158 +214,10 @@ export default class HaAutomationAction extends LitElement { elClass ? { ...elClass.defaultConfig } : { [action]: {} } ); } - this._focusLastActionOnChange = true; + this.focusLastItemOnChange = true; fireEvent(this, "value-changed", { value: actions }); }; - private _getKey(action: Action) { - if (!this._actionKeys.has(action)) { - this._actionKeys.set(action, Math.random().toString()); - } - - return this._actionKeys.get(action)!; - } - - private async _moveUp(ev) { - ev.stopPropagation(); - const index = (ev.target as any).index; - if (!(ev.target as HaAutomationActionRow).first) { - const newIndex = index - 1; - this._move(index, newIndex); - if (this._rowSortSelected === index) { - this._rowSortSelected = newIndex; - } - ev.target.focus(); - } - } - - private async _moveDown(ev) { - ev.stopPropagation(); - const index = (ev.target as any).index; - if (!(ev.target as HaAutomationActionRow).last) { - const newIndex = index + 1; - this._move(index, newIndex); - if (this._rowSortSelected === index) { - this._rowSortSelected = newIndex; - } - ev.target.focus(); - } - } - - private _move(oldIndex: number, newIndex: number) { - const actions = this.actions.concat(); - const item = actions.splice(oldIndex, 1)[0]; - actions.splice(newIndex, 0, item); - this.actions = actions; - fireEvent(this, "value-changed", { value: actions }); - } - - private _actionMoved(ev: CustomEvent): void { - ev.stopPropagation(); - const { oldIndex, newIndex } = ev.detail; - this._move(oldIndex, newIndex); - } - - private async _actionAdded(ev: CustomEvent): Promise { - ev.stopPropagation(); - const { index, data } = ev.detail; - const item = ev.detail.item as HaAutomationActionRow; - const selected = item.selected; - - let actions = [ - ...this.actions.slice(0, index), - data, - ...this.actions.slice(index), - ]; - // Add action locally to avoid UI jump - this.actions = actions; - if (selected) { - this._focusActionIndexOnChange = actions.length === 1 ? 0 : index; - } - await nextRender(); - if (this.actions !== actions) { - // Ensure action is added even after update - actions = [ - ...this.actions.slice(0, index), - data, - ...this.actions.slice(index), - ]; - if (selected) { - this._focusActionIndexOnChange = actions.length === 1 ? 0 : index; - } - } - fireEvent(this, "value-changed", { value: actions }); - } - - private async _actionRemoved(ev: CustomEvent): Promise { - ev.stopPropagation(); - const { index } = ev.detail; - const action = this.actions[index]; - // Remove action locally to avoid UI jump - this.actions = this.actions.filter((a) => a !== action); - await nextRender(); - // Ensure action is removed even after update - const actions = this.actions.filter((a) => a !== action); - fireEvent(this, "value-changed", { value: actions }); - } - - private _actionChanged(ev: CustomEvent) { - ev.stopPropagation(); - const actions = [...this.actions]; - const newValue = ev.detail.value; - const index = (ev.target as any).index; - - if (newValue === null) { - actions.splice(index, 1); - } else { - // Store key on new value. - const key = this._getKey(actions[index]); - this._actionKeys.set(newValue, key); - - actions[index] = newValue; - } - - fireEvent(this, "value-changed", { value: actions }); - } - - private _duplicateAction(ev: CustomEvent) { - ev.stopPropagation(); - const index = (ev.target as any).index; - fireEvent(this, "value-changed", { - // @ts-expect-error Requires library bump to ES2023 - value: this.actions.toSpliced( - index + 1, - 0, - deepClone(this.actions[index]) - ), - }); - } - - private _insertAfter(ev: CustomEvent) { - ev.stopPropagation(); - const index = (ev.target as any).index; - const inserted = ensureArray(ev.detail.value); - this.highlightedActions = inserted; - fireEvent(this, "value-changed", { - // @ts-expect-error Requires library bump to ES2023 - value: this.actions.toSpliced(index + 1, 0, ...inserted), - }); - } - - private _handleDragKeydown(ev: KeyboardEvent) { - if (ev.key === "Enter" || ev.key === " ") { - ev.stopPropagation(); - this._rowSortSelected = - this._rowSortSelected === undefined - ? (ev.target as any).index - : undefined; - } - } - - private _stopSortSelection() { - this._rowSortSelected = undefined; - } - static styles = automationRowsStyles; } diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts index a796fc0705..a598f81687 100644 --- a/src/panels/config/automation/condition/ha-automation-condition.ts +++ b/src/panels/config/automation/condition/ha-automation-condition.ts @@ -8,18 +8,14 @@ import type { PropertyValues } from "lit"; import { html, LitElement, nothing } from "lit"; import { customElement, property, queryAll, state } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import { ensureArray } from "../../../../common/array/ensure-array"; -import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; import { stopPropagation } from "../../../../common/dom/stop_propagation"; -import { nextRender } from "../../../../common/util/render-status"; import "../../../../components/ha-button"; import "../../../../components/ha-sortable"; import "../../../../components/ha-svg-icon"; import { getValueFromDynamic, isDynamic, - type AutomationClipboard, type Condition, } from "../../../../data/automation"; import type { ConditionDescriptions } from "../../../../data/condition"; @@ -29,58 +25,46 @@ import { } from "../../../../data/condition"; import { subscribeLabFeature } from "../../../../data/labs"; import { SubscribeMixin } from "../../../../mixins/subscribe-mixin"; -import type { HomeAssistant } from "../../../../types"; import { PASTE_VALUE, showAddAutomationElementDialog, } from "../show-add-automation-element-dialog"; +import { AutomationSortableListMixin } from "../ha-automation-sortable-list-mixin"; import { automationRowsStyles } from "../styles"; import "./ha-automation-condition-row"; import type HaAutomationConditionRow from "./ha-automation-condition-row"; @customElement("ha-automation-condition") -export default class HaAutomationCondition extends SubscribeMixin(LitElement) { - @property({ attribute: false }) public hass!: HomeAssistant; - +export default class HaAutomationCondition extends AutomationSortableListMixin( + SubscribeMixin(LitElement) +) { @property({ attribute: false }) public conditions!: Condition[]; @property({ attribute: false }) public highlightedConditions?: Condition[]; - @property({ type: Boolean }) public disabled = false; - - @property({ type: Boolean }) public narrow = false; - @property({ type: Boolean }) public root = false; - @property({ type: Boolean, attribute: "sidebar" }) public optionsInSidebar = - false; - - @state() private _rowSortSelected?: number; - @state() private _conditionDescriptions: ConditionDescriptions = {}; - @state() - @storage({ - key: "automationClipboard", - state: true, - subscribe: true, - storage: "sessionStorage", - }) - public _clipboard?: AutomationClipboard; - @queryAll("ha-automation-condition-row") private _conditionRowElements?: HaAutomationConditionRow[]; - private _focusLastConditionOnChange = false; - - private _focusConditionIndexOnChange?: number; - - private _conditionKeys = new WeakMap(); + // @ts-ignore + @state() private _newTriggersAndConditions = false; private _unsub?: Promise; - // @ts-ignore - @state() private _newTriggersAndConditions = false; + protected get items(): Condition[] { + return this.conditions; + } + + protected set items(items: Condition[]) { + this.conditions = items; + } + + protected setHighlightedItems(items: Condition[]) { + this.highlightedConditions = items; + } public disconnectedCallback() { super.disconnectedCallback(); @@ -155,17 +139,17 @@ export default class HaAutomationCondition extends SubscribeMixin(LitElement) { value: updatedConditions, }); } else if ( - this._focusLastConditionOnChange || - this._focusConditionIndexOnChange !== undefined + this.focusLastItemOnChange || + this.focusItemIndexOnChange !== undefined ) { - const mode = this._focusLastConditionOnChange ? "new" : "moved"; + const mode = this.focusLastItemOnChange ? "new" : "moved"; const row = this.shadowRoot!.querySelector( - `ha-automation-condition-row:${mode === "new" ? "last-of-type" : `nth-of-type(${this._focusConditionIndexOnChange! + 1})`}` + `ha-automation-condition-row:${mode === "new" ? "last-of-type" : `nth-of-type(${this.focusItemIndexOnChange! + 1})`}` )!; - this._focusLastConditionOnChange = false; - this._focusConditionIndexOnChange = undefined; + this.focusLastItemOnChange = false; + this.focusItemIndexOnChange = undefined; row.updateComplete.then(() => { // on new condition open the settings in the sidebar, except for building blocks @@ -217,14 +201,14 @@ export default class HaAutomationCondition extends SubscribeMixin(LitElement) { .disabled=${this.disabled} group="conditions" invert-swap - @item-moved=${this._conditionMoved} - @item-added=${this._conditionAdded} - @item-removed=${this._conditionRemoved} + @item-moved=${this.itemMoved} + @item-added=${this.itemAdded} + @item-removed=${this.itemRemoved} >
${repeat( this.conditions.filter((c) => typeof c === "object"), - (condition) => this._getKey(condition), + (condition) => this.getKey(condition), (cond, idx) => html` ${!this.disabled ? html`
@@ -321,159 +305,10 @@ export default class HaAutomationCondition extends SubscribeMixin(LitElement) { ...(target?.entity_id ? { entity_id: target.entity_id } : {}), }); } - this._focusLastConditionOnChange = true; + this.focusLastItemOnChange = true; fireEvent(this, "value-changed", { value: conditions }); }; - private _getKey(condition: Condition) { - if (!this._conditionKeys.has(condition)) { - this._conditionKeys.set(condition, Math.random().toString()); - } - - return this._conditionKeys.get(condition)!; - } - - private _moveUp(ev) { - ev.stopPropagation(); - const index = (ev.target as any).index; - if (!(ev.target as HaAutomationConditionRow).first) { - const newIndex = index - 1; - this._move(index, newIndex); - if (this._rowSortSelected === index) { - this._rowSortSelected = newIndex; - } - ev.target.focus(); - } - } - - private _moveDown(ev) { - ev.stopPropagation(); - const index = (ev.target as any).index; - if (!(ev.target as HaAutomationConditionRow).last) { - const newIndex = index + 1; - this._move(index, newIndex); - if (this._rowSortSelected === index) { - this._rowSortSelected = newIndex; - } - ev.target.focus(); - } - } - - private _move(oldIndex: number, newIndex: number) { - const conditions = this.conditions.concat(); - const item = conditions.splice(oldIndex, 1)[0]; - conditions.splice(newIndex, 0, item); - this.conditions = conditions; - fireEvent(this, "value-changed", { value: conditions }); - } - - private _conditionMoved(ev: CustomEvent): void { - ev.stopPropagation(); - const { oldIndex, newIndex } = ev.detail; - this._move(oldIndex, newIndex); - } - - private async _conditionAdded(ev: CustomEvent): Promise { - ev.stopPropagation(); - const { index, data } = ev.detail; - const item = ev.detail.item as HaAutomationConditionRow; - const selected = item.selected; - let conditions = [ - ...this.conditions.slice(0, index), - data, - ...this.conditions.slice(index), - ]; - // Add condition locally to avoid UI jump - this.conditions = conditions; - if (selected) { - this._focusConditionIndexOnChange = conditions.length === 1 ? 0 : index; - } - await nextRender(); - if (this.conditions !== conditions) { - // Ensure condition is added even after update - conditions = [ - ...this.conditions.slice(0, index), - data, - ...this.conditions.slice(index), - ]; - if (selected) { - this._focusConditionIndexOnChange = conditions.length === 1 ? 0 : index; - } - } - fireEvent(this, "value-changed", { value: conditions }); - } - - private async _conditionRemoved(ev: CustomEvent): Promise { - ev.stopPropagation(); - const { index } = ev.detail; - const condition = this.conditions[index]; - // Remove condition locally to avoid UI jump - this.conditions = this.conditions.filter((c) => c !== condition); - await nextRender(); - // Ensure condition is removed even after update - const conditions = this.conditions.filter((c) => c !== condition); - fireEvent(this, "value-changed", { value: conditions }); - } - - private _conditionChanged(ev: CustomEvent) { - ev.stopPropagation(); - const conditions = [...this.conditions]; - const newValue = ev.detail.value; - const index = (ev.target as any).index; - - if (newValue === null) { - conditions.splice(index, 1); - } else { - // Store key on new value. - const key = this._getKey(conditions[index]); - this._conditionKeys.set(newValue, key); - - conditions[index] = newValue; - } - - this.conditions = conditions; - - fireEvent(this, "value-changed", { value: conditions }); - } - - private _duplicateCondition(ev: CustomEvent) { - ev.stopPropagation(); - const index = (ev.target as any).index; - fireEvent(this, "value-changed", { - // @ts-expect-error Requires library bump to ES2023 - value: this.conditions.toSpliced( - index + 1, - 0, - deepClone(this.conditions[index]) - ), - }); - } - - private _insertAfter(ev: CustomEvent) { - ev.stopPropagation(); - const index = (ev.target as any).index; - const inserted = ensureArray(ev.detail.value); - this.highlightedConditions = inserted; - fireEvent(this, "value-changed", { - // @ts-expect-error Requires library bump to ES2023 - value: this.conditions.toSpliced(index + 1, 0, ...inserted), - }); - } - - private _handleDragKeydown(ev: KeyboardEvent) { - if (ev.key === "Enter" || ev.key === " ") { - ev.stopPropagation(); - this._rowSortSelected = - this._rowSortSelected === undefined - ? (ev.target as any).index - : undefined; - } - } - - private _stopSortSelection() { - this._rowSortSelected = undefined; - } - static styles = automationRowsStyles; } diff --git a/src/panels/config/automation/ha-automation-sortable-list-mixin.ts b/src/panels/config/automation/ha-automation-sortable-list-mixin.ts new file mode 100644 index 0000000000..0af1ef5a1e --- /dev/null +++ b/src/panels/config/automation/ha-automation-sortable-list-mixin.ts @@ -0,0 +1,198 @@ +import deepClone from "deep-clone-simple"; +import type { LitElement } from "lit"; +import { property, state } from "lit/decorators"; +import { ensureArray } from "../../../common/array/ensure-array"; +import { storage } from "../../../common/decorators/storage"; +import { fireEvent } from "../../../common/dom/fire_event"; +import { nextRender } from "../../../common/util/render-status"; +import type { AutomationClipboard } from "../../../data/automation"; +import type { Constructor, HomeAssistant } from "../../../types"; + +export const AutomationSortableListMixin = ( + superClass: Constructor +) => { + class AutomationSortableListClass extends superClass { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ type: Boolean }) public disabled = false; + + @property({ type: Boolean }) public narrow = false; + + @property({ type: Boolean, attribute: "sidebar" }) public optionsInSidebar = + false; + + @state() protected rowSortSelected?: number; + + @state() + @storage({ + key: "automationClipboard", + state: true, + subscribe: true, + storage: "sessionStorage", + }) + public _clipboard?: AutomationClipboard; + + protected focusLastItemOnChange = false; + + protected focusItemIndexOnChange?: number; + + private _itemKeys = new WeakMap(); + + protected get items(): T[] { + throw new Error("Not implemented"); + } + + protected set items(_items: T[]) { + throw new Error("Not implemented"); + } + + protected getKey(item: T): string { + if (!this._itemKeys.has(item)) { + this._itemKeys.set(item, Math.random().toString()); + } + + return this._itemKeys.get(item)!; + } + + protected moveUp(ev) { + ev.stopPropagation(); + const index = (ev.target as any).index; + if (!(ev.target as any).first) { + const newIndex = index - 1; + this.move(index, newIndex); + if (this.rowSortSelected === index) { + this.rowSortSelected = newIndex; + } + ev.target.focus(); + } + } + + protected moveDown(ev) { + ev.stopPropagation(); + const index = (ev.target as any).index; + if (!(ev.target as any).last) { + const newIndex = index + 1; + this.move(index, newIndex); + if (this.rowSortSelected === index) { + this.rowSortSelected = newIndex; + } + ev.target.focus(); + } + } + + protected move(oldIndex: number, newIndex: number) { + const items = this.items.concat(); + const item = items.splice(oldIndex, 1)[0]; + items.splice(newIndex, 0, item); + this.items = items; + fireEvent(this, "value-changed", { value: items }); + } + + protected itemMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; + this.move(oldIndex, newIndex); + } + + protected async itemAdded(ev: CustomEvent): Promise { + ev.stopPropagation(); + const { index, data } = ev.detail; + const selected = (ev.detail.item as any).selected; + + let items = [ + ...this.items.slice(0, index), + data, + ...this.items.slice(index), + ]; + // Add item locally to avoid UI jump + this.items = items; + if (selected) { + this.focusItemIndexOnChange = items.length === 1 ? 0 : index; + } + await nextRender(); + if (this.items !== items) { + // Ensure item is added even after update + items = [ + ...this.items.slice(0, index), + data, + ...this.items.slice(index), + ]; + if (selected) { + this.focusItemIndexOnChange = items.length === 1 ? 0 : index; + } + } + fireEvent(this, "value-changed", { value: items }); + } + + protected async itemRemoved(ev: CustomEvent): Promise { + ev.stopPropagation(); + const { index } = ev.detail; + const item = this.items[index]; + // Remove item locally to avoid UI jump + this.items = this.items.filter((i) => i !== item); + await nextRender(); + // Ensure item is removed even after update + const items = this.items.filter((i) => i !== item); + fireEvent(this, "value-changed", { value: items }); + } + + protected itemChanged(ev: CustomEvent) { + ev.stopPropagation(); + const items = [...this.items]; + const newValue = ev.detail.value; + const index = (ev.target as any).index; + + if (newValue === null) { + items.splice(index, 1); + } else { + // Store key on new value. + const key = this.getKey(items[index]); + this._itemKeys.set(newValue, key); + + items[index] = newValue; + } + + this.items = items; + fireEvent(this, "value-changed", { value: items }); + } + + protected duplicateItem(ev: CustomEvent) { + ev.stopPropagation(); + const index = (ev.target as any).index; + fireEvent(this, "value-changed", { + // @ts-expect-error Requires library bump to ES2023 + value: this.items.toSpliced(index + 1, 0, deepClone(this.items[index])), + }); + } + + protected insertAfter(ev: CustomEvent) { + ev.stopPropagation(); + const index = (ev.target as any).index; + const inserted = ensureArray(ev.detail.value); + this.setHighlightedItems(inserted); + fireEvent(this, "value-changed", { + // @ts-expect-error Requires library bump to ES2023 + value: this.items.toSpliced(index + 1, 0, ...inserted), + }); + } + + protected setHighlightedItems(_items: T[]) { + throw new Error("Not implemented"); + } + + protected handleDragKeydown(ev: KeyboardEvent) { + if (ev.key === "Enter" || ev.key === " ") { + ev.stopPropagation(); + this.rowSortSelected = + this.rowSortSelected === undefined + ? (ev.target as any).index + : undefined; + } + } + + protected stopSortSelection() { + this.rowSortSelected = undefined; + } + } + return AutomationSortableListClass; +}; diff --git a/src/panels/config/automation/option/ha-automation-option.ts b/src/panels/config/automation/option/ha-automation-option.ts index 4395cb80e0..b2a0cb21b6 100644 --- a/src/panels/config/automation/option/ha-automation-option.ts +++ b/src/panels/config/automation/option/ha-automation-option.ts @@ -1,58 +1,38 @@ import { mdiDragHorizontalVariant, mdiPlus } from "@mdi/js"; -import deepClone from "deep-clone-simple"; import type { PropertyValues } from "lit"; import { LitElement, css, html, nothing } from "lit"; -import { customElement, property, queryAll, state } from "lit/decorators"; +import { customElement, property, queryAll } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; import { stopPropagation } from "../../../../common/dom/stop_propagation"; -import { nextRender } from "../../../../common/util/render-status"; import "../../../../components/ha-button"; import "../../../../components/ha-sortable"; import "../../../../components/ha-svg-icon"; -import type { AutomationClipboard } from "../../../../data/automation"; import type { Option } from "../../../../data/script"; -import type { HomeAssistant } from "../../../../types"; +import { AutomationSortableListMixin } from "../ha-automation-sortable-list-mixin"; import { automationRowsStyles } from "../styles"; import "./ha-automation-option-row"; import type HaAutomationOptionRow from "./ha-automation-option-row"; @customElement("ha-automation-option") -export default class HaAutomationOption extends LitElement { - @property({ attribute: false }) public hass!: HomeAssistant; - - @property({ type: Boolean }) public narrow = false; - - @property({ type: Boolean }) public disabled = false; - +export default class HaAutomationOption extends AutomationSortableListMixin