mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 12:26:35 +00:00
Add option to lazy load cards (#4857)
* Add option to lazy load cards * Lazy load header/footer elements * Lazy load rows * Clean up params * Rename last var
This commit is contained in:
parent
f5384e8bc8
commit
b2243f480c
@ -1,10 +1,19 @@
|
|||||||
import "../badges/hui-entity-filter-badge";
|
|
||||||
import "../badges/hui-state-label-badge";
|
import "../badges/hui-state-label-badge";
|
||||||
|
|
||||||
import { LovelaceBadgeConfig } from "../../../data/lovelace";
|
import { LovelaceBadgeConfig } from "../../../data/lovelace";
|
||||||
import { createLovelaceElement } from "./create-element-base";
|
import { createLovelaceElement } from "./create-element-base";
|
||||||
|
|
||||||
const BADGE_TYPES = new Set(["entity-filter", "error", "state-label"]);
|
const ALWAYS_LOADED_TYPES = new Set(["error", "state-label"]);
|
||||||
|
const LAZY_LOAD_TYPES = {
|
||||||
|
"entity-filter": () => import("../badges/hui-entity-filter-badge"),
|
||||||
|
};
|
||||||
|
|
||||||
export const createBadgeElement = (config: LovelaceBadgeConfig) =>
|
export const createBadgeElement = (config: LovelaceBadgeConfig) =>
|
||||||
createLovelaceElement("badge", config, BADGE_TYPES, undefined, "state-label");
|
createLovelaceElement(
|
||||||
|
"badge",
|
||||||
|
config,
|
||||||
|
ALWAYS_LOADED_TYPES,
|
||||||
|
LAZY_LOAD_TYPES,
|
||||||
|
undefined,
|
||||||
|
"state-label"
|
||||||
|
);
|
||||||
|
@ -1,57 +1,54 @@
|
|||||||
import "../cards/hui-alarm-panel-card";
|
|
||||||
import "../cards/hui-conditional-card";
|
|
||||||
import "../cards/hui-entities-card";
|
import "../cards/hui-entities-card";
|
||||||
import "../cards/hui-entity-button-card";
|
import "../cards/hui-entity-button-card";
|
||||||
import "../cards/hui-entity-filter-card";
|
|
||||||
import "../cards/hui-glance-card";
|
import "../cards/hui-glance-card";
|
||||||
import "../cards/hui-history-graph-card";
|
import "../cards/hui-history-graph-card";
|
||||||
import "../cards/hui-horizontal-stack-card";
|
import "../cards/hui-horizontal-stack-card";
|
||||||
import "../cards/hui-iframe-card";
|
|
||||||
import "../cards/hui-light-card";
|
import "../cards/hui-light-card";
|
||||||
import "../cards/hui-map-card";
|
|
||||||
import "../cards/hui-markdown-card";
|
|
||||||
import "../cards/hui-media-control-card";
|
import "../cards/hui-media-control-card";
|
||||||
import "../cards/hui-picture-card";
|
|
||||||
import "../cards/hui-picture-elements-card";
|
|
||||||
import "../cards/hui-picture-entity-card";
|
|
||||||
import "../cards/hui-picture-glance-card";
|
|
||||||
import "../cards/hui-plant-status-card";
|
|
||||||
import "../cards/hui-sensor-card";
|
import "../cards/hui-sensor-card";
|
||||||
import "../cards/hui-vertical-stack-card";
|
|
||||||
import "../cards/hui-shopping-list-card";
|
|
||||||
import "../cards/hui-thermostat-card";
|
import "../cards/hui-thermostat-card";
|
||||||
|
import "../cards/hui-vertical-stack-card";
|
||||||
import "../cards/hui-weather-forecast-card";
|
import "../cards/hui-weather-forecast-card";
|
||||||
import "../cards/hui-gauge-card";
|
|
||||||
import { LovelaceCardConfig } from "../../../data/lovelace";
|
import { LovelaceCardConfig } from "../../../data/lovelace";
|
||||||
import { createLovelaceElement } from "./create-element-base";
|
import { createLovelaceElement } from "./create-element-base";
|
||||||
|
|
||||||
const CARD_TYPES = new Set([
|
const ALWAYS_LOADED_TYPES = new Set([
|
||||||
"alarm-panel",
|
|
||||||
"conditional",
|
|
||||||
"entities",
|
"entities",
|
||||||
"entity-button",
|
"entity-button",
|
||||||
"entity-filter",
|
|
||||||
"error",
|
"error",
|
||||||
"gauge",
|
|
||||||
"glance",
|
"glance",
|
||||||
"history-graph",
|
"history-graph",
|
||||||
"horizontal-stack",
|
"horizontal-stack",
|
||||||
"iframe",
|
|
||||||
"light",
|
"light",
|
||||||
"map",
|
|
||||||
"markdown",
|
|
||||||
"media-control",
|
"media-control",
|
||||||
"picture",
|
|
||||||
"picture-elements",
|
|
||||||
"picture-entity",
|
|
||||||
"picture-glance",
|
|
||||||
"plant-status",
|
|
||||||
"sensor",
|
"sensor",
|
||||||
"shopping-list",
|
|
||||||
"thermostat",
|
"thermostat",
|
||||||
"vertical-stack",
|
"vertical-stack",
|
||||||
"weather-forecast",
|
"weather-forecast",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const LAZY_LOAD_TYPES = {
|
||||||
|
"alarm-panel": () => import("../cards/hui-alarm-panel-card"),
|
||||||
|
"entity-filter": () => import("../cards/hui-entity-filter-card"),
|
||||||
|
"picture-elements": () => import("../cards/hui-picture-elements-card"),
|
||||||
|
"picture-entity": () => import("../cards/hui-picture-entity-card"),
|
||||||
|
"picture-glance": () => import("../cards/hui-picture-glance-card"),
|
||||||
|
"plant-status": () => import("../cards/hui-plant-status-card"),
|
||||||
|
"shopping-list": () => import("../cards/hui-shopping-list-card"),
|
||||||
|
conditional: () => import("../cards/hui-conditional-card"),
|
||||||
|
gauge: () => import("../cards/hui-gauge-card"),
|
||||||
|
iframe: () => import("../cards/hui-iframe-card"),
|
||||||
|
map: () => import("../cards/hui-map-card"),
|
||||||
|
markdown: () => import("../cards/hui-markdown-card"),
|
||||||
|
picture: () => import("../cards/hui-picture-card"),
|
||||||
|
};
|
||||||
|
|
||||||
export const createCardElement = (config: LovelaceCardConfig) =>
|
export const createCardElement = (config: LovelaceCardConfig) =>
|
||||||
createLovelaceElement("card", config, CARD_TYPES);
|
createLovelaceElement(
|
||||||
|
"card",
|
||||||
|
config,
|
||||||
|
ALWAYS_LOADED_TYPES,
|
||||||
|
LAZY_LOAD_TYPES,
|
||||||
|
undefined,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
@ -50,10 +50,36 @@ const _createErrorElement = <T extends keyof CreateElementConfigTypes>(
|
|||||||
config: CreateElementConfigTypes[T]["config"]
|
config: CreateElementConfigTypes[T]["config"]
|
||||||
): HuiErrorCard => createErrorCardElement(createErrorCardConfig(error, config));
|
): HuiErrorCard => createErrorCardElement(createErrorCardConfig(error, config));
|
||||||
|
|
||||||
|
const _maybeCreate = <T extends keyof CreateElementConfigTypes>(
|
||||||
|
tag: string,
|
||||||
|
config: CreateElementConfigTypes[T]["config"]
|
||||||
|
) => {
|
||||||
|
if (customElements.get(tag)) {
|
||||||
|
return _createElement(tag, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
const element = _createErrorElement(
|
||||||
|
`Custom element doesn't exist: ${tag}.`,
|
||||||
|
config
|
||||||
|
);
|
||||||
|
element.style.display = "None";
|
||||||
|
const timer = window.setTimeout(() => {
|
||||||
|
element.style.display = "";
|
||||||
|
}, TIMEOUT);
|
||||||
|
|
||||||
|
customElements.whenDefined(tag).then(() => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
fireEvent(element, "ll-rebuild");
|
||||||
|
});
|
||||||
|
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
export const createLovelaceElement = <T extends keyof CreateElementConfigTypes>(
|
export const createLovelaceElement = <T extends keyof CreateElementConfigTypes>(
|
||||||
tagSuffix: T,
|
tagSuffix: T,
|
||||||
config: CreateElementConfigTypes[T]["config"],
|
config: CreateElementConfigTypes[T]["config"],
|
||||||
elementTypes: Set<string>,
|
alwaysLoadTypes?: Set<string>,
|
||||||
|
lazyLoadTypes?: { [domain: string]: () => unknown },
|
||||||
// Allow looking at "entity" in config and mapping that to a type
|
// Allow looking at "entity" in config and mapping that to a type
|
||||||
domainTypes?: { _domain_not_found: string; [domain: string]: string },
|
domainTypes?: { _domain_not_found: string; [domain: string]: string },
|
||||||
// Default type if no type given. If given, entity types will not work.
|
// Default type if no type given. If given, entity types will not work.
|
||||||
@ -73,43 +99,35 @@ export const createLovelaceElement = <T extends keyof CreateElementConfigTypes>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.type && config.type.startsWith(CUSTOM_TYPE_PREFIX)) {
|
if (config.type && config.type.startsWith(CUSTOM_TYPE_PREFIX)) {
|
||||||
const tag = config.type.substr(CUSTOM_TYPE_PREFIX.length);
|
return _maybeCreate(config.type.substr(CUSTOM_TYPE_PREFIX.length), config);
|
||||||
|
|
||||||
if (customElements.get(tag)) {
|
|
||||||
return _createElement(tag, config);
|
|
||||||
}
|
|
||||||
const element = _createErrorElement(
|
|
||||||
`Custom element doesn't exist: ${tag}.`,
|
|
||||||
config
|
|
||||||
);
|
|
||||||
element.style.display = "None";
|
|
||||||
const timer = window.setTimeout(() => {
|
|
||||||
element.style.display = "";
|
|
||||||
}, TIMEOUT);
|
|
||||||
|
|
||||||
customElements.whenDefined(tag).then(() => {
|
|
||||||
clearTimeout(timer);
|
|
||||||
fireEvent(element, "ll-rebuild");
|
|
||||||
});
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let type: string | undefined;
|
||||||
|
|
||||||
// config.type has priority over config.entity, but defaultType has not.
|
// config.type has priority over config.entity, but defaultType has not.
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (domainTypes && !config.type && config.entity) {
|
if (domainTypes && !config.type && config.entity) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const domain = config.entity.split(".", 1)[0];
|
const domain = config.entity.split(".", 1)[0];
|
||||||
return _createElement(
|
type = `${domainTypes![domain] || domainTypes!._domain_not_found}-entity`;
|
||||||
`hui-${domainTypes![domain] ||
|
} else {
|
||||||
domainTypes!._domain_not_found}-entity-${tagSuffix}`,
|
type = config.type || defaultType;
|
||||||
config
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = config.type || defaultType;
|
if (type === undefined) {
|
||||||
|
return _createErrorElement(`No type specified`, config);
|
||||||
|
}
|
||||||
|
|
||||||
return type !== undefined && elementTypes.has(type)
|
const tag = `hui-${type}-${tagSuffix}`;
|
||||||
? _createElement(`hui-${type}-${tagSuffix}`, config)
|
|
||||||
: _createErrorElement(`Unknown type encountered: ${type}.`, config);
|
if (lazyLoadTypes && type in lazyLoadTypes) {
|
||||||
|
lazyLoadTypes[type]();
|
||||||
|
return _maybeCreate(tag, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alwaysLoadTypes && alwaysLoadTypes.has(type)) {
|
||||||
|
return _createElement(tag, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _createErrorElement(`Unknown type encountered: ${type}.`, config);
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
import "../header-footer/hui-picture-header-footer";
|
|
||||||
import "../header-footer/hui-buttons-header-footer";
|
|
||||||
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
||||||
import { createLovelaceElement } from "./create-element-base";
|
import { createLovelaceElement } from "./create-element-base";
|
||||||
|
|
||||||
const SPECIAL_TYPES = new Set(["picture", "buttons"]);
|
const LAZY_LOAD_TYPES = {
|
||||||
|
picture: () => import("../header-footer/hui-picture-header-footer"),
|
||||||
|
buttons: () => import("../header-footer/hui-buttons-header-footer"),
|
||||||
|
};
|
||||||
|
|
||||||
export const createHeaderFooterElement = (config: LovelaceHeaderFooterConfig) =>
|
export const createHeaderFooterElement = (config: LovelaceHeaderFooterConfig) =>
|
||||||
createLovelaceElement("header-footer", config, SPECIAL_TYPES);
|
createLovelaceElement(
|
||||||
|
"header-footer",
|
||||||
|
config,
|
||||||
|
undefined,
|
||||||
|
LAZY_LOAD_TYPES,
|
||||||
|
undefined,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
@ -9,7 +9,7 @@ import "../elements/hui-state-label-element";
|
|||||||
import { LovelaceElementConfig } from "../elements/types";
|
import { LovelaceElementConfig } from "../elements/types";
|
||||||
import { createLovelaceElement } from "./create-element-base";
|
import { createLovelaceElement } from "./create-element-base";
|
||||||
|
|
||||||
const ELEMENT_TYPES = new Set([
|
const ALWAYS_LOADED_TYPES = new Set([
|
||||||
"conditional",
|
"conditional",
|
||||||
"icon",
|
"icon",
|
||||||
"image",
|
"image",
|
||||||
@ -20,4 +20,4 @@ const ELEMENT_TYPES = new Set([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
export const createHuiElement = (config: LovelaceElementConfig) =>
|
export const createHuiElement = (config: LovelaceElementConfig) =>
|
||||||
createLovelaceElement("element", config, ELEMENT_TYPES);
|
createLovelaceElement("element", config, ALWAYS_LOADED_TYPES);
|
||||||
|
@ -1,36 +1,41 @@
|
|||||||
import "../entity-rows/hui-climate-entity-row";
|
|
||||||
import "../entity-rows/hui-cover-entity-row";
|
|
||||||
import "../entity-rows/hui-group-entity-row";
|
|
||||||
import "../entity-rows/hui-input-datetime-entity-row";
|
|
||||||
import "../entity-rows/hui-input-number-entity-row";
|
|
||||||
import "../entity-rows/hui-input-select-entity-row";
|
|
||||||
import "../entity-rows/hui-input-text-entity-row";
|
|
||||||
import "../entity-rows/hui-lock-entity-row";
|
|
||||||
import "../entity-rows/hui-media-player-entity-row";
|
import "../entity-rows/hui-media-player-entity-row";
|
||||||
import "../entity-rows/hui-scene-entity-row";
|
import "../entity-rows/hui-scene-entity-row";
|
||||||
import "../entity-rows/hui-script-entity-row";
|
import "../entity-rows/hui-script-entity-row";
|
||||||
import "../entity-rows/hui-sensor-entity-row";
|
import "../entity-rows/hui-sensor-entity-row";
|
||||||
import "../entity-rows/hui-text-entity-row";
|
import "../entity-rows/hui-text-entity-row";
|
||||||
import "../entity-rows/hui-timer-entity-row";
|
|
||||||
import "../entity-rows/hui-toggle-entity-row";
|
import "../entity-rows/hui-toggle-entity-row";
|
||||||
import "../special-rows/hui-call-service-row";
|
import "../special-rows/hui-call-service-row";
|
||||||
import "../special-rows/hui-conditional-row";
|
|
||||||
import "../special-rows/hui-divider-row";
|
|
||||||
import "../special-rows/hui-section-row";
|
|
||||||
import "../special-rows/hui-weblink-row";
|
|
||||||
import "../special-rows/hui-cast-row";
|
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
import { createLovelaceElement } from "./create-element-base";
|
import { createLovelaceElement } from "./create-element-base";
|
||||||
|
|
||||||
const SPECIAL_TYPES = new Set([
|
const ALWAYS_LOADED_TYPES = new Set([
|
||||||
|
"media-player-entity",
|
||||||
|
"scene-entity",
|
||||||
|
"script-entity",
|
||||||
|
"sensor-entity",
|
||||||
|
"text-entity",
|
||||||
|
"toggle-entity",
|
||||||
"call-service",
|
"call-service",
|
||||||
"cast",
|
|
||||||
"conditional",
|
|
||||||
"divider",
|
|
||||||
"section",
|
|
||||||
"select",
|
|
||||||
"weblink",
|
|
||||||
]);
|
]);
|
||||||
|
const LAZY_LOAD_TYPES = {
|
||||||
|
"climate-entity": () => import("../entity-rows/hui-climate-entity-row"),
|
||||||
|
"cover-entity": () => import("../entity-rows/hui-cover-entity-row"),
|
||||||
|
"group-entity": () => import("../entity-rows/hui-group-entity-row"),
|
||||||
|
"input-datetime-entity": () =>
|
||||||
|
import("../entity-rows/hui-input-datetime-entity-row"),
|
||||||
|
"input-number-entity": () =>
|
||||||
|
import("../entity-rows/hui-input-number-entity-row"),
|
||||||
|
"input-select-entity": () =>
|
||||||
|
import("../entity-rows/hui-input-select-entity-row"),
|
||||||
|
"input-text-entity": () => import("../entity-rows/hui-input-text-entity-row"),
|
||||||
|
"lock-entity": () => import("../entity-rows/hui-lock-entity-row"),
|
||||||
|
"timer-entity": () => import("../entity-rows/hui-timer-entity-row"),
|
||||||
|
conditional: () => import("../special-rows/hui-conditional-row"),
|
||||||
|
divider: () => import("../special-rows/hui-divider-row"),
|
||||||
|
section: () => import("../special-rows/hui-section-row"),
|
||||||
|
weblink: () => import("../special-rows/hui-weblink-row"),
|
||||||
|
cast: () => import("../special-rows/hui-cast-row"),
|
||||||
|
};
|
||||||
const DOMAIN_TO_ELEMENT_TYPE = {
|
const DOMAIN_TO_ELEMENT_TYPE = {
|
||||||
_domain_not_found: "text",
|
_domain_not_found: "text",
|
||||||
alert: "toggle",
|
alert: "toggle",
|
||||||
@ -60,4 +65,11 @@ const DOMAIN_TO_ELEMENT_TYPE = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const createRowElement = (config: EntityConfig) =>
|
export const createRowElement = (config: EntityConfig) =>
|
||||||
createLovelaceElement("row", config, SPECIAL_TYPES, DOMAIN_TO_ELEMENT_TYPE);
|
createLovelaceElement(
|
||||||
|
"row",
|
||||||
|
config,
|
||||||
|
ALWAYS_LOADED_TYPES,
|
||||||
|
LAZY_LOAD_TYPES,
|
||||||
|
DOMAIN_TO_ELEMENT_TYPE,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user