import type { Corner } from "@material/mwc-menu"; import "@material/mwc-menu/mwc-menu-surface"; import { mdiFilterVariant } from "@mdi/js"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; import { stopPropagation } from "../common/dom/stop_propagation"; import { computeStateName } from "../common/entity/compute_state_name"; import { computeDeviceName } from "../data/device_registry"; import { findRelated, RelatedResult } from "../data/search"; import type { HomeAssistant } from "../types"; import "./device/ha-device-picker"; import "./entity/ha-entity-picker"; import "./ha-area-picker"; import "./ha-icon-button"; declare global { // for fire event interface HASSDomEvents { "related-changed": { value?: FilterValue; items?: RelatedResult; filter?: string; }; } } interface FilterValue { area?: string; device?: string; entity?: string; } @customElement("ha-button-related-filter-menu") export class HaRelatedFilterButtonMenu extends LitElement { @property() public hass!: HomeAssistant; @property() public corner: Corner = "BOTTOM_START"; @property({ type: Boolean, reflect: true }) public narrow = false; @property({ type: Boolean }) public disabled = false; @property({ attribute: false }) public value?: FilterValue; /** * Show no entities of these domains. * @type {Array} * @attr exclude-domains */ @property({ type: Array, attribute: "exclude-domains" }) public excludeDomains?: string[]; @state() private _open = false; protected render(): TemplateResult { return html` `; } private _handleClick(): void { if (this.disabled) { return; } this._open = true; } private _onClosed(ev): void { ev.stopPropagation(); this._open = false; } private _preventDefault(ev) { ev.preventDefault(); } private async _entityPicked(ev: CustomEvent) { ev.stopPropagation(); const entityId = ev.detail.value; if (!entityId) { fireEvent(this, "related-changed", { value: undefined }); return; } const filter = this.hass.localize( "ui.components.related-filter-menu.filtered_by_entity", { entity_name: computeStateName( (ev.currentTarget as any).comboBox.selectedItem ), } ); const items = await findRelated(this.hass, "entity", entityId); fireEvent(this, "related-changed", { value: { entity: entityId }, filter, items, }); } private async _devicePicked(ev: CustomEvent) { ev.stopPropagation(); const deviceId = ev.detail.value; if (!deviceId) { fireEvent(this, "related-changed", { value: undefined }); return; } const filter = this.hass.localize( "ui.components.related-filter-menu.filtered_by_device", { device_name: computeDeviceName( (ev.currentTarget as any).comboBox.selectedItem, this.hass ), } ); const items = await findRelated(this.hass, "device", deviceId); fireEvent(this, "related-changed", { value: { device: deviceId }, filter, items, }); } private async _areaPicked(ev: CustomEvent) { ev.stopPropagation(); const areaId = ev.detail.value; if (!areaId) { fireEvent(this, "related-changed", { value: undefined }); return; } const filter = this.hass.localize( "ui.components.related-filter-menu.filtered_by_area", { area_name: (ev.currentTarget as any).comboBox.selectedItem.name } ); const items = await findRelated(this.hass, "area", areaId); fireEvent(this, "related-changed", { value: { area: areaId }, filter, items, }); } static get styles(): CSSResultGroup { return css` :host { display: inline-block; position: relative; --mdc-menu-min-width: 250px; } ha-area-picker, ha-device-picker, ha-entity-picker { display: block; width: 300px; padding: 4px 16px; box-sizing: border-box; } ha-area-picker { padding-top: 16px; } ha-entity-picker { padding-bottom: 16px; } :host([narrow]) ha-area-picker, :host([narrow]) ha-device-picker, :host([narrow]) ha-entity-picker { width: 100%; } `; } } declare global { interface HTMLElementTagNameMap { "ha-button-related-filter-menu": HaRelatedFilterButtonMenu; } }