Allow to resize card in the grid with more precision

This commit is contained in:
Paul Bottein 2024-10-11 12:03:38 +02:00
parent 07e5aa30c6
commit fde1bb7d6a
No known key found for this signature in database
6 changed files with 117 additions and 31 deletions

View File

@ -14,6 +14,12 @@ import {
} from "../panels/lovelace/common/compute-card-grid-size";
import { HomeAssistant } from "../types";
declare global {
interface HASSDomEvents {
"grid-reset": undefined;
}
}
@customElement("ha-grid-size-picker")
export class HaGridSizeEditor extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@ -184,12 +190,7 @@ export class HaGridSizeEditor extends LitElement {
private _reset(ev) {
ev.stopPropagation();
fireEvent(this, "value-changed", {
value: {
rows: undefined,
columns: undefined,
},
});
fireEvent(this, "grid-reset");
}
private _sliderMoved(ev) {

View File

@ -11,6 +11,8 @@ export type CardGridSize = {
columns: number | "full";
};
export const GRID_COLUMN_MULTIPLIER = 3;
export const computeCardGridSize = (
options: LovelaceLayoutOptions
): CardGridSize => {
@ -20,14 +22,16 @@ export const computeCardGridSize = (
const maxRows = options.grid_max_rows;
const minColumns = options.grid_min_columns;
const maxColumns = options.grid_max_columns;
const precisionMode = options.grid_precision_mode;
const clampedRows =
typeof rows === "string" ? rows : conditionalClamp(rows, minRows, maxRows);
const clampedColumns =
typeof columns === "string"
typeof columns === "string" || precisionMode
? columns
: conditionalClamp(columns, minColumns, maxColumns);
: conditionalClamp(columns, minColumns, maxColumns) *
GRID_COLUMN_MULTIPLIER;
return {
rows: clampedRows,

View File

@ -26,6 +26,7 @@ import { HuiCard } from "../../cards/hui-card";
import {
CardGridSize,
computeCardGridSize,
GRID_COLUMN_MULTIPLIER,
} from "../../common/compute-card-grid-size";
import { LovelaceLayoutOptions } from "../../types";
@ -57,11 +58,24 @@ export class HuiCardLayoutEditor extends LitElement {
})
);
private _computeCardGridSize = memoizeOne(computeCardGridSize);
private _computeCardGridSize = memoizeOne(
(options: LovelaceLayoutOptions) => {
const size = computeCardGridSize(options);
if (!options.grid_precision_mode) {
size.columns =
typeof size.columns === "number"
? Math.round(size.columns / GRID_COLUMN_MULTIPLIER)
: size.columns;
}
return size;
}
);
private _isDefault = memoizeOne(
(options?: LovelaceLayoutOptions) =>
options?.grid_columns === undefined && options?.grid_rows === undefined
options?.grid_columns === undefined &&
options?.grid_rows === undefined &&
options?.grid_precision_mode === undefined
);
render() {
@ -74,6 +88,8 @@ export class HuiCardLayoutEditor extends LitElement {
const totalColumns = (this.sectionConfig.column_span ?? 1) * 4;
const precisionMode = options.grid_precision_mode ?? false;
return html`
<div class="header">
<p class="intro">
@ -135,20 +151,39 @@ export class HuiCardLayoutEditor extends LitElement {
></ha-yaml-editor>
`
: html`
<ha-grid-size-picker
style=${styleMap({
"max-width": `${totalColumns * 45 + 50}px`,
})}
.columns=${totalColumns}
.hass=${this.hass}
.value=${value}
.isDefault=${this._isDefault(this.config.layout_options)}
@value-changed=${this._gridSizeChanged}
.rowMin=${options.grid_min_rows}
.rowMax=${options.grid_max_rows}
.columnMin=${options.grid_min_columns}
.columnMax=${options.grid_max_columns}
></ha-grid-size-picker>
${precisionMode
? html`
<ha-grid-size-picker
style=${styleMap({
"max-width": `${totalColumns * 50 + 50}px`,
})}
.columns=${totalColumns * GRID_COLUMN_MULTIPLIER}
.hass=${this.hass}
.value=${value}
.isDefault=${this._isDefault(this.config.layout_options)}
@grid-reset=${this._reset}
@value-changed=${this._gridSizeChanged}
.rowMin=${options.grid_min_rows}
.rowMax=${options.grid_max_rows}
></ha-grid-size-picker>
`
: html`
<ha-grid-size-picker
style=${styleMap({
"max-width": `${totalColumns * 50 + 50}px`,
})}
.columns=${totalColumns}
.hass=${this.hass}
.value=${value}
.isDefault=${this._isDefault(this.config.layout_options)}
@grid-reset=${this._reset}
@value-changed=${this._gridSizeChanged}
.rowMin=${options.grid_min_rows}
.rowMax=${options.grid_max_rows}
.columnMin=${options.grid_min_columns}
.columnMax=${options.grid_max_columns}
></ha-grid-size-picker>
`}
<ha-settings-row>
<span slot="heading" data-for="full-width">
${this.hass.localize(
@ -167,6 +202,24 @@ export class HuiCardLayoutEditor extends LitElement {
>
</ha-switch>
</ha-settings-row>
<ha-settings-row>
<span slot="heading" data-for="full-width">
${this.hass.localize(
"ui.panel.lovelace.editor.edit_card.layout.precision_mode"
)}
</span>
<span slot="description" data-for="full-width">
${this.hass.localize(
"ui.panel.lovelace.editor.edit_card.layout.precision_mode_helper"
)}
</span>
<ha-switch
@change=${this._precisionModeChanged}
.checked=${precisionMode}
name="full-precision_mode"
>
</ha-switch>
</ha-settings-row>
`}
`;
}
@ -211,9 +264,6 @@ export class HuiCardLayoutEditor extends LitElement {
case 1:
this._yamlMode = true;
break;
case 2:
this._reset();
break;
}
}
@ -275,6 +325,34 @@ export class HuiCardLayoutEditor extends LitElement {
fireEvent(this, "value-changed", { value: newConfig });
}
private _precisionModeChanged(ev): void {
ev.stopPropagation();
const value = ev.target.checked;
const preciseMode = value;
const gridColumns = this.config.layout_options?.grid_columns;
const newGridColumns =
typeof gridColumns === "number"
? preciseMode
? gridColumns * GRID_COLUMN_MULTIPLIER
: Math.round(gridColumns / GRID_COLUMN_MULTIPLIER)
: gridColumns;
const newConfig: LovelaceCardConfig = {
...this.config,
layout_options: {
...this.config.layout_options,
grid_columns: newGridColumns,
grid_precision_mode: preciseMode || undefined,
},
};
if (Object.keys(newConfig.layout_options!).length === 0) {
delete newConfig.layout_options;
}
fireEvent(this, "value-changed", { value: newConfig });
}
static styles = [
haStyle,
css`

View File

@ -165,7 +165,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
haStyle,
css`
:host {
--base-column-count: 4;
--base-column-count: 12;
--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);
@ -230,8 +230,8 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
.add {
outline: none;
grid-row: span var(--row-size, 1);
grid-column: span var(--column-size, 2);
grid-row: span 1;
grid-column: span 6;
background: none;
cursor: pointer;
border-radius: var(--ha-card-border-radius, 12px);

View File

@ -49,6 +49,7 @@ export type LovelaceLayoutOptions = {
grid_min_columns?: number;
grid_min_rows?: number;
grid_max_rows?: number;
grid_precision_mode?: boolean;
};
export interface LovelaceCard extends HTMLElement {

View File

@ -5645,7 +5645,9 @@
},
"layout": {
"full_width": "Full width card",
"full_width_helper": "Take up the full width of the section whatever its size"
"full_width_helper": "Take up the full width of the section whatever its size",
"precision_mode": "Precision mode",
"precision_mode_helper": "Change the card width with precision without limits"
}
},
"edit_badge": {