diff --git a/src/panels/lovelace/cards/hui-card.ts b/src/panels/lovelace/cards/hui-card.ts index 4da45042df15..8f313ff62d00 100644 --- a/src/panels/lovelace/cards/hui-card.ts +++ b/src/panels/lovelace/cards/hui-card.ts @@ -25,7 +25,7 @@ declare global { export class HuiCard extends ReactiveElement { @property({ attribute: false }) public hass?: HomeAssistant; - @property({ type: Boolean }) public editMode = false; + @property({ type: Boolean }) public preview = false; @property({ type: Boolean }) public isPanel = false; @@ -89,7 +89,9 @@ export class HuiCard extends ReactiveElement { private _createElement(config: LovelaceCardConfig) { const element = createCardElement(config); element.hass = this.hass; - element.editMode = this.editMode; + element.preview = this.preview; + // For backwards compatibility + (element as any).editMode = this.preview; // Update element when the visibility of the card changes (e.g. conditional card or filter card) element.addEventListener("card-visibility-changed", (ev: Event) => { ev.stopPropagation(); @@ -135,9 +137,11 @@ export class HuiCard extends ReactiveElement { this._buildElement(createErrorCardConfig(e.message, null)); } } - if (changedProps.has("editMode")) { + if (changedProps.has("preview")) { try { - this._element.editMode = this.editMode; + this._element.preview = this.preview; + // For backwards compatibility + (this._element as any).editMode = this.preview; } catch (e: any) { this._buildElement(createErrorCardConfig(e.message, null)); } @@ -192,7 +196,7 @@ export class HuiCard extends ReactiveElement { const visible = forceVisible || - this.editMode || + this.preview || !this.config?.visibility || checkConditionsMet(this.config.visibility, this.hass); this._setElementVisibility(visible); diff --git a/src/panels/lovelace/cards/hui-conditional-card.ts b/src/panels/lovelace/cards/hui-conditional-card.ts index 0152e73b60da..9a57b3e5a343 100644 --- a/src/panels/lovelace/cards/hui-conditional-card.ts +++ b/src/panels/lovelace/cards/hui-conditional-card.ts @@ -39,13 +39,13 @@ class HuiConditionalCard extends HuiConditionalBase implements LovelaceCard { private _createCardElement(cardConfig: LovelaceCardConfig) { const element = document.createElement("hui-card"); element.hass = this.hass; - element.editMode = this.editMode; + element.preview = this.preview; element.config = cardConfig; return element; } protected setVisibility(conditionMet: boolean): void { - const visible = this.editMode || conditionMet; + const visible = this.preview || conditionMet; const previouslyHidden = this.hidden; super.setVisibility(conditionMet); if (previouslyHidden !== this.hidden) { diff --git a/src/panels/lovelace/cards/hui-entity-filter-card.ts b/src/panels/lovelace/cards/hui-entity-filter-card.ts index 25071a7b2a65..ca8372b4a7c0 100644 --- a/src/panels/lovelace/cards/hui-entity-filter-card.ts +++ b/src/panels/lovelace/cards/hui-entity-filter-card.ts @@ -55,7 +55,7 @@ export class HuiEntityFilterCard @property({ type: Boolean }) public isPanel = false; - @property({ type: Boolean }) public editMode = false; + @property({ type: Boolean }) public preview = false; @state() private _config?: EntityFilterCardConfig; @@ -117,7 +117,7 @@ export class HuiEntityFilterCard protected shouldUpdate(changedProps: PropertyValues): boolean { if (this._element) { this._element.hass = this.hass; - this._element.editMode = this.editMode; + this._element.preview = this.preview; this._element.isPanel = this.isPanel; } @@ -247,7 +247,7 @@ export class HuiEntityFilterCard private _createCardElement(cardConfig: LovelaceCardConfig) { const element = document.createElement("hui-card"); element.hass = this.hass; - element.editMode = this.editMode; + element.preview = this.preview; element.config = cardConfig; return element; } diff --git a/src/panels/lovelace/cards/hui-error-card.ts b/src/panels/lovelace/cards/hui-error-card.ts index a1047ec090ef..745b45852b37 100644 --- a/src/panels/lovelace/cards/hui-error-card.ts +++ b/src/panels/lovelace/cards/hui-error-card.ts @@ -10,7 +10,7 @@ import { ErrorCardConfig } from "./types"; export class HuiErrorCard extends LitElement implements LovelaceCard { public hass?: HomeAssistant; - @property({ attribute: false }) public editMode = false; + @property({ attribute: false }) public preview = false; @state() private _config?: ErrorCardConfig; diff --git a/src/panels/lovelace/cards/hui-markdown-card.ts b/src/panels/lovelace/cards/hui-markdown-card.ts index a6d75a00fa9b..ec78139c2280 100644 --- a/src/panels/lovelace/cards/hui-markdown-card.ts +++ b/src/panels/lovelace/cards/hui-markdown-card.ts @@ -38,7 +38,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { @property({ attribute: false }) public hass?: HomeAssistant; - @property({ type: Boolean }) public editMode = false; + @property({ type: Boolean }) public preview = false; @state() private _config?: MarkdownCardConfig; @@ -163,12 +163,12 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { user: this.hass.user!.name, }, strict: true, - report_errors: this.editMode, + report_errors: this.preview, } ); await this._unsubRenderTemplate; } catch (e: any) { - if (this.editMode) { + if (this.preview) { this._error = e.message; this._errorLevel = undefined; } diff --git a/src/panels/lovelace/cards/hui-stack-card.ts b/src/panels/lovelace/cards/hui-stack-card.ts index aad2eacb4010..a308e368eb59 100644 --- a/src/panels/lovelace/cards/hui-stack-card.ts +++ b/src/panels/lovelace/cards/hui-stack-card.ts @@ -23,7 +23,7 @@ export abstract class HuiStackCard @property({ attribute: false }) public hass?: HomeAssistant; - @property({ type: Boolean }) public editMode = false; + @property({ type: Boolean }) public preview = false; @state() protected _cards?: HuiCard[]; @@ -58,7 +58,7 @@ export abstract class HuiStackCard } if (changedProperties.has("editMode")) { this._cards.forEach((card) => { - card.editMode = this.editMode; + card.preview = this.preview; }); } } @@ -67,7 +67,7 @@ export abstract class HuiStackCard private _createCardElement(cardConfig: LovelaceCardConfig) { const element = document.createElement("hui-card"); element.hass = this.hass; - element.editMode = this.editMode; + element.preview = this.preview; element.config = cardConfig; return element; } diff --git a/src/panels/lovelace/components/hui-conditional-base.ts b/src/panels/lovelace/components/hui-conditional-base.ts index c921c2623ddf..86ff09f57d5d 100644 --- a/src/panels/lovelace/components/hui-conditional-base.ts +++ b/src/panels/lovelace/components/hui-conditional-base.ts @@ -24,7 +24,7 @@ declare global { export class HuiConditionalBase extends ReactiveElement { @property({ attribute: false }) public hass?: HomeAssistant; - @property({ type: Boolean }) public editMode = false; + @property({ type: Boolean }) public preview = false; @state() protected _config?: ConditionalCardConfig | ConditionalRowConfig; @@ -116,7 +116,7 @@ export class HuiConditionalBase extends ReactiveElement { changed.has("_element") || changed.has("_config") || changed.has("hass") || - changed.has("editMode") + changed.has("preview") ) { this._listenMediaQueries(); this._updateVisibility(); @@ -128,7 +128,7 @@ export class HuiConditionalBase extends ReactiveElement { return; } - this._element.editMode = this.editMode; + this._element.preview = this.preview; const conditionMet = checkConditionsMet( this._config!.conditions, @@ -142,7 +142,7 @@ export class HuiConditionalBase extends ReactiveElement { if (!this._element || !this.hass) { return; } - const visible = this.editMode || conditionMet; + const visible = this.preview || conditionMet; if (this.hidden !== !visible) { this.toggleAttribute("hidden", !visible); this.style.setProperty("display", visible ? "" : "none"); diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-delete-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-delete-card.ts index 59974f4f001d..65690b750161 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-delete-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-delete-card.ts @@ -48,7 +48,7 @@ export class HuiDialogDeleteCard extends LitElement { ` diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts index 288e83529025..a1a90408be88 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts @@ -9,6 +9,7 @@ import { nothing, } from "lit"; import { customElement, property, query, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; import type { HASSDomEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event"; import { computeRTLDirection } from "../../../../common/util/compute_rtl"; @@ -29,6 +30,7 @@ import type { HassDialog } from "../../../../dialogs/make-dialog-manager"; import { haStyleDialog } from "../../../../resources/styles"; import type { HomeAssistant } from "../../../../types"; import { showSaveSuccessToast } from "../../../../util/toast-saved-success"; +import "../../sections/hui-section"; import { addCard, replaceCard } from "../config-util"; import { getCardDocumentationURL } from "../get-card-documentation-url"; import type { ConfigChangedEvent } from "../hui-element-editor"; @@ -245,12 +247,23 @@ export class HuiDialogEditCard >
- + ${this._isInSection + ? html` + + ` + : html` + + `} ${this._error ? html` { + const { cards, title, ...containerConfig } = this + ._containerConfig as LovelaceSectionConfig; + + return { + ...containerConfig, + cards: cardConfig ? [cardConfig] : [], + }; + } + ); + private get _canSave(): boolean { if (this._saving) { return false; @@ -454,9 +483,17 @@ export class HuiDialogEditCard } .content hui-card { - margin: 4px auto; + display: block; + padding: 4px; + margin: 0 auto; max-width: 390px; } + .content hui-section { + display: block; + padding: 4px; + margin: 0 auto; + max-width: var(--ha-view-sections-column-max-width, 500px); + } .content .element-editor { margin: 0 10px; } @@ -476,6 +513,11 @@ export class HuiDialogEditCard margin: auto 0px; max-width: 500px; } + .content hui-section { + padding: 8px 10px; + margin: auto 0px; + max-width: var(--ha-view-sections-column-max-width, 500px); + } } .hidden { display: none; diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts index 37b4cd4cf026..ef2618ff54ea 100644 --- a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts +++ b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts @@ -75,6 +75,7 @@ export class HuiDialogSuggestCard extends LitElement {
`; @@ -84,7 +85,11 @@ export class HuiDialogSuggestCard extends LitElement {
${this._cardConfig.map( (cardConfig) => html` - + ` )}
diff --git a/src/panels/lovelace/entity-rows/types.ts b/src/panels/lovelace/entity-rows/types.ts index 9ec1bd75caa0..9fe17e5fd5ef 100644 --- a/src/panels/lovelace/entity-rows/types.ts +++ b/src/panels/lovelace/entity-rows/types.ts @@ -81,7 +81,7 @@ export type LovelaceRowConfig = export interface LovelaceRow extends HTMLElement { hass?: HomeAssistant; - editMode?: boolean; + preview?: boolean; setConfig(config: LovelaceRowConfig); } diff --git a/src/panels/lovelace/sections/hui-section.ts b/src/panels/lovelace/sections/hui-section.ts index 798025e0cce6..1e4f9ed8bfb8 100644 --- a/src/panels/lovelace/sections/hui-section.ts +++ b/src/panels/lovelace/sections/hui-section.ts @@ -41,6 +41,8 @@ export class HuiSection extends ReactiveElement { @property({ attribute: false }) public lovelace?: Lovelace; + @property({ type: Boolean, reflect: true }) public preview = false; + @property({ type: Number }) public index!: number; @property({ type: Number }) public viewIndex!: number; @@ -56,7 +58,7 @@ export class HuiSection extends ReactiveElement { private _createCardElement(cardConfig: LovelaceCardConfig) { const element = document.createElement("hui-card"); element.hass = this.hass; - element.editMode = this.lovelace?.editMode || false; + element.preview = this.preview; element.config = cardConfig; element.addEventListener("card-updated", (ev: Event) => { ev.stopPropagation(); @@ -118,8 +120,10 @@ export class HuiSection extends ReactiveElement { } if (changedProperties.has("lovelace")) { this._layoutElement.lovelace = this.lovelace; + } + if (changedProperties.has("preview")) { this._cards.forEach((element) => { - element.editMode = this.lovelace?.editMode || false; + element.preview = this.preview; }); } if (changedProperties.has("_cards")) { @@ -205,7 +209,7 @@ export class HuiSection extends ReactiveElement { } const visible = forceVisible || - this.lovelace?.editMode || + this.preview || !this.config.visibility || checkConditionsMet(this.config.visibility, this.hass); diff --git a/src/panels/lovelace/types.ts b/src/panels/lovelace/types.ts index 5aba06015d5c..eaf582057322 100644 --- a/src/panels/lovelace/types.ts +++ b/src/panels/lovelace/types.ts @@ -48,7 +48,7 @@ export type LovelaceLayoutOptions = { export interface LovelaceCard extends HTMLElement { hass?: HomeAssistant; isPanel?: boolean; - editMode?: boolean; + preview?: boolean; getCardSize(): number | Promise; getLayoutOptions?(): LovelaceLayoutOptions; setConfig(config: LovelaceCardConfig): void; diff --git a/src/panels/lovelace/views/hui-masonry-view.ts b/src/panels/lovelace/views/hui-masonry-view.ts index b360b9601bbd..520856ad7ba5 100644 --- a/src/panels/lovelace/views/hui-masonry-view.ts +++ b/src/panels/lovelace/views/hui-masonry-view.ts @@ -248,17 +248,17 @@ export class MasonryView extends LitElement implements LovelaceViewElement { }); } - private _addCardToColumn(columnEl, index, editMode) { + private _addCardToColumn(columnEl, index, preview) { const card: HuiCard = this.cards[index]; - if (!editMode || this.isStrategy) { - card.editMode = false; + if (!preview || this.isStrategy) { + card.preview = false; columnEl.appendChild(card); } else { const wrapper = document.createElement("hui-card-options"); wrapper.hass = this.hass; wrapper.lovelace = this.lovelace; wrapper.path = [this.index!, index]; - card.editMode = true; + card.preview = true; wrapper.appendChild(card); columnEl.appendChild(wrapper); } diff --git a/src/panels/lovelace/views/hui-panel-view.ts b/src/panels/lovelace/views/hui-panel-view.ts index 9da53437c8c2..99d5f05a911d 100644 --- a/src/panels/lovelace/views/hui-panel-view.ts +++ b/src/panels/lovelace/views/hui-panel-view.ts @@ -108,7 +108,7 @@ export class PanelView extends LitElement implements LovelaceViewElement { card.isPanel = true; if (this.isStrategy || !this.lovelace?.editMode) { - card.editMode = false; + card.preview = false; this._card = card; return; } @@ -118,7 +118,7 @@ export class PanelView extends LitElement implements LovelaceViewElement { wrapper.lovelace = this.lovelace; wrapper.path = [this.index!, 0]; wrapper.hidePosition = true; - card.editMode = true; + card.preview = true; wrapper.appendChild(card); this._card = wrapper; } diff --git a/src/panels/lovelace/views/hui-sidebar-view.ts b/src/panels/lovelace/views/hui-sidebar-view.ts index a33441232b24..6ef4b3a8005d 100644 --- a/src/panels/lovelace/views/hui-sidebar-view.ts +++ b/src/panels/lovelace/views/hui-sidebar-view.ts @@ -144,14 +144,14 @@ export class SideBarView extends LitElement implements LovelaceViewElement { const cardConfig = this._config?.cards?.[idx]; let element: HuiCard | HuiCardOptions; if (this.isStrategy || !this.lovelace?.editMode) { - card.editMode = false; + card.preview = false; element = card; } else { element = document.createElement("hui-card-options"); element.hass = this.hass; element.lovelace = this.lovelace; element.path = [this.index!, idx]; - card.editMode = true; + card.preview = true; const movePositionButton = document.createElement("ha-icon-button"); movePositionButton.slot = "buttons"; const moveIcon = document.createElement("ha-svg-icon"); diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index 7f614b2c1f47..9e515cd3ef90 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -76,7 +76,7 @@ export class HUIView extends ReactiveElement { private _createCardElement(cardConfig: LovelaceCardConfig) { const element = document.createElement("hui-card"); element.hass = this.hass; - element.editMode = this.lovelace.editMode; + element.preview = this.lovelace.editMode; element.config = cardConfig; element.addEventListener("card-updated", (ev: Event) => { ev.stopPropagation(); @@ -109,6 +109,7 @@ export class HUIView extends ReactiveElement { element.lovelace = this.lovelace; element.config = sectionConfig; element.viewIndex = this.index; + element.preview = this.lovelace.editMode; element.addEventListener( "ll-rebuild", (ev: Event) => { @@ -214,7 +215,7 @@ export class HUIView extends ReactiveElement { } }); this._cards.forEach((element) => { - element.editMode = this.lovelace.editMode; + element.preview = this.lovelace.editMode; }); } if (changedProperties.has("_cards")) {