diff --git a/package.json b/package.json index 9f80261b3a..b80d9f3f7f 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@lezer/highlight": "1.1.4", "@lit-labs/context": "0.3.1", "@lit-labs/motion": "1.0.3", - "@lit-labs/virtualizer": "1.0.1", + "@lit-labs/virtualizer": "2.0.1", "@lrnwebcomponents/simple-tooltip": "4.2.0", "@material/chips": "=14.0.0-canary.53b3cad2f.0", "@material/data-table": "=14.0.0-canary.53b3cad2f.0", diff --git a/src/components/chart/state-history-charts.ts b/src/components/chart/state-history-charts.ts index 4e7a0d429a..0e143284e4 100644 --- a/src/components/chart/state-history-charts.ts +++ b/src/components/chart/state-history-charts.ts @@ -1,4 +1,3 @@ -import "@lit-labs/virtualizer"; import { css, CSSResultGroup, @@ -15,6 +14,7 @@ import { LineChartUnit, TimelineEntity, } from "../../data/history"; +import { loadVirtualizer } from "../../resources/virtualizer"; import type { HomeAssistant } from "../../types"; import "./state-history-chart-line"; import "./state-history-chart-timeline"; @@ -171,6 +171,12 @@ export class StateHistoryCharts extends LitElement { return !(changedProps.size === 1 && changedProps.has("hass")); } + protected willUpdate() { + if (!this.hasUpdated) { + loadVirtualizer(); + } + } + protected updated(changedProps: PropertyValues) { if (changedProps.has("_chartCount")) { if (this._chartCount < this._childYWidths.length) { diff --git a/src/components/data-table/ha-data-table.ts b/src/components/data-table/ha-data-table.ts index b489ba505e..0ddf74db1a 100644 --- a/src/components/data-table/ha-data-table.ts +++ b/src/components/data-table/ha-data-table.ts @@ -1,4 +1,3 @@ -import "@lit-labs/virtualizer"; import { mdiArrowDown, mdiArrowUp } from "@mdi/js"; import deepClone from "deep-clone-simple"; import { @@ -26,6 +25,7 @@ import { fireEvent } from "../../common/dom/fire_event"; import { debounce } from "../../common/util/debounce"; import { nextRender } from "../../common/util/render-status"; import { haStyleScrollbar } from "../../resources/styles"; +import { loadVirtualizer } from "../../resources/virtualizer"; import { HomeAssistant } from "../../types"; import "../ha-checkbox"; import type { HaCheckbox } from "../ha-checkbox"; @@ -184,6 +184,10 @@ export class HaDataTable extends LitElement { public willUpdate(properties: PropertyValues) { super.willUpdate(properties); + if (!this.hasUpdated) { + loadVirtualizer(); + } + if (properties.has("columns")) { this._filterable = Object.values(this.columns).some( (column) => column.filterable diff --git a/src/components/map/ha-map.ts b/src/components/map/ha-map.ts index 671b46e8a1..5cd9d44451 100644 --- a/src/components/map/ha-map.ts +++ b/src/components/map/ha-map.ts @@ -15,7 +15,7 @@ import { } from "../../common/dom/setup-leaflet-map"; import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { computeStateName } from "../../common/entity/compute_state_name"; -import { installResizeObserver } from "../../panels/lovelace/common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../resources/resize-observer.polyfill"; import { HomeAssistant } from "../../types"; import "../ha-icon-button"; import "./ha-entity-marker"; @@ -450,7 +450,7 @@ export class HaMap extends ReactiveElement { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver(() => { this.leafletMap?.invalidateSize({ debounceMoveend: true }); }); diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts index 95006e0bda..ae617af86b 100644 --- a/src/components/media-player/ha-media-player-browse.ts +++ b/src/components/media-player/ha-media-player-browse.ts @@ -1,4 +1,3 @@ -import "@lit-labs/virtualizer"; import type { LitVirtualizer } from "@lit-labs/virtualizer"; import { grid } from "@lit-labs/virtualizer/layouts/grid"; import "@material/mwc-button/mwc-button"; @@ -40,7 +39,7 @@ import { import { browseLocalMediaPlayer } from "../../data/media_source"; import { isTTSMediaSource } from "../../data/tts"; import { showAlertDialog } from "../../dialogs/generic/show-dialog-box"; -import { installResizeObserver } from "../../panels/lovelace/common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../resources/resize-observer.polyfill"; import { haStyle } from "../../resources/styles"; import type { HomeAssistant } from "../../types"; import { @@ -59,6 +58,7 @@ import "../ha-icon-button"; import "../ha-svg-icon"; import "./ha-browse-media-tts"; import type { TtsMediaPickedEvent } from "./ha-browse-media-tts"; +import { loadVirtualizer } from "../../resources/virtualizer"; declare global { interface HASSDomEvents { @@ -154,6 +154,10 @@ export class HaMediaPlayerBrowse extends LitElement { public willUpdate(changedProps: PropertyValues): void { super.willUpdate(changedProps); + if (!this.hasUpdated) { + loadVirtualizer(); + } + if (changedProps.has("entityId")) { this._setError(undefined); } else if (!changedProps.has("navigateIds")) { @@ -750,7 +754,7 @@ export class HaMediaPlayerBrowse extends LitElement { private async _attachResizeObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureCard(), 250, false) ); diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index b9c53375d0..bb1902e7dd 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -1,4 +1,3 @@ -import "@lit-labs/virtualizer"; import "@material/mwc-list/mwc-list"; import type { ListItem } from "@material/mwc-list/mwc-list-item"; import { @@ -39,6 +38,7 @@ import { getPanelNameTranslationKey } from "../../data/panel"; import { PageNavigation } from "../../layouts/hass-tabs-subpage"; import { configSections } from "../../panels/config/ha-panel-config"; import { haStyleDialog, haStyleScrollbar } from "../../resources/styles"; +import { loadVirtualizer } from "../../resources/virtualizer"; import { HomeAssistant } from "../../types"; import { ConfirmationDialogParams, @@ -122,6 +122,12 @@ export class QuickBar extends LitElement { fireEvent(this, "dialog-closed", { dialog: this.localName }); } + protected willUpdate() { + if (!this.hasUpdated) { + loadVirtualizer(); + } + } + private _getItems = memoizeOne( (commandMode: boolean, commandItems, entityItems, filter: string) => { const items = commandMode ? commandItems : entityItems; diff --git a/src/panels/config/helpers/forms/ha-schedule-form.ts b/src/panels/config/helpers/forms/ha-schedule-form.ts index 81d34c6c9a..1568452504 100644 --- a/src/panels/config/helpers/forms/ha-schedule-form.ts +++ b/src/panels/config/helpers/forms/ha-schedule-form.ts @@ -22,7 +22,7 @@ import "../../../../components/ha-textfield"; import { Schedule, ScheduleDay, weekdays } from "../../../../data/schedule"; import { haStyle } from "../../../../resources/styles"; import { HomeAssistant } from "../../../../types"; -import { installResizeObserver } from "../../../lovelace/common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../../../resources/resize-observer.polyfill"; const defaultFullCalendarConfig: CalendarOptions = { plugins: [timeGridPlugin, interactionPlugin], @@ -125,7 +125,7 @@ class HaScheduleForm extends LitElement { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureForm(), 250, false) ); diff --git a/src/panels/logbook/ha-logbook-renderer.ts b/src/panels/logbook/ha-logbook-renderer.ts index aa6a64e5f2..e93d3858d4 100644 --- a/src/panels/logbook/ha-logbook-renderer.ts +++ b/src/panels/logbook/ha-logbook-renderer.ts @@ -35,6 +35,7 @@ import { haStyle, haStyleScrollbar, } from "../../resources/styles"; +import { loadVirtualizer } from "../../resources/virtualizer"; import { HomeAssistant } from "../../types"; import { brandsUrl } from "../../util/brands-url"; @@ -83,6 +84,15 @@ class HaLogbookRenderer extends LitElement { // @ts-ignore @restoreScroll(".container") private _savedScrollPos?: number; + protected willUpdate(changedProps: PropertyValues) { + if ( + (!this.hasUpdated && this.virtualize) || + (changedProps.has("virtualize") && this.virtualize) + ) { + loadVirtualizer(); + } + } + protected shouldUpdate(changedProps: PropertyValues) { const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const languageChanged = diff --git a/src/panels/lovelace/cards/hui-calendar-card.ts b/src/panels/lovelace/cards/hui-calendar-card.ts index c502cc1da8..855825f65d 100644 --- a/src/panels/lovelace/cards/hui-calendar-card.ts +++ b/src/panels/lovelace/cards/hui-calendar-card.ts @@ -26,7 +26,7 @@ import type { import "../../calendar/ha-full-calendar"; import type { HAFullCalendar } from "../../calendar/ha-full-calendar"; import { findEntities } from "../common/find-entities"; -import { installResizeObserver } from "../common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../../resources/resize-observer.polyfill"; import "../components/hui-warning"; import type { LovelaceCard, LovelaceCardEditor } from "../types"; import type { CalendarCardConfig } from "./types"; @@ -215,7 +215,7 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureCard(), 250, false) ); diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index 2a021ff662..4a5af932ce 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -37,7 +37,7 @@ import { import type { HomeAssistant } from "../../../types"; import { findEntities } from "../common/find-entities"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import { installResizeObserver } from "../common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../../resources/resize-observer.polyfill"; import "../components/hui-marquee"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { LovelaceCard, LovelaceCardEditor } from "../types"; @@ -471,7 +471,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureCard(), 250, false) ); diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index ede2e99b3a..066d14fa02 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -35,7 +35,7 @@ import { findEntities } from "../common/find-entities"; import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import { installResizeObserver } from "../common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../../resources/resize-observer.polyfill"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { LovelaceCard, LovelaceCardEditor } from "../types"; import type { WeatherForecastCardConfig } from "./types"; @@ -377,7 +377,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureCard(), 250, false) ); diff --git a/src/panels/lovelace/common/install-resize-observer.ts b/src/panels/lovelace/common/install-resize-observer.ts deleted file mode 100644 index 1018ea38ca..0000000000 --- a/src/panels/lovelace/common/install-resize-observer.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const installResizeObserver = async () => { - if (typeof ResizeObserver !== "function") { - window.ResizeObserver = (await import("resize-observer-polyfill")).default; - } -}; diff --git a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts index 777cbc0a68..ab81ff7eb1 100644 --- a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts @@ -16,7 +16,7 @@ import { isUnavailableState } from "../../../data/entity"; import { setValue } from "../../../data/input_text"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import { installResizeObserver } from "../common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../../resources/resize-observer.polyfill"; import "../components/hui-generic-entity-row"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; @@ -170,7 +170,7 @@ class HuiInputNumberEntityRow extends LitElement implements LovelaceRow { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureCard(), 250, false) ); diff --git a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts index 6828944007..2dc020a493 100644 --- a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts @@ -36,7 +36,7 @@ import { } from "../../../data/media-player"; import type { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import { installResizeObserver } from "../common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../../resources/resize-observer.polyfill"; import "../components/hui-generic-entity-row"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { EntityConfig, LovelaceRow } from "./types"; @@ -298,7 +298,7 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureCard(), 250, false) ); diff --git a/src/panels/lovelace/entity-rows/hui-number-entity-row.ts b/src/panels/lovelace/entity-rows/hui-number-entity-row.ts index f9232a1b17..0046379e3f 100644 --- a/src/panels/lovelace/entity-rows/hui-number-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-number-entity-row.ts @@ -16,7 +16,7 @@ import { UNAVAILABLE } from "../../../data/entity"; import { setValue } from "../../../data/input_text"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import { installResizeObserver } from "../common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../../../resources/resize-observer.polyfill"; import "../components/hui-generic-entity-row"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; @@ -175,7 +175,7 @@ class HuiNumberEntityRow extends LitElement implements LovelaceRow { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureCard(), 250, false) ); diff --git a/src/resources/resize-observer.polyfill.ts b/src/resources/resize-observer.polyfill.ts new file mode 100644 index 0000000000..4aa3e14cc6 --- /dev/null +++ b/src/resources/resize-observer.polyfill.ts @@ -0,0 +1,13 @@ +export const loadPolyfillIfNeeded = async () => { + try { + // eslint-disable-next-line no-new + new ResizeObserver(() => {}); + return; + } catch (e) { + window.ResizeObserver = ( + await import( + "@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver.js" + ) + ).default; + } +}; diff --git a/src/resources/virtualizer.ts b/src/resources/virtualizer.ts new file mode 100644 index 0000000000..ba92a2b2f4 --- /dev/null +++ b/src/resources/virtualizer.ts @@ -0,0 +1,6 @@ +import { loadPolyfillIfNeeded } from "./resize-observer.polyfill"; + +export const loadVirtualizer = async () => { + await loadPolyfillIfNeeded(); + await import("@lit-labs/virtualizer"); +}; diff --git a/src/state-summary/state-card-input_number.ts b/src/state-summary/state-card-input_number.ts index 02829dd96a..d455a5a862 100644 --- a/src/state-summary/state-card-input_number.ts +++ b/src/state-summary/state-card-input_number.ts @@ -10,7 +10,7 @@ import "../components/entity/state-info"; import { isUnavailableState } from "../data/entity"; import { setValue } from "../data/input_text"; import { HomeAssistant } from "../types"; -import { installResizeObserver } from "../panels/lovelace/common/install-resize-observer"; +import { loadPolyfillIfNeeded } from "../resources/resize-observer.polyfill"; @customElement("state-card-input_number") class StateCardInputNumber extends LitElement { @@ -141,7 +141,7 @@ class StateCardInputNumber extends LitElement { private async _attachObserver(): Promise { if (!this._resizeObserver) { - await installResizeObserver(); + await loadPolyfillIfNeeded(); this._resizeObserver = new ResizeObserver( debounce(() => this._measureCard(), 250, false) ); diff --git a/yarn.lock b/yarn.lock index d738bd2d8f..3706cdc659 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2002,14 +2002,13 @@ __metadata: languageName: node linkType: hard -"@lit-labs/virtualizer@npm:1.0.1": - version: 1.0.1 - resolution: "@lit-labs/virtualizer@npm:1.0.1" +"@lit-labs/virtualizer@npm:2.0.1": + version: 2.0.1 + resolution: "@lit-labs/virtualizer@npm:2.0.1" dependencies: - event-target-shim: ^6.0.2 - lit: ^2.5.0 + lit: ^2.7.0 tslib: ^2.0.3 - checksum: e20ab1cefb48768e8b757147a4eb97c2dd5db686b452eb1cf3d6c9ea178c23ed55540f57117597599c2b5abfb9266f068c782fdbf6b4286637ff8d2e6fd9ff0a + checksum: 93f7fafecd0a535c4d1c6107dab39bf6092b323f1ce57adfa816058da9dce71006f3c109e4fb473aa1e5aeba3154b1fc9bdba7aa75f97f021cbcaf0d3f052d87 languageName: node linkType: hard @@ -8126,13 +8125,6 @@ __metadata: languageName: node linkType: hard -"event-target-shim@npm:^6.0.2": - version: 6.0.2 - resolution: "event-target-shim@npm:6.0.2" - checksum: 9be93437e5b84056a7dc70af8b8962f4ef7f6fd41a988efcd39dfa2853e33242a4058e0dac9cc589cb16ed7409010590ac8cbcc2e3f823100cd337e13be953a0 - languageName: node - linkType: hard - "eventemitter3@npm:^4.0.0": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" @@ -9460,7 +9452,7 @@ __metadata: "@lezer/highlight": 1.1.4 "@lit-labs/context": 0.3.1 "@lit-labs/motion": 1.0.3 - "@lit-labs/virtualizer": 1.0.1 + "@lit-labs/virtualizer": 2.0.1 "@lrnwebcomponents/simple-tooltip": 4.2.0 "@material/chips": =14.0.0-canary.53b3cad2f.0 "@material/data-table": =14.0.0-canary.53b3cad2f.0 @@ -11285,7 +11277,7 @@ __metadata: languageName: node linkType: hard -"lit@npm:2.7.2, lit@npm:^2.0.0, lit@npm:^2.0.0-rc.2, lit@npm:^2.2.1, lit@npm:^2.3.0, lit@npm:^2.5.0, lit@npm:^2.6.1, lit@npm:^2.7.0": +"lit@npm:2.7.2, lit@npm:^2.0.0, lit@npm:^2.0.0-rc.2, lit@npm:^2.2.1, lit@npm:^2.3.0, lit@npm:^2.6.1, lit@npm:^2.7.0": version: 2.7.2 resolution: "lit@npm:2.7.2" dependencies: