Convert menu to a separate component file.

This commit is contained in:
Dermot Duffy
2021-09-20 21:33:37 -07:00
parent 63a5a93eeb
commit 023c66b137
4 changed files with 134 additions and 128 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ const plugins = [
export default [ export default [
{ {
input: ['src/main.ts'], input: ['src/card.ts'],
output: { output: {
file: 'dist/frigate-hass-card.js', file: 'dist/frigate-hass-card.js',
format: 'es', format: 'es',
+8 -122
View File
@@ -11,7 +11,8 @@ import { customElement, property, query, state } from 'lit/decorators';
import { classMap } from 'lit/directives/class-map.js'; import { classMap } from 'lit/directives/class-map.js';
import { until } from 'lit/directives/until.js'; import { until } from 'lit/directives/until.js';
import { renderMessage, renderErrorMessage, renderProgressIndicator } from './message'; import { FrigateCardMenu } from './components/menu';
import { renderMessage, renderErrorMessage, renderProgressIndicator } from './components/message';
import { import {
HomeAssistant, HomeAssistant,
@@ -22,9 +23,11 @@ import {
} from 'custom-card-helpers'; } from 'custom-card-helpers';
import './editor'; import './editor';
import './components/menu'
import './components/message'
import frigate_card_style from './scss/card.scss';
import frigate_card_menu_style from './scss/menu.scss'; import cardStyle from './scss/card.scss';
import { import {
MenuButton, MenuButton,
@@ -39,7 +42,6 @@ import type {
ExtendedHomeAssistant, ExtendedHomeAssistant,
FrigateCardConfig, FrigateCardConfig,
FrigateCardView, FrigateCardView,
FrigateMenuMode,
ResolvedMedia, ResolvedMedia,
} from './types'; } from './types';
import { CARD_VERSION } from './const'; import { CARD_VERSION } from './const';
@@ -70,8 +72,6 @@ console.info(
description: localize('common.frigate_card_description'), description: localize('common.frigate_card_description'),
}); });
type FrigateCardMenuCallback = (name: string) => any;
// Determine whether the card should be updated based on Home Assistant changes. // Determine whether the card should be updated based on Home Assistant changes.
function shouldUpdateBasedOnHass( function shouldUpdateBasedOnHass(
newHass: HomeAssistant | null, newHass: HomeAssistant | null,
@@ -100,119 +100,6 @@ function shouldUpdateBasedOnHass(
return false; return false;
} }
// A menu for the Frigate card.
@customElement('frigate-card-menu')
export class FrigateCardMenu extends LitElement {
static FRIGATE_CARD_MENU_ID: string = 'frigate-card-menu-id' as const;
@property({ attribute: false })
protected menuMode: FrigateMenuMode = 'hidden-top';
@property({ attribute: false })
protected expand = false;
@property({ attribute: false })
protected actionCallback: FrigateCardMenuCallback | null = null;
@property({ attribute: false })
public buttons: Map<string, MenuButton> = new Map();
// Call the callback.
protected _callAction(name: string): void {
if (this.menuMode.startsWith('hidden-')) {
if (name == 'frigate') {
this.expand = !this.expand;
return;
}
// Collapse menu after the user clicks on something.
this.expand = false;
}
if (this.actionCallback) {
this.actionCallback(name);
}
}
// Render a menu button.
protected _renderButton(name: string, button: MenuButton): TemplateResult {
const classes = {
button: true,
emphasize: button.emphasize ?? false,
};
return html` <ha-icon-button
class="${classMap(classes)}"
icon=${button.icon || 'mdi:gesture-tap-button'}
title=${button.description}
@click=${() => this._callAction(name)}
></ha-icon-button>`;
}
// Render the Frigate menu button.
protected _renderFrigateButton(name: string, button: MenuButton): TemplateResult {
const icon =
this.menuMode.startsWith('hidden-') && !this.expand
? 'mdi:alpha-f-box-outline'
: 'mdi:alpha-f-box';
return this._renderButton(name, Object.assign({}, button, { icon: icon }));
}
// Render the menu.
protected render(): TemplateResult {
// If the menu is off, or if it's in hidden mode but there's no button to
// unhide it, just show nothing.
if (
this.menuMode == 'none' ||
(this.menuMode.startsWith('hidden-') && !this.buttons.get('frigate'))
) {
return html``;
}
const classes = {
'frigate-card-menu': true,
'overlay-hidden':
this.menuMode.startsWith('hidden-') ||
this.menuMode.startsWith('overlay-') ||
this.menuMode.startsWith('hover-'),
'expanded-horizontal':
(this.menuMode.startsWith('overlay-') ||
this.menuMode.startsWith('hover-') ||
this.expand) &&
(this.menuMode.endsWith('-top') || this.menuMode.endsWith('-bottom')),
'expanded-vertical':
(this.menuMode.startsWith('overlay-') ||
this.menuMode.startsWith('hover-') ||
this.expand) &&
(this.menuMode.endsWith('-left') || this.menuMode.endsWith('-right')),
full: ['above', 'below'].includes(this.menuMode),
left: this.menuMode.endsWith('-left'),
right: this.menuMode.endsWith('-right'),
top: this.menuMode.endsWith('-top'),
bottom: this.menuMode.endsWith('-bottom'),
};
return html`
<div class=${classMap(classes)}>
${Array.from(this.buttons.keys()).map((name) => {
const button = this.buttons.get(name);
if (button) {
return name === 'frigate'
? this._renderFrigateButton(name, button)
: this._renderButton(name, button);
}
return html``;
})}
</div>
`;
}
// Return compiled CSS styles (thus safe to use with unsafeCSS).
static get styles(): CSSResultGroup {
return unsafeCSS(frigate_card_menu_style);
}
}
interface ViewParameters { interface ViewParameters {
view?: FrigateCardView; view?: FrigateCardView;
target?: BrowseMediaSource; target?: BrowseMediaSource;
@@ -285,7 +172,7 @@ export class FrigateCard extends LitElement {
// Whether or not there is an active clip being played. // Whether or not there is an active clip being played.
protected _clipPlaying = false; protected _clipPlaying = false;
@query(`#${FrigateCardMenu.FRIGATE_CARD_MENU_ID}`) @query("frigate-card-menu")
_menu!: FrigateCardMenu | null; _menu!: FrigateCardMenu | null;
// A small cache to avoid needing to create a new list of entities every time // A small cache to avoid needing to create a new list of entities every time
@@ -1039,7 +926,6 @@ export class FrigateCard extends LitElement {
}; };
return html` return html`
<frigate-card-menu <frigate-card-menu
id="${FrigateCardMenu.FRIGATE_CARD_MENU_ID}"
class="${classMap(classes)}" class="${classMap(classes)}"
.actionCallback=${this._menuActionHandler.bind(this)} .actionCallback=${this._menuActionHandler.bind(this)}
.menuMode=${this.config.menu_mode} .menuMode=${this.config.menu_mode}
@@ -1094,7 +980,7 @@ export class FrigateCard extends LitElement {
// Return compiled CSS styles (thus safe to use with unsafeCSS). // Return compiled CSS styles (thus safe to use with unsafeCSS).
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return unsafeCSS(frigate_card_style); return unsafeCSS(cardStyle);
} }
// Get the Lovelace card size. // Get the Lovelace card size.
+121
View File
@@ -0,0 +1,121 @@
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
import { customElement, property } from 'lit/decorators';
import { classMap } from 'lit/directives/class-map.js';
import menuStyle from '../scss/menu.scss';
import { MenuButton } from '../types';
import type { FrigateMenuMode } from '../types';
type FrigateCardMenuCallback = (name: string) => void;
// A menu for the Frigate card.
@customElement('frigate-card-menu')
export class FrigateCardMenu extends LitElement {
@property({ attribute: false })
protected menuMode: FrigateMenuMode = 'hidden-top';
@property({ attribute: false })
protected expand = false;
@property({ attribute: false })
protected actionCallback: FrigateCardMenuCallback | null = null;
@property({ attribute: false })
public buttons: Map<string, MenuButton> = new Map();
// Call the callback.
protected _callAction(name: string): void {
if (this.menuMode.startsWith('hidden-')) {
if (name == 'frigate') {
this.expand = !this.expand;
return;
}
// Collapse menu after the user clicks on something.
this.expand = false;
}
if (this.actionCallback) {
this.actionCallback(name);
}
}
// Render a menu button.
protected _renderButton(name: string, button: MenuButton): TemplateResult {
const classes = {
button: true,
emphasize: button.emphasize ?? false,
};
return html` <ha-icon-button
class="${classMap(classes)}"
icon=${button.icon || 'mdi:gesture-tap-button'}
title=${button.description}
@click=${() => this._callAction(name)}
></ha-icon-button>`;
}
// Render the Frigate menu button.
protected _renderFrigateButton(name: string, button: MenuButton): TemplateResult {
const icon =
this.menuMode.startsWith('hidden-') && !this.expand
? 'mdi:alpha-f-box-outline'
: 'mdi:alpha-f-box';
return this._renderButton(name, Object.assign({}, button, { icon: icon }));
}
// Render the menu.
protected render(): TemplateResult {
// If the menu is off, or if it's in hidden mode but there's no button to
// unhide it, just show nothing.
if (
this.menuMode == 'none' ||
(this.menuMode.startsWith('hidden-') && !this.buttons.get('frigate'))
) {
return html``;
}
const classes = {
'frigate-card-menu': true,
'overlay-hidden':
this.menuMode.startsWith('hidden-') ||
this.menuMode.startsWith('overlay-') ||
this.menuMode.startsWith('hover-'),
'expanded-horizontal':
(this.menuMode.startsWith('overlay-') ||
this.menuMode.startsWith('hover-') ||
this.expand) &&
(this.menuMode.endsWith('-top') || this.menuMode.endsWith('-bottom')),
'expanded-vertical':
(this.menuMode.startsWith('overlay-') ||
this.menuMode.startsWith('hover-') ||
this.expand) &&
(this.menuMode.endsWith('-left') || this.menuMode.endsWith('-right')),
full: ['above', 'below'].includes(this.menuMode),
left: this.menuMode.endsWith('-left'),
right: this.menuMode.endsWith('-right'),
top: this.menuMode.endsWith('-top'),
bottom: this.menuMode.endsWith('-bottom'),
};
return html`
<div class=${classMap(classes)}>
${Array.from(this.buttons.keys()).map((name) => {
const button = this.buttons.get(name);
if (button) {
return name === 'frigate'
? this._renderFrigateButton(name, button)
: this._renderButton(name, button);
}
return html``;
})}
</div>
`;
}
// Return compiled CSS styles (thus safe to use with unsafeCSS).
static get styles(): CSSResultGroup {
return unsafeCSS(menuStyle);
}
}
+4 -5
View File
@@ -1,8 +1,7 @@
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit'; import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
import { customElement, property } from 'lit/decorators'; import { customElement, property } from 'lit/decorators';
import { localize } from './localize/localize'; import { localize } from '../localize/localize';
import messageStyle from '../scss/message.scss';
import frigate_card_message_style from './scss/message.scss';
const URL_TROUBLESHOOTING = const URL_TROUBLESHOOTING =
'https://github.com/dermotduffy/frigate-hass-card#troubleshooting'; 'https://github.com/dermotduffy/frigate-hass-card#troubleshooting';
@@ -26,7 +25,7 @@ export class FrigateCardMessage extends LitElement {
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return unsafeCSS(frigate_card_message_style); return unsafeCSS(messageStyle);
} }
} }
@@ -54,7 +53,7 @@ export class FrigateCardProgressIndicator extends LitElement {
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return unsafeCSS(frigate_card_message_style); return unsafeCSS(messageStyle);
} }
} }