import { HomeAssistant } from '@dermotduffy/custom-card-helpers'; import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { styleMap } from 'lit/directives/style-map.js'; import { actionHandler } from '../action-handler-directive.js'; import { MenuController } from '../components-lib/menu-controller.js'; import type { MenuConfig, MenuItem } from '../config/types.js'; import menuStyle from '../scss/menu.scss'; import { frigateCardHasAction } from '../utils/action.js'; import { EntityRegistryManager } from '../utils/ha/entity-registry/index.js'; import './submenu.js'; @customElement('frigate-card-menu') export class FrigateCardMenu extends LitElement { protected _controller = new MenuController(this); @property({ attribute: false }) public entityRegistryManager?: EntityRegistryManager; @property({ attribute: false }) public hass?: HomeAssistant; set menuConfig(menuConfig: MenuConfig) { this._controller.setMenuConfig(menuConfig); } set buttons(buttons: MenuItem[]) { this._controller.setButtons(buttons); } set expanded(expanded: boolean) { this._controller.setExpanded(expanded); } public toggleMenu(): void { this._controller.toggleExpanded(); } protected _renderButton(button: MenuItem): TemplateResult | void { if (!this.hass) { return; } if (button.type === 'custom:frigate-card-menu-submenu') { return html` this.hass && this._controller.actionHandler(this.hass, ev)} > `; } else if (button.type === 'custom:frigate-card-menu-submenu-select') { return html` this.hass && this._controller.actionHandler(this.hass, ev)} > `; } // ===================================================================================== // For `data-domain` and `data-state`, see: See // https://github.com/home-assistant/frontend/blob/dev/src/components/entity/state-badge.ts#L54 // ===================================================================================== // Buttons are styled in a few ways (in order of precedence): // // - User provided style // - Color/Brightness styling for the `light` domain (calculated in // `refreshDynamicStateParameters`) // - Static styling based on domain (`data-domain`) and state // (`data-state`). This looks up a CSS style in `menu.scss`. const buttonState = this._controller.getFreshButtonState(this.hass, button); const svgPath = this._controller.getSVGPath(button); return html` this.hass && this._controller.actionHandler(this.hass, ev, button)} > ${svgPath ? html`` : html``} `; } protected render(): TemplateResult | void { const config = this._controller.getMenuConfig(); const style = config?.style; if (!config || style === 'none') { return; } const matchingButtons = this._controller.getButtons('matching'); const opposingButtons = this._controller.getButtons('opposing'); return html`
${matchingButtons.map((button) => this._renderButton(button))}
${opposingButtons.map((button) => this._renderButton(button))}
`; } static get styles(): CSSResultGroup { return unsafeCSS(menuStyle); } } declare global { interface HTMLElementTagNameMap { 'frigate-card-menu': FrigateCardMenu; } }