mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-19 06:09:27 +00:00
Compare commits
44 Commits
20210208.0
...
lit-grid-l
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2fef57f0b2 | ||
![]() |
9b279632f8 | ||
![]() |
480e781364 | ||
![]() |
adc10ff0c6 | ||
![]() |
57a718e409 | ||
![]() |
23462bacfa | ||
![]() |
d99f8b0da8 | ||
![]() |
991d1f0997 | ||
![]() |
54e99357b5 | ||
![]() |
d263b5550a | ||
![]() |
a2b6ce3437 | ||
![]() |
9458f7ae62 | ||
![]() |
4d2ae36b0d | ||
![]() |
ebf0050e81 | ||
![]() |
3d0f492d62 | ||
![]() |
f5d3237b06 | ||
![]() |
07671ba1d4 | ||
![]() |
354d74ce1d | ||
![]() |
e892d14af0 | ||
![]() |
8d034fb7e7 | ||
![]() |
249456e6a0 | ||
![]() |
d3a6f31310 | ||
![]() |
4c31aead8b | ||
![]() |
3caf91c5d3 | ||
![]() |
9c3e754d53 | ||
![]() |
f48765c2b6 | ||
![]() |
236f26e652 | ||
![]() |
0fed96aba3 | ||
![]() |
70b77833f1 | ||
![]() |
307694a820 | ||
![]() |
402391c3e1 | ||
![]() |
81b5866e4d | ||
![]() |
09985bf5f7 | ||
![]() |
71d12a9e7a | ||
![]() |
5fd733b6c9 | ||
![]() |
bc3f827b4a | ||
![]() |
a807a182e4 | ||
![]() |
0a1fb843ca | ||
![]() |
fceb1568f5 | ||
![]() |
74e93bbefc | ||
![]() |
5c0f4b564b | ||
![]() |
76734f7a0b | ||
![]() |
440d10e4cd | ||
![]() |
a901072695 |
@@ -35,6 +35,9 @@ const createWebpackConfig = ({
|
||||
loader: "babel-loader",
|
||||
options: bundle.babelOptions({ latestBuild }),
|
||||
},
|
||||
resolve: {
|
||||
fullySpecified: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
|
@@ -105,6 +105,7 @@
|
||||
"leaflet": "^1.4.0",
|
||||
"leaflet-draw": "^1.0.4",
|
||||
"lit-element": "^2.4.0",
|
||||
"lit-grid-layout": "^1.1.11",
|
||||
"lit-html": "^1.3.0",
|
||||
"lit-virtualizer": "^0.4.2",
|
||||
"marked": "^1.1.1",
|
||||
@@ -121,6 +122,7 @@
|
||||
"superstruct": "^0.10.12",
|
||||
"tinykeys": "^1.1.1",
|
||||
"unfetch": "^4.1.0",
|
||||
"uuid": "^8.3.0",
|
||||
"vue": "^2.6.11",
|
||||
"vue2-daterange-picker": "^0.5.1",
|
||||
"web-animations-js": "^2.3.2",
|
||||
|
@@ -9,6 +9,7 @@ const ALWAYS_LOADED_LAYOUTS = new Set(["masonry"]);
|
||||
|
||||
const LAZY_LOAD_LAYOUTS = {
|
||||
panel: () => import("../views/hui-panel-view"),
|
||||
grid: () => import("../views/hui-grid-view"),
|
||||
};
|
||||
|
||||
export const createViewElement = (
|
||||
|
@@ -13,6 +13,7 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import {
|
||||
any,
|
||||
array,
|
||||
assert,
|
||||
boolean,
|
||||
@@ -62,6 +63,7 @@ const cardConfigStruct = object({
|
||||
theme: optional(string()),
|
||||
show_header_toggle: optional(boolean()),
|
||||
state_color: optional(boolean()),
|
||||
layout: optional(any()),
|
||||
entities: array(entitiesConfigStruct),
|
||||
header: optional(headerFooterConfigStructs),
|
||||
footer: optional(headerFooterConfigStructs),
|
||||
|
@@ -36,6 +36,7 @@ export interface LovelaceCard extends HTMLElement {
|
||||
hass?: HomeAssistant;
|
||||
isPanel?: boolean;
|
||||
editMode?: boolean;
|
||||
layout?: any;
|
||||
getCardSize(): number | Promise<number>;
|
||||
setConfig(config: LovelaceCardConfig): void;
|
||||
}
|
||||
|
3
src/panels/lovelace/views/grid/grid-view-editable.ts
Normal file
3
src/panels/lovelace/views/grid/grid-view-editable.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// hui-grid-view dependencies for when in edit mode.
|
||||
import "@material/mwc-fab";
|
||||
import "./hui-grid-card-options";
|
195
src/panels/lovelace/views/grid/hui-grid-card-options.ts
Normal file
195
src/panels/lovelace/views/grid/hui-grid-card-options.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
import "@material/mwc-icon-button";
|
||||
import {
|
||||
mdiContentDuplicate,
|
||||
mdiDelete,
|
||||
mdiDotsVertical,
|
||||
mdiPencil,
|
||||
} from "@mdi/js";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
LitElement,
|
||||
property,
|
||||
queryAssignedNodes,
|
||||
} from "lit-element";
|
||||
import { html, TemplateResult } from "lit-html";
|
||||
import "../../../../components/ha-svg-icon";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { computeCardSize } from "../../common/compute-card-size";
|
||||
import { showEditCardDialog } from "../../editor/card-editor/show-edit-card-dialog";
|
||||
import { confDeleteCard } from "../../editor/delete-card";
|
||||
import { Lovelace, LovelaceCard } from "../../types";
|
||||
|
||||
@customElement("hui-grid-card-options")
|
||||
export class HuiGridCardOptions extends LitElement {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public lovelace?: Lovelace;
|
||||
|
||||
@property({ type: Array }) public path?: [number, number];
|
||||
|
||||
@queryAssignedNodes() private _assignedNodes?: NodeListOf<LovelaceCard>;
|
||||
|
||||
public getCardSize() {
|
||||
return this._assignedNodes ? computeCardSize(this._assignedNodes[0]) : 1;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<slot></slot>
|
||||
<div class="parent-card-actions">
|
||||
<div class="overlay"></div>
|
||||
<div class="card-actions">
|
||||
<mwc-icon-button
|
||||
.title=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.edit"
|
||||
)}
|
||||
@click=${this._editCard}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiPencil}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<mwc-icon-button
|
||||
.title=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.duplicate"
|
||||
)}
|
||||
@click=${this._duplicateCard}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiContentDuplicate}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<mwc-icon-button
|
||||
.title=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.delete"
|
||||
)}
|
||||
@click=${this._deleteCard}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<div>
|
||||
<ha-button-menu corner="BOTTOM_START">
|
||||
<mwc-icon-button
|
||||
slot="trigger"
|
||||
aria-label=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.options"
|
||||
)}
|
||||
.title=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.options"
|
||||
)}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<mwc-list-item>
|
||||
${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.move"
|
||||
)}
|
||||
</mwc-list-item>
|
||||
</ha-button-menu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
slot {
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
transition: all 0.25s;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.parent-card-actions:hover .overlay {
|
||||
outline: 2px solid var(--primary-color);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
/* background-color: grey; */
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.parent-card-actions {
|
||||
transition: all 0.25s;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.parent-card-actions:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 24px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card-actions > * {
|
||||
margin: 0 4px;
|
||||
border-radius: 24px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
mwc-list-item {
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
mwc-list-item.delete-item {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
cursor: move;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
private _duplicateCard(): void {
|
||||
const path = this.path!;
|
||||
const cardConfig = this.lovelace!.config.views[path[0]].cards![path[1]];
|
||||
showEditCardDialog(this, {
|
||||
lovelaceConfig: this.lovelace!.config,
|
||||
cardConfig,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
path: [path[0]],
|
||||
});
|
||||
}
|
||||
|
||||
private _editCard(): void {
|
||||
showEditCardDialog(this, {
|
||||
lovelaceConfig: this.lovelace!.config,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
path: this.path!,
|
||||
});
|
||||
}
|
||||
|
||||
private _deleteCard(): void {
|
||||
confDeleteCard(this, this.hass!, this.lovelace!, this.path!);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-grid-card-options": HuiGridCardOptions;
|
||||
}
|
||||
}
|
363
src/panels/lovelace/views/hui-grid-view.ts
Normal file
363
src/panels/lovelace/views/hui-grid-view.ts
Normal file
@@ -0,0 +1,363 @@
|
||||
import "@material/mwc-fab/mwc-fab";
|
||||
import { mdiPlus, mdiResizeBottomRight } from "@mdi/js";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "lit-grid-layout";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import { nextRender } from "../../../common/util/render-status";
|
||||
import "../../../components/entity/ha-state-label-badge";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import type {
|
||||
LovelaceViewConfig,
|
||||
LovelaceViewElement,
|
||||
} from "../../../data/lovelace";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { computeCardSize } from "../common/compute-card-size";
|
||||
import { HuiCardOptions } from "../components/hui-card-options";
|
||||
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
||||
import { replaceView } from "../editor/config-util";
|
||||
import type { Lovelace, LovelaceBadge, LovelaceCard } from "../types";
|
||||
import { HuiGridCardOptions } from "./grid/hui-grid-card-options";
|
||||
|
||||
let editCodeLoaded = false;
|
||||
const mediaQueryColumns = [2, 6, 9, 12];
|
||||
|
||||
interface LovelaceGridCard extends LovelaceCard, HuiGridCardOptions {
|
||||
key: string;
|
||||
grid?: {
|
||||
key: string;
|
||||
width: number;
|
||||
height: number;
|
||||
posX: number;
|
||||
posY: number;
|
||||
};
|
||||
}
|
||||
|
||||
const RESIZE_HANDLE = document.createElement("div") as HTMLElement;
|
||||
RESIZE_HANDLE.style.cssText =
|
||||
"width: 100%; height: 100%; cursor: se-resize; fill: var(--primary-text-color)";
|
||||
RESIZE_HANDLE.innerHTML = `
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
focusable="false"
|
||||
>
|
||||
<g><path d=${mdiResizeBottomRight}></path></g>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
@customElement("hui-grid-view")
|
||||
export class GridView extends LitElement implements LovelaceViewElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public lovelace?: Lovelace;
|
||||
|
||||
@property({ type: Number }) public index?: number;
|
||||
|
||||
@property({ attribute: false }) public cards: Array<LovelaceGridCard> = [];
|
||||
|
||||
@property({ attribute: false }) public badges: LovelaceBadge[] = [];
|
||||
|
||||
@internalProperty() private _columns?: number;
|
||||
|
||||
@internalProperty() private _layout?: Array<{
|
||||
width: number;
|
||||
height: number;
|
||||
posX: number;
|
||||
posY: number;
|
||||
key: string;
|
||||
}>;
|
||||
|
||||
@internalProperty() public _cards: {
|
||||
[key: string]: LovelaceCard | HuiCardOptions;
|
||||
} = {};
|
||||
|
||||
private _config?: LovelaceViewConfig;
|
||||
|
||||
private _createColumnsIteration = 0;
|
||||
|
||||
private _mqls?: MediaQueryList[];
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
this.addEventListener("iron-resize", (ev: Event) => ev.stopPropagation());
|
||||
}
|
||||
|
||||
public setConfig(config: LovelaceViewConfig): void {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div
|
||||
id="badges"
|
||||
style=${this.badges.length > 0 ? "display: block" : "display: none"}
|
||||
>
|
||||
${this.badges.map((badge) => html`${badge}`)}
|
||||
</div>
|
||||
<lit-grid-layout
|
||||
rowHeight="15"
|
||||
.resizeHandle=${RESIZE_HANDLE}
|
||||
.itemRenderer=${this._itemRenderer}
|
||||
.layout=${this._layout}
|
||||
.columns=${this._columns}
|
||||
.dragDisabled=${!this.lovelace?.editMode}
|
||||
.resizeDisabled=${!this.lovelace?.editMode}
|
||||
@item-changed=${this._saveLayout}
|
||||
></lit-grid-layout>
|
||||
${this.lovelace?.editMode
|
||||
? html`
|
||||
<mwc-fab
|
||||
class=${classMap({
|
||||
rtl: computeRTL(this.hass!),
|
||||
})}
|
||||
.title=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.add"
|
||||
)}
|
||||
@click=${this._addCard}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</mwc-fab>
|
||||
`
|
||||
: ""}
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(): void {
|
||||
this._updateColumns = this._updateColumns.bind(this);
|
||||
this._mqls = [300, 600, 900, 1200].map((width) => {
|
||||
const mql = matchMedia(`(min-width: ${width}px)`);
|
||||
mql.addEventListener("change", this._updateColumns);
|
||||
return mql;
|
||||
});
|
||||
this._updateColumns();
|
||||
}
|
||||
|
||||
protected updated(changedProperties: PropertyValues): void {
|
||||
super.updated(changedProperties);
|
||||
|
||||
if (this.lovelace?.editMode && !editCodeLoaded) {
|
||||
editCodeLoaded = true;
|
||||
import(
|
||||
/* webpackChunkName: "grid-view-editable" */ "./grid/grid-view-editable"
|
||||
);
|
||||
}
|
||||
|
||||
if (changedProperties.has("hass")) {
|
||||
const oldHass = changedProperties.get("hass") as HomeAssistant;
|
||||
|
||||
if (
|
||||
(oldHass && this.hass!.dockedSidebar !== oldHass.dockedSidebar) ||
|
||||
(!oldHass && this.hass)
|
||||
) {
|
||||
this._updateColumns();
|
||||
}
|
||||
|
||||
if (changedProperties.size === 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const oldLovelace = changedProperties.get("lovelace") as
|
||||
| Lovelace
|
||||
| undefined;
|
||||
|
||||
if (
|
||||
(changedProperties.has("lovelace") &&
|
||||
(oldLovelace?.config !== this.lovelace?.config ||
|
||||
oldLovelace?.editMode !== this.lovelace?.editMode)) ||
|
||||
changedProperties.has("_columns")
|
||||
) {
|
||||
this._createLayout();
|
||||
this._createCards();
|
||||
}
|
||||
}
|
||||
|
||||
private async _saveLayout(ev: CustomEvent): Promise<void> {
|
||||
console.log("save");
|
||||
|
||||
const viewConf: LovelaceViewConfig = {
|
||||
...this._config,
|
||||
layout: ev.detail.layout,
|
||||
};
|
||||
await this.lovelace?.saveConfig(
|
||||
replaceView(this.lovelace!.config, this.index, viewConf)
|
||||
);
|
||||
}
|
||||
|
||||
private _itemRenderer = (key: string): TemplateResult => {
|
||||
if (!this._cards) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`${this._cards[key]}`;
|
||||
};
|
||||
|
||||
private _addCard(): void {
|
||||
showCreateCardDialog(this, {
|
||||
lovelaceConfig: this.lovelace!.config,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
path: [this.index!],
|
||||
});
|
||||
}
|
||||
|
||||
private async _createLayout() {
|
||||
this._createColumnsIteration++;
|
||||
const iteration = this._createColumnsIteration;
|
||||
|
||||
if (this._layout?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newLayout: Array<{
|
||||
width: number;
|
||||
height: number;
|
||||
posX: number;
|
||||
posY: number;
|
||||
key: string;
|
||||
minHeight: number;
|
||||
}> = [];
|
||||
|
||||
let tillNextRender: Promise<unknown> | undefined;
|
||||
let start: Date | undefined;
|
||||
|
||||
// Calculate the size of every card and determine in what column it should go
|
||||
for (const [index, card] of this.cards.entries()) {
|
||||
const cardConfig = this._config!.cards![index];
|
||||
if (tillNextRender === undefined) {
|
||||
// eslint-disable-next-line no-loop-func
|
||||
tillNextRender = nextRender().then(() => {
|
||||
tillNextRender = undefined;
|
||||
start = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
let waitProm: Promise<unknown> | undefined;
|
||||
|
||||
// We should work for max 16ms (60fps) before allowing a frame to render
|
||||
if (start === undefined) {
|
||||
// Save the time we start for this frame, no need to wait yet
|
||||
start = new Date();
|
||||
} else if (new Date().getTime() - start.getTime() > 16) {
|
||||
// We are working too long, we will prevent a render, wait to allow for a render
|
||||
waitProm = tillNextRender;
|
||||
}
|
||||
|
||||
const cardSizeProm = computeCardSize(card);
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const [cardSize] = await Promise.all([cardSizeProm, waitProm]);
|
||||
|
||||
if (iteration !== this._createColumnsIteration) {
|
||||
// An other create columns is started, abort this one
|
||||
return;
|
||||
}
|
||||
|
||||
const layout = {
|
||||
width: 3,
|
||||
height: cardSize,
|
||||
key: uuidv4(),
|
||||
minHeight: 4,
|
||||
...cardConfig.layout,
|
||||
};
|
||||
|
||||
newLayout.push(layout);
|
||||
}
|
||||
|
||||
this._layout = newLayout;
|
||||
this._createCards();
|
||||
}
|
||||
|
||||
private _createCards(): void {
|
||||
const elements = {};
|
||||
this.cards.forEach((card: LovelaceGridCard, index) => {
|
||||
const layout = this._layout![index];
|
||||
|
||||
card.editMode = this.lovelace?.editMode;
|
||||
let element = card;
|
||||
|
||||
if (this.lovelace?.editMode) {
|
||||
const wrapper = document.createElement(
|
||||
"hui-grid-card-options"
|
||||
) as LovelaceGridCard;
|
||||
wrapper.hass = this.hass;
|
||||
wrapper.lovelace = this.lovelace;
|
||||
wrapper.path = [this.index!, index];
|
||||
wrapper.appendChild(card);
|
||||
element = wrapper;
|
||||
}
|
||||
|
||||
elements[layout.key] = element;
|
||||
});
|
||||
|
||||
this._cards = elements;
|
||||
}
|
||||
|
||||
private _updateColumns() {
|
||||
if (!this._mqls) {
|
||||
return;
|
||||
}
|
||||
const matchColumns = this._mqls!.reduce(
|
||||
(cols, mql) => cols + Number(mql.matches),
|
||||
0
|
||||
);
|
||||
// Do -1 column if the menu is docked and open
|
||||
this._columns = Math.max(1, mediaQueryColumns[matchColumns - 1]);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
:host {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
padding: 4px 4px env(safe-area-inset-bottom);
|
||||
transform: translateZ(0);
|
||||
position: relative;
|
||||
color: var(--primary-text-color);
|
||||
background: var(--lovelace-background, var(--primary-background-color));
|
||||
}
|
||||
|
||||
lit-grid-layout {
|
||||
--placeholder-background-color: var(--accent-color);
|
||||
--resize-handle-size: 32px;
|
||||
}
|
||||
|
||||
#badges {
|
||||
margin: 8px 16px;
|
||||
font-size: 85%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
mwc-fab {
|
||||
position: sticky;
|
||||
float: right;
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
mwc-fab.rtl {
|
||||
float: left;
|
||||
right: auto;
|
||||
left: calc(16px + env(safe-area-inset-left));
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-grid-view": GridView;
|
||||
}
|
||||
}
|
@@ -114,7 +114,7 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
||||
if (this.lovelace?.editMode && !editCodeLoaded) {
|
||||
editCodeLoaded = true;
|
||||
import(
|
||||
/* webpackChunkName: "default-layout-editable" */ "./default-view-editable"
|
||||
/* webpackChunkName: "default-view-editable" */ "./default-view-editable"
|
||||
);
|
||||
}
|
||||
|
||||
|
13
yarn.lock
13
yarn.lock
@@ -8608,6 +8608,14 @@ lit-element@2.4.0, lit-element@^2.0.0, lit-element@^2.2.1, lit-element@^2.3.0, l
|
||||
dependencies:
|
||||
lit-html "^1.1.1"
|
||||
|
||||
lit-grid-layout@^1.1.11:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/lit-grid-layout/-/lit-grid-layout-1.1.11.tgz#0eb160ac61fcd25fd1929963776ff5d2df051320"
|
||||
integrity sha512-NSI7QuLllKvjrQEYdAFOv8Ucznu3TWDtxxroyDcv8Qv/zsjkuAJDK/bQjjuDSw/x7yy3NVn/c1I864fSUb47Rw==
|
||||
dependencies:
|
||||
lit-element "^2.4.0"
|
||||
lit-html "^1.3.0"
|
||||
|
||||
lit-html@1.3.0, lit-html@^1.0.0, lit-html@^1.1.1, lit-html@^1.1.2, lit-html@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-1.3.0.tgz#c80f3cc5793a6dea6c07172be90a70ab20e56034"
|
||||
@@ -12583,6 +12591,11 @@ uuid@^3.4.0:
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||
|
||||
uuid@^8.3.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea"
|
||||
integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==
|
||||
|
||||
v8-compile-cache@^2.0.3:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"
|
||||
|
Reference in New Issue
Block a user