mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-05 09:00:11 +00:00
Compare commits
1 Commits
20251103.0
...
grid_secti
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b065799bf |
@@ -17,6 +17,10 @@ export interface LovelaceSectionConfig extends LovelaceBaseSectionConfig {
|
||||
cards?: LovelaceCardConfig[];
|
||||
}
|
||||
|
||||
export interface LovelaceGridSectionConfig extends LovelaceSectionConfig {
|
||||
grid_base?: number;
|
||||
}
|
||||
|
||||
export interface LovelaceStrategySectionConfig
|
||||
extends LovelaceBaseSectionConfig {
|
||||
strategy: LovelaceStrategyConfig;
|
||||
|
||||
@@ -3,12 +3,15 @@ import "@material/mwc-tab/mwc-tab";
|
||||
import { CSSResultGroup, TemplateResult, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
||||
import {
|
||||
LovelaceGridSectionConfig,
|
||||
LovelaceSectionConfig,
|
||||
} from "../../../../data/lovelace/config/section";
|
||||
import { getCardElementClass } from "../../create-element/create-card-element";
|
||||
import type { LovelaceCardEditor, LovelaceConfigForm } from "../../types";
|
||||
import { HuiTypedElementEditor } from "../hui-typed-element-editor";
|
||||
import "./hui-card-layout-editor";
|
||||
import "./hui-card-visibility-editor";
|
||||
import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
|
||||
|
||||
const tabs = ["config", "visibility", "layout"] as const;
|
||||
|
||||
@@ -59,7 +62,7 @@ export class HuiCardElementEditor extends HuiTypedElementEditor<LovelaceCardConf
|
||||
protected renderConfigElement(): TemplateResult {
|
||||
const displayedTabs: string[] = ["config"];
|
||||
if (this.showVisibilityTab) displayedTabs.push("visibility");
|
||||
if (this._showLayoutTab) displayedTabs.push("layout");
|
||||
if (this.sectionConfig?.type === "grid") displayedTabs.push("layout");
|
||||
|
||||
if (displayedTabs.length === 1) return super.renderConfigElement();
|
||||
|
||||
@@ -83,8 +86,8 @@ export class HuiCardElementEditor extends HuiTypedElementEditor<LovelaceCardConf
|
||||
<hui-card-layout-editor
|
||||
.hass=${this.hass}
|
||||
.config=${this.value}
|
||||
.sectionConfig=${this.sectionConfig!}
|
||||
@value-changed=${this._configChanged}
|
||||
.sectionConfig=${this.sectionConfig as LovelaceGridSectionConfig}
|
||||
>
|
||||
</hui-card-layout-editor>
|
||||
`;
|
||||
|
||||
@@ -19,7 +19,10 @@ import "../../../../components/ha-switch";
|
||||
import "../../../../components/ha-yaml-editor";
|
||||
import type { HaYamlEditor } from "../../../../components/ha-yaml-editor";
|
||||
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
||||
import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
|
||||
import {
|
||||
LovelaceGridSectionConfig,
|
||||
LovelaceSectionConfig,
|
||||
} from "../../../../data/lovelace/config/section";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { HuiCard } from "../../cards/hui-card";
|
||||
@@ -27,6 +30,7 @@ import {
|
||||
CardGridSize,
|
||||
computeCardGridSize,
|
||||
} from "../../common/compute-card-grid-size";
|
||||
import { DEFAULT_GRID_BASE } from "../../sections/hui-grid-section";
|
||||
import { LovelaceLayoutOptions } from "../../types";
|
||||
|
||||
@customElement("hui-card-layout-editor")
|
||||
@@ -72,7 +76,10 @@ export class HuiCardLayoutEditor extends LitElement {
|
||||
|
||||
const value = this._computeCardGridSize(options);
|
||||
|
||||
const totalColumns = (this.sectionConfig.column_span ?? 1) * 4;
|
||||
const totalColumns =
|
||||
(this.sectionConfig.column_span ?? 1) *
|
||||
((this.sectionConfig as LovelaceGridSectionConfig).grid_base ||
|
||||
DEFAULT_GRID_BASE);
|
||||
|
||||
return html`
|
||||
<div class="header">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LitElement, html } from "lit";
|
||||
import { html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
@@ -6,12 +6,21 @@ import {
|
||||
HaFormSchema,
|
||||
SchemaUnion,
|
||||
} from "../../../../components/ha-form/types";
|
||||
import { LovelaceSectionRawConfig } from "../../../../data/lovelace/config/section";
|
||||
import {
|
||||
isStrategySection,
|
||||
LovelaceGridSectionConfig,
|
||||
LovelaceSectionRawConfig,
|
||||
} from "../../../../data/lovelace/config/section";
|
||||
import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { LocalizeFunc } from "../../../../common/translations/localize";
|
||||
import { DEFAULT_GRID_BASE } from "../../sections/hui-grid-section";
|
||||
|
||||
type GridDensity = "default" | "dense" | "custom";
|
||||
|
||||
type SettingsData = {
|
||||
column_span?: number;
|
||||
grid_density?: GridDensity;
|
||||
};
|
||||
|
||||
@customElement("hui-section-settings-editor")
|
||||
@@ -23,27 +32,89 @@ export class HuiDialogEditSection extends LitElement {
|
||||
@property({ attribute: false }) public viewConfig!: LovelaceViewConfig;
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(maxColumns: number) =>
|
||||
(
|
||||
maxColumns: number,
|
||||
localize: LocalizeFunc,
|
||||
type?: string | undefined,
|
||||
columnDensity?: GridDensity,
|
||||
columnBase?: number
|
||||
) =>
|
||||
[
|
||||
{
|
||||
name: "column_span",
|
||||
selector: {
|
||||
number: {
|
||||
min: 1,
|
||||
max: maxColumns,
|
||||
slider_ticks: true,
|
||||
},
|
||||
},
|
||||
name: "title",
|
||||
selector: { text: {} },
|
||||
},
|
||||
...(type === "grid"
|
||||
? ([
|
||||
{
|
||||
name: "grid_density",
|
||||
default: "default",
|
||||
selector: {
|
||||
select: {
|
||||
mode: "list",
|
||||
options: [
|
||||
{
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.edit_section.settings.grid_density_options.default`,
|
||||
{ count: 4 }
|
||||
),
|
||||
value: "default",
|
||||
},
|
||||
{
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.edit_section.settings.grid_density_options.dense`,
|
||||
{ count: 6 }
|
||||
),
|
||||
value: "dense",
|
||||
},
|
||||
...(columnDensity === "custom" && columnBase
|
||||
? [
|
||||
{
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.edit_section.settings.grid_density_options.custom`,
|
||||
{ count: columnBase }
|
||||
),
|
||||
value: "custom",
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
] as const satisfies readonly HaFormSchema[])
|
||||
: []),
|
||||
] as const satisfies HaFormSchema[]
|
||||
);
|
||||
|
||||
private _isGridSectionConfig(
|
||||
config: LovelaceSectionRawConfig
|
||||
): config is LovelaceGridSectionConfig {
|
||||
return !isStrategySection(config) && config.type === "grid";
|
||||
}
|
||||
|
||||
render() {
|
||||
const gridBase = this._isGridSectionConfig(this.config)
|
||||
? this.config.grid_base || DEFAULT_GRID_BASE
|
||||
: undefined;
|
||||
|
||||
const columnDensity =
|
||||
gridBase === 6 ? "dense" : gridBase === 4 ? "default" : "custom";
|
||||
|
||||
const data: SettingsData = {
|
||||
column_span: this.config.column_span || 1,
|
||||
grid_density: columnDensity,
|
||||
};
|
||||
|
||||
const schema = this._schema(this.viewConfig.max_columns || 4);
|
||||
const type = "type" in this.config ? this.config.type : undefined;
|
||||
|
||||
const schema = this._schema(
|
||||
this.viewConfig.max_columns || 4,
|
||||
this.hass.localize,
|
||||
type,
|
||||
columnDensity,
|
||||
gridBase
|
||||
);
|
||||
|
||||
return html`
|
||||
<ha-form
|
||||
@@ -75,11 +146,26 @@ export class HuiDialogEditSection extends LitElement {
|
||||
ev.stopPropagation();
|
||||
const newData = ev.detail.value as SettingsData;
|
||||
|
||||
const { column_span, grid_density } = newData;
|
||||
|
||||
const newConfig: LovelaceSectionRawConfig = {
|
||||
...this.config,
|
||||
column_span: newData.column_span,
|
||||
column_span: column_span,
|
||||
};
|
||||
|
||||
if (this._isGridSectionConfig(newConfig)) {
|
||||
const gridBase =
|
||||
grid_density === "default"
|
||||
? 4
|
||||
: grid_density === "dense"
|
||||
? 6
|
||||
: undefined;
|
||||
|
||||
if (gridBase) {
|
||||
(newConfig as LovelaceGridSectionConfig).grid_base = gridBase;
|
||||
}
|
||||
}
|
||||
|
||||
fireEvent(this, "value-changed", { value: newConfig });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import type { HaSortableOptions } from "../../../components/ha-sortable";
|
||||
import { LovelaceSectionElement } from "../../../data/lovelace";
|
||||
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||
import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
|
||||
import type { LovelaceGridSectionConfig } from "../../../data/lovelace/config/section";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { HuiCard } from "../cards/hui-card";
|
||||
@@ -24,6 +24,8 @@ const CARD_SORTABLE_OPTIONS: HaSortableOptions = {
|
||||
invertedSwapThreshold: 0.7,
|
||||
} as HaSortableOptions;
|
||||
|
||||
export const DEFAULT_GRID_BASE = 4;
|
||||
|
||||
export class GridSection extends LitElement implements LovelaceSectionElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@@ -37,11 +39,11 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
||||
|
||||
@property({ attribute: false }) public cards: HuiCard[] = [];
|
||||
|
||||
@state() _config?: LovelaceSectionConfig;
|
||||
@state() _config?: LovelaceGridSectionConfig;
|
||||
|
||||
@state() _dragging = false;
|
||||
|
||||
public setConfig(config: LovelaceSectionConfig): void {
|
||||
public setConfig(config: LovelaceGridSectionConfig): void {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
@@ -64,6 +66,8 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
||||
|
||||
const editMode = Boolean(this.lovelace?.editMode && !this.isStrategy);
|
||||
|
||||
const columnCount = this._config.grid_base ?? DEFAULT_GRID_BASE;
|
||||
|
||||
return html`
|
||||
<ha-sortable
|
||||
.disabled=${!editMode}
|
||||
@@ -77,7 +81,10 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
||||
.options=${CARD_SORTABLE_OPTIONS}
|
||||
invert-swap
|
||||
>
|
||||
<div class="container ${classMap({ "edit-mode": editMode })}">
|
||||
<div
|
||||
class="container ${classMap({ "edit-mode": editMode })}"
|
||||
style=${styleMap({ "--column-count": columnCount })}
|
||||
>
|
||||
${repeat(
|
||||
cardsConfig,
|
||||
(cardConfig) => this._getKey(cardConfig),
|
||||
@@ -165,7 +172,6 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
||||
haStyle,
|
||||
css`
|
||||
:host {
|
||||
--base-column-count: 4;
|
||||
--row-gap: var(--ha-section-grid-row-gap, 8px);
|
||||
--column-gap: var(--ha-section-grid-column-gap, 8px);
|
||||
--row-height: var(--ha-section-grid-row-height, 56px);
|
||||
@@ -175,7 +181,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
||||
}
|
||||
.container {
|
||||
--grid-column-count: calc(
|
||||
var(--base-column-count) * var(--column-span, 1)
|
||||
var(--column-count, 4) * var(--column-span, 1)
|
||||
);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(
|
||||
|
||||
@@ -5714,7 +5714,13 @@
|
||||
"title": "Title",
|
||||
"title_helper": "The title will appear at the top of section. Leave empty to hide the title.",
|
||||
"column_span": "Width",
|
||||
"column_span_helper": "Larger sections will be made smaller to fit the display. (e.g. on mobile devices)"
|
||||
"column_span_helper": "Larger sections will be made smaller to fit the display. (e.g. on mobile devices)",
|
||||
"grid_density": "Grid density",
|
||||
"grid_density_options": {
|
||||
"default": "Default ({count} columns)",
|
||||
"dense": "Dense ({count} columns)",
|
||||
"custom": "Custom ({count} {count, plural,\n one {column}\n other {columns}\n})"
|
||||
}
|
||||
},
|
||||
"visibility": {
|
||||
"explanation": "The section will be shown when ALL conditions below are fulfilled. If no conditions are set, the section will always be shown."
|
||||
|
||||
Reference in New Issue
Block a user