import { mdiInformationOutline, mdiLabel, mdiPlus, mdiTextureBox, } from "@mdi/js"; import { LitElement, css, html, nothing, type TemplateResult } from "lit"; import { customElement, eventOptions, property, query, state, } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { repeat } from "lit/directives/repeat"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; import { stopPropagation } from "../../../../common/dom/stop_propagation"; import "../../../../components/entity/state-badge"; import "../../../../components/ha-domain-icon"; import "../../../../components/ha-floor-icon"; import "../../../../components/ha-icon-next"; import "../../../../components/ha-md-list"; import "../../../../components/ha-md-list-item"; import "../../../../components/ha-svg-icon"; import "../../../../components/ha-tooltip"; import type { ConfigEntry } from "../../../../data/config_entries"; import type { HomeAssistant } from "../../../../types"; import type { AddAutomationElementListItem } from "../add-automation-element-dialog"; type Target = [string, string | undefined, string | undefined]; @customElement("ha-automation-add-items") export class HaAutomationAddItems extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public items?: { title: string; items: AddAutomationElementListItem[]; }[]; @property() public error?: string; @property({ attribute: "select-label" }) public selectLabel!: string; @property({ attribute: "empty-label" }) public emptyLabel!: string; @property({ attribute: false }) public target?: Target; @property({ attribute: false }) public getLabel!: ( id: string ) => { name: string; icon?: string } | undefined; @property({ attribute: false }) public configEntryLookup: Record< string, ConfigEntry > = {}; @property({ type: Boolean, attribute: "tooltip-description" }) public tooltipDescription = false; @state() private _itemsScrolled = false; @query(".items") private _itemsDiv!: HTMLDivElement; protected render() { return html`
${!this.items && !this.error ? this.selectLabel : this.error ? html`${this.error}
${this._renderTarget(this.target)}
` : this.items && !this.items.length ? html`${this.emptyLabel} ${this.target ? html`
${this._renderTarget(this.target)}
` : nothing}` : repeat( this.items, (_, index) => `item-group-${index}`, (itemGroup) => this._renderItemList(itemGroup.title, itemGroup.items) )}
`; } private _renderItemList(title, items?: AddAutomationElementListItem[]) { if (!items || !items.length) { return nothing; } return html`
${title}
${repeat( items, (item) => item.key, (item) => html`
${item.name}${this._renderTarget(this.target)}
${!this.tooltipDescription && item.description ? html`
${item.description}
` : nothing} ${item.icon ? html`${item.icon}` : item.iconPath ? html`` : nothing} ${this.tooltipDescription && item.description ? html` ${item.description} ` : nothing}
` )}
`; } private _renderTarget = memoizeOne((target?: Target) => { if (!target) { return nothing; } return html`
${this._getSelectedTargetIcon(target[0], target[1])}
${target[2]}
`; }); private _getSelectedTargetIcon( targetType: string, targetId: string | undefined ): TemplateResult | typeof nothing { if (!targetId) { return nothing; } if (targetType === "floor") { return html``; } if (targetType === "area" && this.hass.areas[targetId]) { const area = this.hass.areas[targetId]; if (area.icon) { return html``; } return html``; } if (targetType === "device" && this.hass.devices[targetId]) { const device = this.hass.devices[targetId]; const configEntry = device.primary_config_entry ? this.configEntryLookup[device.primary_config_entry] : undefined; const domain = configEntry?.domain; if (domain) { return html``; } } if (targetType === "entity" && this.hass.states[targetId]) { const stateObj = this.hass.states[targetId]; if (stateObj) { return html``; } } if (targetType === "label") { const label = this.getLabel(targetId); if (label?.icon) { return html``; } return html``; } return nothing; } private _selected(ev) { const item = ev.currentTarget; fireEvent(this, "value-changed", { value: item.value, }); } @eventOptions({ passive: true }) private _onItemsScroll(ev) { const top = ev.target.scrollTop ?? 0; this._itemsScrolled = top > 0; } public override scrollTo(options?: ScrollToOptions): void; public override scrollTo(x: number, y: number): void; public override scrollTo( xOrOptions?: number | ScrollToOptions, y?: number ): void { if (typeof xOrOptions === "number") { this._itemsDiv?.scrollTo(xOrOptions, y!); } else { this._itemsDiv?.scrollTo(xOrOptions); } } static styles = css` :host { display: flex; } .items { display: flex; flex-direction: column; overflow: auto; flex: 1; } .items.blank { border-radius: var(--ha-border-radius-xl); background-color: var(--ha-color-surface-default); align-items: center; color: var(--ha-color-text-secondary); padding: var(--ha-space-0); margin: var(--ha-space-0) var(--ha-space-4) max(var(--safe-area-inset-bottom), var(--ha-space-3)); line-height: var(--ha-line-height-expanded); justify-content: center; } .items.error { background-color: var(--ha-color-fill-danger-quiet-resting); color: var(--ha-color-on-danger-normal); } .items ha-md-list { --md-list-item-two-line-container-height: var(--ha-space-12); --md-list-item-leading-space: var(--ha-space-3); --md-list-item-trailing-space: var(--md-list-item-leading-space); --md-list-item-bottom-space: var(--ha-space-2); --md-list-item-top-space: var(--md-list-item-bottom-space); --md-list-item-supporting-text-font: var(--ha-font-family-body); --ha-md-list-item-gap: var(--ha-space-3); gap: var(--ha-space-2); padding: var(--ha-space-0) var(--ha-space-4); } .items ha-md-list ha-md-list-item { border-radius: var(--ha-border-radius-lg); border: 1px solid var(--ha-color-border-neutral-quiet); } .items ha-md-list { padding-bottom: max(var(--safe-area-inset-bottom), var(--ha-space-3)); } .items .item-headline { display: flex; align-items: center; gap: var(--ha-space-2); min-height: var(--ha-space-9); flex-wrap: wrap; } .items-title { position: sticky; display: flex; align-items: center; font-weight: var(--ha-font-weight-medium); padding-top: var(--ha-space-2); padding-bottom: var(--ha-space-2); padding-inline-start: var(--ha-space-8); padding-inline-end: var(--ha-space-3); top: 0; z-index: 1; background-color: var(--card-background-color); } ha-bottom-sheet .items-title { padding-top: var(--ha-space-3); } .scrolled .items-title:first-of-type { box-shadow: var(--bar-box-shadow); border-bottom: 1px solid var(--ha-color-border-neutral-quiet); } ha-icon-next { width: var(--ha-space-6); } ha-svg-icon.plus { color: var(--primary-color); } .selected-target { display: inline-flex; gap: var(--ha-space-1); justify-content: center; align-items: center; border-radius: var(--ha-border-radius-md); background: var(--ha-color-fill-neutral-normal-resting); padding: 0 var(--ha-space-2) 0 var(--ha-space-1); color: var(--ha-color-on-neutral-normal); overflow: hidden; } .selected-target .label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .selected-target ha-icon, .selected-target ha-svg-icon, .selected-target state-badge, .selected-target ha-domain-icon { display: flex; padding: var(--ha-space-1) 0; } .selected-target state-badge { --mdc-icon-size: 24px; } .selected-target state-badge, .selected-target ha-floor-icon { display: flex; height: 32px; width: 24px; align-items: center; } .selected-target ha-domain-icon { filter: grayscale(100%); } `; } declare global { interface HTMLElementTagNameMap { "ha-automation-add-items": HaAutomationAddItems; } }