diff --git a/src/common.ts b/src/common.ts index 34e5511a..35efece0 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,5 +1,10 @@ import { HassEntity, MessageBase } from 'home-assistant-js-websocket'; -import { HomeAssistant, handleActionConfig, hasAction, stateIcon } from 'custom-card-helpers'; +import { + HomeAssistant, + handleActionConfig, + hasAction, + stateIcon, +} from 'custom-card-helpers'; import { StyleInfo } from 'lit/directives/style-map'; import { ZodSchema, z } from 'zod'; import { isEqual } from 'lodash-es'; @@ -359,6 +364,23 @@ function computeStyle(state: HassEntity): StyleInfo { }; } +/** + * Determine the string state of a given stateObj. + * From: https://github.com/home-assistant/frontend/blob/dev/src/common/entity/compute_active_state.ts + * @param stateObj The HassEntity object from `hass.states`. + * @returns A string state, e.g. 'on'. + */ +export const computeActiveState = (stateObj: HassEntity): string => { + const domain = stateObj.entity_id.split('.')[0]; + let state = stateObj.state; + + if (domain === 'climate') { + state = stateObj.attributes.hvac_action; + } + + return state; +}; + /** * Use Home Assistant state to refresh state parameters for an item to be rendered. * @param hass Home Assistant object. @@ -373,11 +395,7 @@ export function refreshDynamicStateParameters( return params; } const state = hass.states[params.entity]; - if ( - !!state && - !!params.state_color && - ['on', 'active', 'home'].includes(state.state) - ) { + if (!!state && !!params.state_color) { params.style = { ...computeStyle(state), ...params.style }; } params.title = params.title ?? (state?.attributes?.friendly_name || params.entity); @@ -545,9 +563,11 @@ export const frigateCardHandleActionConfig = ( * @param config The action config in question. * @returns `true` if there's a real action defined, `false` otherwise. */ -export const frigateCardHasAction = (config?: ActionType | ActionType[] | undefined): boolean => { +export const frigateCardHasAction = ( + config?: ActionType | ActionType[] | undefined, +): boolean => { if (Array.isArray(config)) { return !!config.find((item) => hasAction(item)); } return hasAction(config); -} \ No newline at end of file +}; diff --git a/src/components/menu.ts b/src/components/menu.ts index 729ea42f..8f200a22 100644 --- a/src/components/menu.ts +++ b/src/components/menu.ts @@ -1,7 +1,8 @@ -import { HASSDomEvent, HomeAssistant } from 'custom-card-helpers'; +import { computeStateDomain, HASSDomEvent, HomeAssistant } from 'custom-card-helpers'; import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; +import { ifDefined } from 'lit/directives/if-defined'; import { styleMap } from 'lit/directives/style-map.js'; import { actionHandler } from '../action-handler-directive.js'; @@ -17,6 +18,7 @@ import type { StateParameters, } from '../types.js'; import { + computeActiveState, convertActionToFrigateCardCustomAction, frigateCardHandleActionConfig, frigateCardHasAction, @@ -218,10 +220,7 @@ export class FrigateCardMenu extends LitElement { const svgPath = stateParameters.icon === FRIGATE_BUTTON_MENU_ICON ? FRIGATE_ICON_FILLED : ''; - if (button.type === 'custom:frigate-card-menu-state-icon') { - if (!this.hass) { - return; - } + if (this.hass && button.type === 'custom:frigate-card-menu-state-icon') { stateParameters = refreshDynamicStateParameters(this.hass, stateParameters); } @@ -232,7 +231,28 @@ export class FrigateCardMenu extends LitElement { button: true, }; + const stateObj = stateParameters.entity ? this.hass?.states[stateParameters.entity] : undefined; + const domain = stateObj ? computeStateDomain(stateObj) : undefined; + + // ===================================================================================== + // 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`. + return html`