138 lines
3.7 KiB
TypeScript
138 lines
3.7 KiB
TypeScript
import {
|
|
css,
|
|
CSSResultGroup,
|
|
html,
|
|
LitElement,
|
|
PropertyValues,
|
|
nothing,
|
|
} from "lit";
|
|
import { property, state } from "lit/decorators";
|
|
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
|
import { HomeAssistant } from "../../../types";
|
|
import { createCardElement } from "../create-element/create-card-element";
|
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
|
import { StackCardConfig } from "./types";
|
|
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
|
|
|
export abstract class HuiStackCard<T extends StackCardConfig = StackCardConfig>
|
|
extends LitElement
|
|
implements LovelaceCard
|
|
{
|
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
|
await import("../editor/config-elements/hui-stack-card-editor");
|
|
return document.createElement("hui-stack-card-editor");
|
|
}
|
|
|
|
public static getStubConfig(): Record<string, unknown> {
|
|
return { cards: [] };
|
|
}
|
|
|
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
|
|
|
@property({ type: Boolean }) public editMode = false;
|
|
|
|
@state() protected _cards?: LovelaceCard[];
|
|
|
|
@state() protected _config?: T;
|
|
|
|
public getCardSize(): number | Promise<number> {
|
|
return 1;
|
|
}
|
|
|
|
public setConfig(config: T): void {
|
|
if (!config || !config.cards || !Array.isArray(config.cards)) {
|
|
throw new Error("Invalid configuration");
|
|
}
|
|
this._config = config;
|
|
this._cards = config.cards.map((card) => {
|
|
const element = this._createCardElement(card) as LovelaceCard;
|
|
return element;
|
|
});
|
|
}
|
|
|
|
protected updated(changedProps: PropertyValues) {
|
|
super.updated(changedProps);
|
|
if (
|
|
!this._cards ||
|
|
(!changedProps.has("hass") && !changedProps.has("editMode"))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
for (const element of this._cards) {
|
|
if (this.hass) {
|
|
element.hass = this.hass;
|
|
}
|
|
if (this.editMode !== undefined) {
|
|
element.editMode = this.editMode;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected render() {
|
|
if (!this._config || !this._cards) {
|
|
return nothing;
|
|
}
|
|
|
|
return html`
|
|
${this._config.title
|
|
? html`<h1 class="card-header">${this._config.title}</h1>`
|
|
: ""}
|
|
<div id="root" dir=${this.hass ? computeRTLDirection(this.hass) : "ltr"}>
|
|
${this._cards}
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
static get sharedStyles(): CSSResultGroup {
|
|
return css`
|
|
.card-header {
|
|
color: var(--ha-card-header-color, var(--primary-text-color));
|
|
font-family: var(--ha-card-header-font-family, inherit);
|
|
font-size: var(--ha-card-header-font-size, 24px);
|
|
font-weight: normal;
|
|
margin-block-start: 0px;
|
|
margin-block-end: 0px;
|
|
letter-spacing: -0.012em;
|
|
line-height: 32px;
|
|
display: block;
|
|
padding: 24px 16px 16px;
|
|
}
|
|
:host {
|
|
--ha-card-border-radius: inherit !important;
|
|
--ha-card-border-width: inherit !important;
|
|
--ha-card-box-shadow: inherit !important;
|
|
}
|
|
`;
|
|
}
|
|
|
|
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
|
const element = createCardElement(cardConfig) as LovelaceCard;
|
|
if (this.hass) {
|
|
element.hass = this.hass;
|
|
}
|
|
element.addEventListener(
|
|
"ll-rebuild",
|
|
(ev) => {
|
|
ev.stopPropagation();
|
|
this._rebuildCard(element, cardConfig);
|
|
},
|
|
{ once: true }
|
|
);
|
|
return element;
|
|
}
|
|
|
|
private _rebuildCard(
|
|
cardElToReplace: LovelaceCard,
|
|
config: LovelaceCardConfig
|
|
): void {
|
|
const newCardEl = this._createCardElement(config);
|
|
if (cardElToReplace.parentElement) {
|
|
cardElToReplace.parentElement.replaceChild(newCardEl, cardElToReplace);
|
|
}
|
|
this._cards = this._cards!.map((curCardEl) =>
|
|
curCardEl === cardElToReplace ? newCardEl : curCardEl
|
|
);
|
|
}
|
|
}
|