Initial submenu support.

This commit is contained in:
Dermot Duffy
2021-12-17 18:08:07 -08:00
parent 85fd0eebdd
commit 93ff4d8445
8 changed files with 153 additions and 10 deletions
+4
View File
@@ -9,6 +9,7 @@ import {
MenuIcon,
MenuStateIcon,
PictureElements,
MenuSubmenu,
} from '../types.js';
import {
dispatchErrorMessageEvent,
@@ -339,3 +340,6 @@ export class FrigateCardElementsMenuIcon extends FrigateCardElementsBaseMenuIcon
@customElement('frigate-card-menu-state-icon')
export class FrigateCardElementsMenuStateIcon extends FrigateCardElementsBaseMenuIcon<MenuStateIcon> {}
@customElement('frigate-card-menu-submenu')
export class FrigateCardElementsMenuSubmenu extends FrigateCardElementsBaseMenuIcon<MenuSubmenu> {}
+24 -4
View File
@@ -14,7 +14,10 @@ import { StyleInfo, styleMap } from 'lit/directives/style-map.js';
import { actionHandler } from '../action-handler-directive.js';
import './submenu.js';
import type {
Actions,
ExtendedHomeAssistant,
MenuButton,
MenuConfig,
@@ -61,18 +64,26 @@ export class FrigateCardMenu extends LitElement {
* @param ev The action event.
* @param button The button configuration.
*/
protected _actionHandler(ev: CustomEvent, button: MenuButton): void {
protected _actionHandler(ev: CustomEvent<{action: string, config?: Actions}>, config?: Actions): void {
if (!ev) {
return;
}
// If the event itself contains a configuration then use that. This is
// useful in cases where the registration of the event handler does not have
// access to the actual desired configuration (e.g. action events generated
// by a submenu).
if (ev.detail.config) {
config = ev.detail.config;
}
// These interactions should only be handled by the card, as nothing
// upstream has the user-provided configuration.
ev.stopPropagation();
const interaction: string = ev.detail.action;
const action = getActionConfigGivenAction(interaction, button);
if (!action || !interaction) {
const action = getActionConfigGivenAction(interaction, config);
if (!config || !action || !interaction) {
return;
}
@@ -92,7 +103,7 @@ export class FrigateCardMenu extends LitElement {
// Collapse menu after the user clicks on something.
this.expand = false;
handleAction(this, this.hass as HomeAssistant, button, interaction);
handleAction(this, this.hass as HomeAssistant, config, interaction);
}
/**
@@ -169,6 +180,15 @@ export class FrigateCardMenu extends LitElement {
button: true,
};
if (button.type == 'custom:frigate-card-menu-submenu') {
return html`
<frigate-card-submenu
.submenu=${button}
@action=${this._actionHandler.bind(this)}
>
</frigate-card-submenu>`;
}
// TODO: Upon a safe distance from the release of HA 2021.11 these
// attributes can be removed from the <ha-icon-button>.
// - icon (replaced with the embedded <ha-icon>)
+60
View File
@@ -0,0 +1,60 @@
import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit';
import { customElement, property } from 'lit/decorators';
import { actionHandler } from '../action-handler-directive.js';
import { MenuSubmenu } from '../types.js';
import submenuStyle from '../scss/submenu.scss';
import { hasAction } from 'custom-card-helpers';
@customElement('frigate-card-submenu')
export class FrigateCardSubmenu extends LitElement {
@property({ attribute: false })
public submenu?: MenuSubmenu;
protected render(): TemplateResult {
if (!this.submenu) {
return html``;
}
return html`
<ha-button-menu corner="BOTTOM_LEFT">
<ha-icon-button
class="button"
slot="trigger"
.label=${this.submenu.title || ''}
.actionHandler=${actionHandler({
hasHold: hasAction(this.submenu.hold_action),
hasDoubleClick: hasAction(this.submenu.double_tap_action),
})}
>
<ha-icon icon="${this.submenu.icon}"></ha-icon>
</ha-icon-button>
${this.submenu.items.map(
(item) => html`
<mwc-list-item
graphic="icon"
aria-label="${item.title || ''}"
@action=${(ev) => {
// Attach the action config so ascendants have access to it.
ev.detail.config = item;
}}
.actionHandler=${actionHandler({
hasHold: hasAction(item.hold_action),
hasDoubleClick: hasAction(item.double_tap_action),
})}
>
${item.title || ''}
${item.icon
? html` <ha-icon slot="graphic" icon="${item.icon}"> </ha-icon>`
: ``}
</mwc-list-item>
`,
)}
</ha-button-menu>
`;
}
static get styles(): CSSResultGroup {
return unsafeCSS(submenuStyle);
}
}