Compare commits

...

8 Commits

Author SHA1 Message Date
Paul Bottein
1d007a5aaf After rebase clean 2024-09-05 15:52:59 +02:00
Paul Bottein
94c1af7729 Use breakpoints to define number of column in dashboard view 2024-09-05 15:49:13 +02:00
Paul Bottein
d7aaf9bc41 Use old logic to calculate the number of columns 2024-09-05 15:46:28 +02:00
Paul Bottein
c0aed4325d Make column breakpoints optional 2024-09-05 15:44:49 +02:00
Paul Bottein
79a56fabdf Remove column min width 2024-09-05 15:44:21 +02:00
Paul Bottein
14c2b60538 Rename variables 2024-09-05 11:36:18 +02:00
Paul Bottein
79f3dfdfce Use listeners 2024-09-05 11:33:54 +02:00
Paul Bottein
3de4dffa02 WIP: Allow to resize section 2024-09-05 11:30:07 +02:00
2 changed files with 65 additions and 3 deletions

View File

@@ -25,6 +25,8 @@ export interface LovelaceBaseViewConfig {
// Only used for section view, it should move to a section view config type when the views will have dedicated editor.
max_columns?: number;
dense_section_placement?: boolean;
column_breakpoints?: Record<string, number>;
experimental_breakpoints?: boolean;
}
export interface LovelaceViewConfig extends LovelaceBaseViewConfig {

View File

@@ -12,6 +12,7 @@ import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { repeat } from "lit/directives/repeat";
import { styleMap } from "lit/directives/style-map";
import { listenMediaQuery } from "../../../common/dom/media_query";
import "../../../components/ha-icon-button";
import "../../../components/ha-sortable";
import "../../../components/ha-svg-icon";
@@ -28,8 +29,29 @@ import { showEditSectionDialog } from "../editor/section-editor/show-edit-sectio
import { HuiSection } from "../sections/hui-section";
import type { Lovelace } from "../types";
type Breakpoints = Record<string, number>;
export const DEFAULT_MAX_COLUMNS = 4;
export const DEFAULT_BREAKPOINTS: Breakpoints = {
"0": 1,
"768": 2,
"1280": 3,
"1600": 4,
"1920": 5,
"2560": 6,
};
const buildMediaQueries = (breakpoints: Breakpoints) =>
Object.keys(breakpoints).map((breakpoint, index, array) => {
const nextBreakpoint = array[index + 1] as string | undefined;
let mediaQuery = `(min-width: ${breakpoint}px)`;
if (nextBreakpoint) {
mediaQuery += ` and (max-width: ${parseInt(nextBreakpoint) - 1}px)`;
}
return mediaQuery;
});
const parsePx = (value: string) => parseInt(value.replace("px", ""));
@customElement("hui-sections-view")
@@ -52,8 +74,15 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
@state() _dragging = false;
private _listeners: Array<() => void> = [];
@state() private _breakpointsColumns: number = 1;
private _columnsController = new ResizeController(this, {
callback: (entries) => {
// Don't do anything if we are using breakpoints
if (this._config?.experimental_breakpoints) return 1;
const totalWidth = entries[0]?.contentRect.width;
const style = getComputedStyle(this);
@@ -76,8 +105,13 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
},
});
private get _sizeColumns() {
return this._columnsController.value ?? 1;
}
public setConfig(config: LovelaceViewConfig): void {
this._config = config;
this._attachMediaQueriesListeners();
}
private _sectionConfigKeys = new WeakMap<HuiSection, string>();
@@ -100,12 +134,35 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
this._computeSectionsCount();
};
private _attachMediaQueriesListeners() {
this._detachMediaQueriesListeners();
if (!this._config?.experimental_breakpoints) return;
const breakpoints = this._config?.column_breakpoints ?? DEFAULT_BREAKPOINTS;
const maxColumns = this._config?.max_columns ?? DEFAULT_MAX_COLUMNS;
const mediaQueries = buildMediaQueries(breakpoints);
this._listeners = mediaQueries.map((mediaQuery, index) =>
listenMediaQuery(mediaQuery, (matches) => {
if (matches) {
const columns = Object.values(breakpoints)[index];
this._breakpointsColumns = Math.min(maxColumns, columns);
}
})
);
}
private _detachMediaQueriesListeners() {
while (this._listeners.length) {
this._listeners.pop()!();
}
}
connectedCallback(): void {
super.connectedCallback();
this.addEventListener(
"section-visibility-changed",
this._sectionVisibilityChanged
);
this._attachMediaQueriesListeners();
}
disconnectedCallback(): void {
@@ -114,6 +171,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
"section-visibility-changed",
this._sectionVisibilityChanged
);
this._detachMediaQueriesListeners();
}
willUpdate(changedProperties: PropertyValues<typeof this>): void {
@@ -130,7 +188,9 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
this._sectionColumnCount + (this.lovelace?.editMode ? 1 : 0);
const editMode = this.lovelace.editMode;
const maxColumnCount = this._columnsController.value ?? 1;
const maxColumnCount = this._config?.experimental_breakpoints
? this._breakpointsColumns
: this._sizeColumns;
return html`
<hui-view-badges
@@ -321,9 +381,9 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
:host {
--row-height: var(--ha-view-sections-row-height, 56px);
--row-gap: var(--ha-view-sections-row-gap, 8px);
--column-gap: var(--ha-view-sections-column-gap, 32px);
--column-max-width: var(--ha-view-sections-column-max-width, 500px);
--column-gap: var(--ha-view-sections-column-gap, 24px);
--column-min-width: var(--ha-view-sections-column-min-width, 320px);
--column-max-width: var(--ha-view-sections-column-max-width, 500px);
display: block;
}