POC
This commit is contained in:
parent
6234f7b7d2
commit
539472bd96
|
@ -109,6 +109,7 @@
|
||||||
"element-internals-polyfill": "1.3.10",
|
"element-internals-polyfill": "1.3.10",
|
||||||
"fuse.js": "7.0.0",
|
"fuse.js": "7.0.0",
|
||||||
"google-timezones-json": "1.2.0",
|
"google-timezones-json": "1.2.0",
|
||||||
|
"gridstack": "10.0.1",
|
||||||
"hls.js": "1.5.1",
|
"hls.js": "1.5.1",
|
||||||
"home-assistant-js-websocket": "9.1.0",
|
"home-assistant-js-websocket": "9.1.0",
|
||||||
"idb-keyval": "6.2.1",
|
"idb-keyval": "6.2.1",
|
||||||
|
|
|
@ -25,7 +25,6 @@ import "../ha-dialog";
|
||||||
import "../ha-dialog-header";
|
import "../ha-dialog-header";
|
||||||
import "../ha-svg-icon";
|
import "../ha-svg-icon";
|
||||||
import "../ha-tip";
|
import "../ha-tip";
|
||||||
import "./ha-media-player-browse";
|
|
||||||
import "./ha-media-upload-button";
|
import "./ha-media-upload-button";
|
||||||
import type { MediaManageDialogParams } from "./show-media-manage-dialog";
|
import type { MediaManageDialogParams } from "./show-media-manage-dialog";
|
||||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||||
|
|
|
@ -73,6 +73,7 @@ class HuiGridCard extends HuiStackCard<GridCardConfig> {
|
||||||
super.sharedStyles,
|
super.sharedStyles,
|
||||||
css`
|
css`
|
||||||
#root {
|
#root {
|
||||||
|
height: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(
|
grid-template-columns: repeat(
|
||||||
var(--grid-card-column-count, ${DEFAULT_COLUMNS}),
|
var(--grid-card-column-count, ${DEFAULT_COLUMNS}),
|
||||||
|
|
|
@ -453,12 +453,14 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
|
||||||
.secondary=${localizedState}
|
.secondary=${localizedState}
|
||||||
></ha-tile-info>
|
></ha-tile-info>
|
||||||
</div>
|
</div>
|
||||||
<hui-card-features
|
${this._config.features?.length
|
||||||
.hass=${this.hass}
|
? html`<hui-card-features
|
||||||
.stateObj=${stateObj}
|
.hass=${this.hass}
|
||||||
.color=${this._config.color}
|
.stateObj=${stateObj}
|
||||||
.features=${this._config.features}
|
.color=${this._config.color}
|
||||||
></hui-card-features>
|
.features=${this._config.features}
|
||||||
|
></hui-card-features>`
|
||||||
|
: nothing}
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -481,6 +483,9 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
|
||||||
transition:
|
transition:
|
||||||
box-shadow 180ms ease-in-out,
|
box-shadow 180ms ease-in-out,
|
||||||
border-color 180ms ease-in-out;
|
border-color 180ms ease-in-out;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
ha-card.active {
|
ha-card.active {
|
||||||
--tile-color: var(--state-icon-color);
|
--tile-color: var(--state-icon-color);
|
||||||
|
|
|
@ -9,6 +9,7 @@ const ALWAYS_LOADED_LAYOUTS = new Set(["masonry"]);
|
||||||
const LAZY_LOAD_LAYOUTS = {
|
const LAZY_LOAD_LAYOUTS = {
|
||||||
panel: () => import("../views/hui-panel-view"),
|
panel: () => import("../views/hui-panel-view"),
|
||||||
sidebar: () => import("../views/hui-sidebar-view"),
|
sidebar: () => import("../views/hui-sidebar-view"),
|
||||||
|
manual: () => import("../views/hui-manual-view"),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createViewElement = (
|
export const createViewElement = (
|
||||||
|
|
|
@ -212,6 +212,7 @@ export class HuiCreateDialogCard
|
||||||
|
|
||||||
showEditCardDialog(this, {
|
showEditCardDialog(this, {
|
||||||
lovelaceConfig: this._params!.lovelaceConfig,
|
lovelaceConfig: this._params!.lovelaceConfig,
|
||||||
|
preSaveConfig: this._params!.preSaveConfig,
|
||||||
saveConfig: this._params!.saveConfig,
|
saveConfig: this._params!.saveConfig,
|
||||||
path: this._params!.path,
|
path: this._params!.path,
|
||||||
cardConfig: config,
|
cardConfig: config,
|
||||||
|
|
|
@ -367,17 +367,20 @@ export class HuiDialogEditCard
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._saving = true;
|
this._saving = true;
|
||||||
|
const cardConfig = this._params?.preSaveConfig
|
||||||
|
? await this._params.preSaveConfig(this._cardConfig!)
|
||||||
|
: this._cardConfig!;
|
||||||
await this._params!.saveConfig(
|
await this._params!.saveConfig(
|
||||||
this._params!.path.length === 1
|
this._params!.path.length === 1
|
||||||
? addCard(
|
? addCard(
|
||||||
this._params!.lovelaceConfig,
|
this._params!.lovelaceConfig,
|
||||||
this._params!.path as [number],
|
this._params!.path as [number],
|
||||||
this._cardConfig!
|
cardConfig
|
||||||
)
|
)
|
||||||
: replaceCard(
|
: replaceCard(
|
||||||
this._params!.lovelaceConfig,
|
this._params!.lovelaceConfig,
|
||||||
this._params!.path as [number, number],
|
this._params!.path as [number, number],
|
||||||
this._cardConfig!
|
cardConfig
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
this._saving = false;
|
this._saving = false;
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
||||||
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
||||||
|
|
||||||
export interface CreateCardDialogParams {
|
export interface CreateCardDialogParams {
|
||||||
lovelaceConfig: LovelaceConfig;
|
lovelaceConfig: LovelaceConfig;
|
||||||
|
preSaveConfig?: (
|
||||||
|
config: LovelaceCardConfig
|
||||||
|
) => LovelaceCardConfig | Promise<LovelaceCardConfig>;
|
||||||
saveConfig: (config: LovelaceConfig) => void;
|
saveConfig: (config: LovelaceConfig) => void;
|
||||||
path: [number] | [number, number];
|
path: [number] | [number, number];
|
||||||
entities?: string[]; // We can pass entity id's that will be added to the config when a card is picked
|
entities?: string[]; // We can pass entity id's that will be added to the config when a card is picked
|
||||||
|
|
|
@ -4,6 +4,9 @@ import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
||||||
|
|
||||||
export interface EditCardDialogParams {
|
export interface EditCardDialogParams {
|
||||||
lovelaceConfig: LovelaceConfig;
|
lovelaceConfig: LovelaceConfig;
|
||||||
|
preSaveConfig?: (
|
||||||
|
config: LovelaceCardConfig
|
||||||
|
) => LovelaceCardConfig | Promise<LovelaceCardConfig>;
|
||||||
saveConfig: (config: LovelaceConfig) => void;
|
saveConfig: (config: LovelaceConfig) => void;
|
||||||
path: [number] | [number, number];
|
path: [number] | [number, number];
|
||||||
cardConfig?: LovelaceCardConfig;
|
cardConfig?: LovelaceCardConfig;
|
||||||
|
|
|
@ -9,6 +9,7 @@ import type { SchemaUnion } from "../../../../components/ha-form/types";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import {
|
import {
|
||||||
DEFAULT_VIEW_LAYOUT,
|
DEFAULT_VIEW_LAYOUT,
|
||||||
|
MANUAL_VIEW_LAYOUT,
|
||||||
PANEL_VIEW_LAYOUT,
|
PANEL_VIEW_LAYOUT,
|
||||||
SIDEBAR_VIEW_LAYOUT,
|
SIDEBAR_VIEW_LAYOUT,
|
||||||
} from "../../views/const";
|
} from "../../views/const";
|
||||||
|
@ -53,6 +54,7 @@ export class HuiViewEditor extends LitElement {
|
||||||
DEFAULT_VIEW_LAYOUT,
|
DEFAULT_VIEW_LAYOUT,
|
||||||
SIDEBAR_VIEW_LAYOUT,
|
SIDEBAR_VIEW_LAYOUT,
|
||||||
PANEL_VIEW_LAYOUT,
|
PANEL_VIEW_LAYOUT,
|
||||||
|
MANUAL_VIEW_LAYOUT,
|
||||||
] as const
|
] as const
|
||||||
).map((type) => ({
|
).map((type) => ({
|
||||||
value: type,
|
value: type,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export const DEFAULT_VIEW_LAYOUT = "masonry";
|
export const DEFAULT_VIEW_LAYOUT = "masonry";
|
||||||
export const PANEL_VIEW_LAYOUT = "panel";
|
export const PANEL_VIEW_LAYOUT = "panel";
|
||||||
export const SIDEBAR_VIEW_LAYOUT = "sidebar";
|
export const SIDEBAR_VIEW_LAYOUT = "sidebar";
|
||||||
|
export const MANUAL_VIEW_LAYOUT = "manual";
|
||||||
export const VIEWS_NO_BADGE_SUPPORT = [PANEL_VIEW_LAYOUT, SIDEBAR_VIEW_LAYOUT];
|
export const VIEWS_NO_BADGE_SUPPORT = [PANEL_VIEW_LAYOUT, SIDEBAR_VIEW_LAYOUT];
|
||||||
|
|
|
@ -0,0 +1,358 @@
|
||||||
|
import { mdiCursorMove, mdiDelete, mdiPencil, mdiPlus } from "@mdi/js";
|
||||||
|
import { GridStack, GridStackWidget } from "gridstack";
|
||||||
|
import gridStackStyleExtra from "gridstack/dist/gridstack-extra.min.css";
|
||||||
|
import gridStackStyle from "gridstack/dist/gridstack.min.css";
|
||||||
|
import {
|
||||||
|
CSSResultGroup,
|
||||||
|
LitElement,
|
||||||
|
PropertyValues,
|
||||||
|
TemplateResult,
|
||||||
|
css,
|
||||||
|
html,
|
||||||
|
nothing,
|
||||||
|
unsafeCSS,
|
||||||
|
} from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { classMap } from "lit/directives/class-map";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||||
|
import "../../../components/entity/ha-state-label-badge";
|
||||||
|
import "../../../components/ha-svg-icon";
|
||||||
|
import type { LovelaceViewElement } from "../../../data/lovelace";
|
||||||
|
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||||
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import type { HuiErrorCard } from "../cards/hui-error-card";
|
||||||
|
import { createCardElement } from "../custom-card-helpers";
|
||||||
|
import { replaceView } from "../editor/config-util";
|
||||||
|
import type { Lovelace, LovelaceBadge, LovelaceCard } from "../types";
|
||||||
|
|
||||||
|
@customElement("hui-manual-view")
|
||||||
|
export class ManualView extends LitElement implements LovelaceViewElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public lovelace?: Lovelace;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
|
@property({ type: Number }) public index?: number;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public isStrategy = false;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public cards: Array<
|
||||||
|
LovelaceCard | HuiErrorCard
|
||||||
|
> = [];
|
||||||
|
|
||||||
|
@property({ attribute: false }) public badges: LovelaceBadge[] = [];
|
||||||
|
|
||||||
|
public setConfig(_config: LovelaceViewConfig): void {}
|
||||||
|
|
||||||
|
private _grid?: GridStack;
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
if (this.hasUpdated) {
|
||||||
|
this._setupGrid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
this._grid?.destroy(false);
|
||||||
|
this._grid = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
${this.badges.length > 0
|
||||||
|
? html`<div class="badges">${this.badges}</div>`
|
||||||
|
: ""}
|
||||||
|
<div class="grid-stack">
|
||||||
|
${this.cards.map(
|
||||||
|
(card, i) =>
|
||||||
|
html`<div class="grid-stack-item" gs-id=${i}>
|
||||||
|
${this.lovelace?.editMode
|
||||||
|
? html` <div class="controls">
|
||||||
|
<ha-svg-icon
|
||||||
|
class="handle"
|
||||||
|
.path=${mdiCursorMove}
|
||||||
|
></ha-svg-icon>
|
||||||
|
<ha-icon-button
|
||||||
|
@click=${this._editCard}
|
||||||
|
.path=${mdiPencil}
|
||||||
|
.index=${i}
|
||||||
|
></ha-icon-button>
|
||||||
|
<ha-icon-button
|
||||||
|
@click=${this._deleteCard}
|
||||||
|
.index=${i}
|
||||||
|
class="warning"
|
||||||
|
.path=${mdiDelete}
|
||||||
|
></ha-icon-button>
|
||||||
|
</div>`
|
||||||
|
: nothing}
|
||||||
|
<div class="grid-stack-item-content">${card}</div>
|
||||||
|
</div>`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
${this.lovelace?.editMode
|
||||||
|
? html`
|
||||||
|
<ha-fab
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_card.add"
|
||||||
|
)}
|
||||||
|
extended
|
||||||
|
@click=${this._addCard}
|
||||||
|
class=${classMap({
|
||||||
|
rtl: computeRTL(this.hass!),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||||
|
</ha-fab>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
firstUpdated(changed) {
|
||||||
|
super.firstUpdated(changed);
|
||||||
|
this._setupGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
updated(changedProperties: PropertyValues) {
|
||||||
|
if (
|
||||||
|
changedProperties.has("lovelace") &&
|
||||||
|
this.lovelace?.editMode !== changedProperties.get("lovelace")?.editMode
|
||||||
|
) {
|
||||||
|
if (this.lovelace?.editMode) {
|
||||||
|
this._grid!.setStatic(false);
|
||||||
|
this._grid!.setAnimation(true);
|
||||||
|
// this.grid.addWidget(
|
||||||
|
// '<div class="grid-stack-item"><div class="grid-stack-item-content">hello</div></div>',
|
||||||
|
// { w: 3 }
|
||||||
|
// );
|
||||||
|
} else {
|
||||||
|
this._grid!.setStatic(true);
|
||||||
|
this._grid!.setAnimation(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
changedProperties.has("cards") &&
|
||||||
|
changedProperties.get("cards") &&
|
||||||
|
!this.lovelace?.editMode
|
||||||
|
) {
|
||||||
|
this._grid!.load(
|
||||||
|
(
|
||||||
|
this.lovelace?.config.views[this.index!] as LovelaceViewConfig
|
||||||
|
).cards?.map((card, i) => ({
|
||||||
|
id: i.toString(),
|
||||||
|
...card.view_layout,
|
||||||
|
})) || [],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public willUpdate(changedProperties: PropertyValues) {
|
||||||
|
super.willUpdate(changedProperties);
|
||||||
|
|
||||||
|
if (
|
||||||
|
changedProperties.has("lovelace") &&
|
||||||
|
this.lovelace?.editMode !== changedProperties.get("lovelace")?.editMode
|
||||||
|
) {
|
||||||
|
if (this.lovelace?.editMode) {
|
||||||
|
import("./default-view-editable");
|
||||||
|
} else if (this._grid) {
|
||||||
|
this._saveLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedProperties.has("hass")) {
|
||||||
|
const oldHass = changedProperties.get("hass") as
|
||||||
|
| HomeAssistant
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
if (this.hass!.dockedSidebar !== oldHass?.dockedSidebar) {
|
||||||
|
// this._updateColumns();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedProperties.has("narrow")) {
|
||||||
|
// this._updateColumns();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldLovelace = changedProperties.get("lovelace") as
|
||||||
|
| Lovelace
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
if (
|
||||||
|
changedProperties.has("cards") ||
|
||||||
|
(changedProperties.has("lovelace") &&
|
||||||
|
oldLovelace &&
|
||||||
|
(oldLovelace.config !== this.lovelace!.config ||
|
||||||
|
oldLovelace.editMode !== this.lovelace!.editMode))
|
||||||
|
) {
|
||||||
|
// this._createColumns();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _editCard(ev): Promise<void> {
|
||||||
|
const index = ev.target.index;
|
||||||
|
fireEvent(this, "ll-edit-card", { path: [this.index!, index] });
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _deleteCard(ev): Promise<void> {
|
||||||
|
const index = ev.target.index;
|
||||||
|
fireEvent(this, "ll-delete-card", {
|
||||||
|
path: [this.index!, index],
|
||||||
|
confirm: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _addCard(): Promise<void> {
|
||||||
|
fireEvent(this, "ll-create-card", {
|
||||||
|
preSaveConfig: async (config) => {
|
||||||
|
const card = createCardElement(config);
|
||||||
|
const height = await card.getCardSize();
|
||||||
|
const add = this._grid!.addWidget({
|
||||||
|
w: 3,
|
||||||
|
h: height,
|
||||||
|
content: "",
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
view_layout: {
|
||||||
|
x: add.gridstackNode!.x,
|
||||||
|
y: add.gridstackNode!.y,
|
||||||
|
w: add.gridstackNode!.w,
|
||||||
|
h: add.gridstackNode!.h,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _saveLayout(): Promise<void> {
|
||||||
|
if (!this._grid || !this.lovelace?.editMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const layouts = this._grid.save(false) as GridStackWidget[];
|
||||||
|
layouts
|
||||||
|
.sort((a, b) => Number(a.id!) - Number(b.id!))
|
||||||
|
.forEach((layout) => {
|
||||||
|
delete layout.id;
|
||||||
|
});
|
||||||
|
const cardConfigs = (
|
||||||
|
this.lovelace?.config.views[this.index!] as LovelaceViewConfig
|
||||||
|
).cards?.map((card, i) => ({
|
||||||
|
...card,
|
||||||
|
view_layout: layouts[i],
|
||||||
|
}));
|
||||||
|
await this.lovelace!.saveConfig(
|
||||||
|
replaceView(this.hass!, this.lovelace!.config, this.index!, {
|
||||||
|
...this.lovelace!.config.views[this.index!],
|
||||||
|
cards: cardConfigs,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setupGrid(): void {
|
||||||
|
this._grid = GridStack.init(
|
||||||
|
{
|
||||||
|
cellHeight: 60,
|
||||||
|
animate: false,
|
||||||
|
columnOpts: {
|
||||||
|
layout: "moveScale",
|
||||||
|
// breakpointForWindow: true, // test window vs grid size
|
||||||
|
breakpoints: [
|
||||||
|
{ w: 700, c: 1 },
|
||||||
|
{ w: 850, c: 4 },
|
||||||
|
{ w: 950, c: 8 },
|
||||||
|
{ w: 1100, c: 12 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
minRow: 5,
|
||||||
|
sizeToContent: false,
|
||||||
|
handleClass: "handle",
|
||||||
|
staticGrid: true,
|
||||||
|
margin: 4,
|
||||||
|
},
|
||||||
|
this.shadowRoot!.querySelector(".grid-stack") as HTMLElement
|
||||||
|
);
|
||||||
|
this._grid.load(
|
||||||
|
(
|
||||||
|
this.lovelace?.config.views[this.index!] as LovelaceViewConfig
|
||||||
|
).cards?.map((card, i) => ({
|
||||||
|
id: i.toString(),
|
||||||
|
...card.view_layout,
|
||||||
|
})) || [],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
this._grid.on("dragstop resizestop", () => {
|
||||||
|
this._saveLayout();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return css`
|
||||||
|
${unsafeCSS(gridStackStyle)}
|
||||||
|
${unsafeCSS(gridStackStyleExtra)}
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
.grid-stack {
|
||||||
|
height: 100vh;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
.grid-stack-item {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
display: none;
|
||||||
|
z-index: 999;
|
||||||
|
= }
|
||||||
|
|
||||||
|
.grid-stack-item:hover .controls {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.handle {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 12px;
|
||||||
|
cursor: move; /* fallback if grab cursor is unsupported */
|
||||||
|
cursor: grab !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.badges {
|
||||||
|
margin: 8px 16px;
|
||||||
|
font-size: 85%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
ha-fab {
|
||||||
|
position: fixed;
|
||||||
|
right: calc(16px + env(safe-area-inset-right));
|
||||||
|
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-fab.rtl {
|
||||||
|
right: auto;
|
||||||
|
left: calc(16px + env(safe-area-inset-left));
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-manual-view": ManualView;
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,7 +35,13 @@ import {
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"ll-create-card": undefined;
|
"ll-create-card":
|
||||||
|
| {
|
||||||
|
preSaveConfig?: (
|
||||||
|
config: LovelaceCardConfig
|
||||||
|
) => LovelaceCardConfig | Promise<LovelaceCardConfig>;
|
||||||
|
}
|
||||||
|
| undefined;
|
||||||
"ll-edit-card": { path: [number] | [number, number] };
|
"ll-edit-card": { path: [number] | [number, number] };
|
||||||
"ll-delete-card": { path: [number] | [number, number]; confirm: boolean };
|
"ll-delete-card": { path: [number] | [number, number]; confirm: boolean };
|
||||||
}
|
}
|
||||||
|
@ -236,9 +242,10 @@ export class HUIView extends ReactiveElement {
|
||||||
private _createLayoutElement(config: LovelaceViewConfig): void {
|
private _createLayoutElement(config: LovelaceViewConfig): void {
|
||||||
this._layoutElement = createViewElement(config) as LovelaceViewElement;
|
this._layoutElement = createViewElement(config) as LovelaceViewElement;
|
||||||
this._layoutElementType = config.type;
|
this._layoutElementType = config.type;
|
||||||
this._layoutElement.addEventListener("ll-create-card", () => {
|
this._layoutElement.addEventListener("ll-create-card", (ev) => {
|
||||||
showCreateCardDialog(this, {
|
showCreateCardDialog(this, {
|
||||||
lovelaceConfig: this.lovelace.config,
|
lovelaceConfig: this.lovelace.config,
|
||||||
|
preSaveConfig: ev.detail.preSaveConfig,
|
||||||
saveConfig: this.lovelace.saveConfig,
|
saveConfig: this.lovelace.saveConfig,
|
||||||
path: [this.index],
|
path: [this.index],
|
||||||
});
|
});
|
||||||
|
|
|
@ -4984,7 +4984,8 @@
|
||||||
"types": {
|
"types": {
|
||||||
"masonry": "Masonry (default)",
|
"masonry": "Masonry (default)",
|
||||||
"sidebar": "Sidebar",
|
"sidebar": "Sidebar",
|
||||||
"panel": "Panel (1 card)"
|
"panel": "Panel (1 card)",
|
||||||
|
"manual": "Manual"
|
||||||
},
|
},
|
||||||
"subview": "Subview",
|
"subview": "Subview",
|
||||||
"subview_helper": "Subviews don't appear in tabs and have a back button.",
|
"subview_helper": "Subviews don't appear in tabs and have a back button.",
|
||||||
|
|
|
@ -9235,6 +9235,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"gridstack@npm:10.0.1":
|
||||||
|
version: 10.0.1
|
||||||
|
resolution: "gridstack@npm:10.0.1"
|
||||||
|
checksum: 5310d1e299f01bba68162d1cf69725248a3a4baee2088276927597f74894da6a432981d2e1879464faee91f0011fc4f6cd8b71dceb812a175bb7cbcf4ab7ea8b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"gulp-cli@npm:^2.2.0":
|
"gulp-cli@npm:^2.2.0":
|
||||||
version: 2.3.0
|
version: 2.3.0
|
||||||
resolution: "gulp-cli@npm:2.3.0"
|
resolution: "gulp-cli@npm:2.3.0"
|
||||||
|
@ -9613,6 +9620,7 @@ __metadata:
|
||||||
fuse.js: "npm:7.0.0"
|
fuse.js: "npm:7.0.0"
|
||||||
glob: "npm:10.3.10"
|
glob: "npm:10.3.10"
|
||||||
google-timezones-json: "npm:1.2.0"
|
google-timezones-json: "npm:1.2.0"
|
||||||
|
gridstack: "npm:10.0.1"
|
||||||
gulp: "npm:4.0.2"
|
gulp: "npm:4.0.2"
|
||||||
gulp-flatmap: "npm:1.0.2"
|
gulp-flatmap: "npm:1.0.2"
|
||||||
gulp-json-transform: "npm:0.4.8"
|
gulp-json-transform: "npm:0.4.8"
|
||||||
|
|
Loading…
Reference in New Issue