- ${repositories.length
- ? repositories.map(
- (repo) => html`
-
${this.group.members.length
? html`
diff --git a/src/panels/config/logs/dialog-system-log-detail.ts b/src/panels/config/logs/dialog-system-log-detail.ts
index 5e047d7b07..1ea09ae743 100644
--- a/src/panels/config/logs/dialog-system-log-detail.ts
+++ b/src/panels/config/logs/dialog-system-log-detail.ts
@@ -102,12 +102,17 @@ class DialogSystemLogDetail extends LitElement {
: ""}
- Logger: ${item.name}
- Source: ${item.source.join(":")}
+ ${this.hass.localize("ui.panel.config.logs.detail.logger")}:
+ ${item.name}
+ ${this.hass.localize("ui.panel.config.logs.detail.source")}:
+ ${item.source.join(":")}
${integration
? html`
- Integration: ${domainToName(this.hass.localize, integration)}
+ ${this.hass.localize(
+ "ui.panel.config.logs.detail.integration"
+ )}:
+ ${domainToName(this.hass.localize, integration)}
${!this._manifest ||
// Can happen with custom integrations
!showDocumentation
@@ -122,7 +127,9 @@ class DialogSystemLogDetail extends LitElement {
: this._manifest.documentation}
target="_blank"
rel="noreferrer"
- >documentation${this.hass.localize(
+ "ui.panel.config.logs.detail.documentation"
+ )}${this._manifest.is_built_in ||
this._manifest.issue_tracker
? html`,
@@ -133,7 +140,9 @@ class DialogSystemLogDetail extends LitElement {
)}
target="_blank"
rel="noreferrer"
- >issues${this.hass.localize(
+ "ui.panel.config.logs.detail.issues"
+ )}`
: ""})
`}
@@ -142,16 +151,21 @@ class DialogSystemLogDetail extends LitElement {
${item.count > 0
? html`
- First occurred:
+ ${this.hass.localize(
+ "ui.panel.config.logs.detail.first_occurred"
+ )}:
${formatSystemLogTime(
item.first_occurred,
this.hass!.locale,
this.hass!.config
)}
- (${item.count} occurrences)
+ (${item.count}
+ ${this.hass.localize(
+ "ui.panel.config.logs.detail.occurrences"
+ )})
`
: ""}
- Last logged:
+ ${this.hass.localize("ui.panel.config.logs.detail.last_logged")}:
${formatSystemLogTime(
item.timestamp,
this.hass!.locale,
diff --git a/src/panels/config/lovelace/ha-config-lovelace.ts b/src/panels/config/lovelace/ha-config-lovelace.ts
index c494232bb8..eda9a8fd56 100644
--- a/src/panels/config/lovelace/ha-config-lovelace.ts
+++ b/src/panels/config/lovelace/ha-config-lovelace.ts
@@ -8,13 +8,20 @@ import { HomeAssistant } from "../../../types";
export const lovelaceTabs = [
{
- component: "lovelace",
path: "/config/lovelace/dashboards",
translationKey: "ui.panel.config.lovelace.dashboards.caption",
iconPath: mdiViewDashboard,
},
];
+export const lovelaceResourcesTabs = [
+ {
+ path: "/config/lovelace/resources",
+ translationKey: "ui.panel.config.lovelace.resources.caption",
+ iconPath: mdiViewDashboard,
+ },
+];
+
@customElement("ha-config-lovelace")
class HaConfigLovelace extends HassRouterPage {
@property({ attribute: false }) public hass!: HomeAssistant;
diff --git a/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts b/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts
index 9574f14fce..7713108edd 100644
--- a/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts
+++ b/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts
@@ -34,7 +34,7 @@ import "../../../../layouts/hass-tabs-subpage-data-table";
import { haStyle } from "../../../../resources/styles";
import { HomeAssistant, Route } from "../../../../types";
import { loadLovelaceResources } from "../../../lovelace/common/load-resources";
-import { lovelaceTabs } from "../ha-config-lovelace";
+import { lovelaceResourcesTabs } from "../ha-config-lovelace";
import { showResourceDetailDialog } from "./show-dialog-lovelace-resource-detail";
@customElement("ha-config-lovelace-resources")
@@ -117,7 +117,7 @@ export class HaConfigLovelaceRescources extends LitElement {
.hass=${this.hass}
.narrow=${this.narrow}
.route=${this.route}
- .tabs=${lovelaceTabs}
+ .tabs=${lovelaceResourcesTabs}
.columns=${this._columns(this.hass.language)}
.data=${this._resources}
.noDataText=${this.hass.localize(
diff --git a/src/panels/config/script/blueprint-script-editor.ts b/src/panels/config/script/blueprint-script-editor.ts
index be455965f4..c233eae662 100644
--- a/src/panels/config/script/blueprint-script-editor.ts
+++ b/src/panels/config/script/blueprint-script-editor.ts
@@ -1,52 +1,19 @@
-import { css, CSSResultGroup, html, LitElement } from "lit";
-import { customElement, property, state } from "lit/decorators";
-import { fireEvent } from "../../../common/dom/fire_event";
-import { nestedArrayMove } from "../../../common/util/array-move";
+import { html } from "lit";
+import { customElement, property } from "lit/decorators";
import "../../../components/ha-alert";
-import "../../../components/ha-blueprint-picker";
-import "../../../components/ha-card";
-import "../../../components/ha-circular-progress";
-import "../../../components/ha-markdown";
-import "../../../components/ha-selector/ha-selector";
-import "../../../components/ha-settings-row";
-import {
- BlueprintOrError,
- Blueprints,
- fetchBlueprints,
-} from "../../../data/blueprint";
import { BlueprintScriptConfig } from "../../../data/script";
-import { haStyle } from "../../../resources/styles";
-import { HomeAssistant } from "../../../types";
-import "../ha-config-section";
+import { fetchBlueprints } from "../../../data/blueprint";
+import { HaBlueprintGenericEditor } from "../blueprint/blueprint-generic-editor";
@customElement("blueprint-script-editor")
-export class HaBlueprintScriptEditor extends LitElement {
- @property({ attribute: false }) public hass!: HomeAssistant;
-
- @property({ type: Boolean }) public isWide = false;
-
- @property({ reflect: true, type: Boolean }) public narrow = false;
-
- @property({ type: Boolean }) public disabled = false;
-
+export class HaBlueprintScriptEditor extends HaBlueprintGenericEditor {
@property({ attribute: false }) public config!: BlueprintScriptConfig;
- @state() private _blueprints?: Blueprints;
-
- protected firstUpdated(changedProps) {
- super.firstUpdated(changedProps);
- this._getBlueprints();
- }
-
- private get _blueprint(): BlueprintOrError | undefined {
- if (!this._blueprints) {
- return undefined;
- }
- return this._blueprints[this.config.use_blueprint.path];
+ protected get _config(): BlueprintScriptConfig {
+ return this.config;
}
protected render() {
- const blueprint = this._blueprint;
return html`
${this.disabled
? html`
@@ -56,228 +23,14 @@ export class HaBlueprintScriptEditor extends LitElement {
`
: ""}
-
-
- ${this._blueprints
- ? Object.keys(this._blueprints).length
- ? html`
-
- `
- : this.hass.localize(
- "ui.panel.config.automation.editor.blueprint.no_blueprints"
- )
- : html` `}
-
- ${this.config.use_blueprint.path
- ? blueprint && "error" in blueprint
- ? html`
- There is an error in this Blueprint: ${blueprint.error}
-
`
- : html`${blueprint?.metadata.description
- ? html` `
- : ""}
- ${blueprint?.metadata?.input &&
- Object.keys(blueprint.metadata.input).length
- ? Object.entries(blueprint.metadata.input).map(
- ([key, value]) => {
- const selector = value?.selector ?? { text: undefined };
- const type = Object.keys(selector)[0];
- const enhancedSelector = [
- "action",
- "condition",
- "trigger",
- ].includes(type)
- ? {
- [type]: {
- ...selector[type],
- path: [key],
- },
- }
- : selector;
-
- return html`
- ${value?.name || key}
-
- ${html` `}
- `;
- }
- )
- : html`
- ${this.hass.localize(
- "ui.panel.config.automation.editor.blueprint.no_inputs"
- )}
-
`}`
- : ""}
-
+ ${this.renderCard()}
`;
}
- private async _getBlueprints() {
+ protected async _getBlueprints() {
this._blueprints = await fetchBlueprints(this.hass, "script");
}
-
- private _blueprintChanged(ev) {
- ev.stopPropagation();
- if (this.config.use_blueprint.path === ev.detail.value) {
- return;
- }
- fireEvent(this, "value-changed", {
- value: {
- ...this.config,
- use_blueprint: {
- path: ev.detail.value,
- },
- },
- });
- }
-
- private _inputChanged(ev) {
- ev.stopPropagation();
- const target = ev.target as any;
- const key = target.key;
- const value = ev.detail ? ev.detail.value : target.value;
- if (
- (this.config.use_blueprint.input &&
- this.config.use_blueprint.input[key] === value) ||
- (!this.config.use_blueprint.input && value === "")
- ) {
- return;
- }
- const input = { ...this.config.use_blueprint.input, [key]: value };
-
- fireEvent(this, "value-changed", {
- value: {
- ...this.config,
- use_blueprint: {
- ...this.config.use_blueprint,
- input,
- },
- },
- });
- }
-
- private _itemMoved(ev) {
- ev.stopPropagation();
- const { oldIndex, newIndex, oldPath, newPath } = ev.detail;
-
- const input = nestedArrayMove(
- this.config.use_blueprint.input,
- oldIndex,
- newIndex,
- oldPath,
- newPath
- );
-
- fireEvent(this, "value-changed", {
- value: {
- ...this.config,
- use_blueprint: {
- ...this.config.use_blueprint,
- input,
- },
- },
- });
- }
-
- private _duplicate() {
- fireEvent(this, "duplicate");
- }
-
- static get styles(): CSSResultGroup {
- return [
- haStyle,
- css`
- :host {
- display: block;
- }
- ha-card.blueprint {
- margin: 0 auto;
- }
- .padding {
- padding: 16px;
- }
- .link-button-row {
- padding: 14px;
- }
- .blueprint-picker-container {
- padding: 0 16px 16px;
- }
- ha-textfield,
- ha-blueprint-picker {
- display: block;
- }
- h3 {
- margin: 16px;
- }
- .introduction {
- margin-top: 0;
- margin-bottom: 12px;
- }
- .introduction a {
- color: var(--primary-color);
- }
- p {
- margin-bottom: 0;
- }
- .description {
- margin-bottom: 16px;
- }
- ha-settings-row {
- --paper-time-input-justify-content: flex-end;
- --settings-row-content-width: 100%;
- --settings-row-prefix-display: contents;
- border-top: 1px solid var(--divider-color);
- }
- ha-alert {
- margin-bottom: 16px;
- display: block;
- }
- ha-alert.re-order {
- border-radius: var(--ha-card-border-radius, 12px);
- overflow: hidden;
- }
- `,
- ];
- }
}
-
declare global {
interface HTMLElementTagNameMap {
"blueprint-script-editor": HaBlueprintScriptEditor;
diff --git a/src/panels/config/storage/ha-config-section-storage.ts b/src/panels/config/storage/ha-config-section-storage.ts
index 708f79e861..89b5fc7cf0 100644
--- a/src/panels/config/storage/ha-config-section-storage.ts
+++ b/src/panels/config/storage/ha-config-section-storage.ts
@@ -334,6 +334,8 @@ class HaConfigSectionStorage extends LitElement {
position: relative;
top: -10px;
right: 10px;
+ inset-inline-end: 10px;
+ inset-inline-start: initial;
}
.no-mounts {
diff --git a/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts b/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts
index a2190dbc63..6137be81b1 100644
--- a/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts
+++ b/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts
@@ -50,7 +50,9 @@ export class AssistPipelineRunDebug extends LitElement {
${this._pipelineRuns.length > 0
? html`
@@ -59,13 +61,13 @@ export class AssistPipelineRunDebug extends LitElement {
@click=${this._clearConversation}
.disabled=${!this._finished}
>
- Clear
+ ${this.hass.localize("ui.common.clear")}
- Download
+ ${this.hass.localize("ui.common.download")}
`
: ""}
@@ -81,7 +83,9 @@ export class AssistPipelineRunDebug extends LitElement {
>
- Run Text Pipeline
+ ${this.hass.localize(
+ "ui.panel.config.voice_assistants.debug.pipeline.run_text_pipeline"
+ )}
- Run Audio Pipeline
+ ${this.hass.localize(
+ "ui.panel.config.voice_assistants.debug.pipeline.run_audio_pipeline"
+ )}
- Run Audio Pipeline with Wake Word detection
+ ${this.hass.localize(
+ "ui.panel.config.voice_assistants.debug.pipeline.run_audio_with_wake"
+ )}
`
@@ -107,7 +115,9 @@ export class AssistPipelineRunDebug extends LitElement {
? html`
@@ -115,7 +125,9 @@ export class AssistPipelineRunDebug extends LitElement {
@click=${this._runTextPipeline}
.disabled=${!this._finished}
>
- Send
+ ${this.hass.localize(
+ "ui.panel.config.voice_assistants.debug.pipeline.send"
+ )}
`
: this._finished
@@ -123,14 +135,22 @@ export class AssistPipelineRunDebug extends LitElement {
"wake_word"
? html`
- Continue listening for wake word
+ ${this.hass.localize(
+ "ui.panel.config.voice_assistants.debug.pipeline.continue_listening"
+ )}
`
: html`
- Continue talking
+ ${this.hass.localize(
+ "ui.panel.config.voice_assistants.debug.pipeline.continue_talking"
+ )}
`
: html`
-
+
${this.narrow
diff --git a/src/panels/developer-tools/statistics/dialog-statistics-adjust-sum.ts b/src/panels/developer-tools/statistics/dialog-statistics-adjust-sum.ts
index 6ffa9790da..b32666bde6 100644
--- a/src/panels/developer-tools/statistics/dialog-statistics-adjust-sum.ts
+++ b/src/panels/developer-tools/statistics/dialog-statistics-adjust-sum.ts
@@ -34,6 +34,11 @@ import { HomeAssistant } from "../../../types";
import { showToast } from "../../../util/toast";
import type { DialogStatisticsAdjustSumParams } from "./show-dialog-statistics-adjust-sum";
+interface CombinedStat {
+ hour: StatisticValue | null;
+ fiveMin: StatisticValue[];
+}
+
@customElement("dialog-statistics-adjust-sum")
export class DialogStatisticsFixUnsupportedUnitMetadata extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -196,6 +201,13 @@ export class DialogStatisticsFixUnsupportedUnitMetadata extends LitElement {
@value-changed=${this._dateTimeSelectorChanged}
>
${stats}
+
{
+ this._stats5min = undefined;
+ this._statsHour = undefined;
+ const statId = this._params!.statistic.statistic_id;
+
+ // Get all the data
+ const start = new Date(0);
+ const end = new Date();
+
+ const statsHourData = await fetchStatistics(
+ this.hass,
+ start,
+ end,
+ [statId],
+ "hour"
+ );
+
+ const statsHour = statId in statsHourData ? statsHourData[statId] : [];
+ if (statsHour.length === 0) {
+ return;
+ }
+
+ const stats5MinData = await fetchStatistics(
+ this.hass,
+ start,
+ end,
+ [statId],
+ "5minute"
+ );
+
+ const stats5Min = statId in stats5MinData ? stats5MinData[statId] : [];
+ // First datapoint of 5 minute data in the history is always junk since it counts the entire sum
+ // as the change, which we don't want here.
+ stats5Min.shift();
+
+ const combinedStatsData: CombinedStat[] = [];
+ statsHour.forEach((s) => {
+ combinedStatsData.push({ hour: s, fiveMin: [] });
+ });
+
+ const lasthour: CombinedStat = { hour: null, fiveMin: [] };
+
+ let i = 0;
+ stats5Min.forEach((s) => {
+ let matched = false;
+ for (i; i < combinedStatsData.length; i++) {
+ const hour = combinedStatsData[i].hour;
+ if (hour && s.start >= hour.start && s.end <= hour.end) {
+ combinedStatsData[i].fiveMin.push(s);
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ lasthour.fiveMin.push(s);
+ }
+ });
+
+ combinedStatsData.push(lasthour);
+
+ let statsOutliers: StatisticValue[] = [];
+ let min = 0;
+ const numOutliers = 10;
+
+ // Track the top 10 values.
+ const addOutlier = (s) => {
+ const val = Math.abs(s.change ?? 0);
+ if (statsOutliers.length < numOutliers || val > min) {
+ statsOutliers.push(s);
+ statsOutliers = statsOutliers.sort(
+ (a, b) => Math.abs(b.change ?? 0) - Math.abs(a.change ?? 0)
+ );
+ statsOutliers = statsOutliers.slice(0, numOutliers);
+ min = statsOutliers[statsOutliers.length - 1].change ?? 0;
+ }
+ };
+
+ // If an hour has no five minute data, add the hour value
+ // Otherwise, add the 5 minute values and ignore the hour value
+ combinedStatsData.forEach((c) => {
+ if (c.fiveMin.length === 0 && c.hour) {
+ addOutlier(c.hour);
+ } else {
+ c.fiveMin.forEach((s) => {
+ addOutlier(s);
+ });
+ }
+ });
+
+ // Outliers are a possible mix of hour/5minute data, but the distinction
+ // is not relevant here, as long as only one array is populated.
+ this._statsHour = statsOutliers;
+ this._stats5min = [];
+ }
+
private async _fixIssue(): Promise {
const unit = getDisplayUnit(
this.hass,
diff --git a/src/panels/developer-tools/template/developer-tools-template.ts b/src/panels/developer-tools/template/developer-tools-template.ts
index 7732ad7760..e4162d3077 100644
--- a/src/panels/developer-tools/template/developer-tools-template.ts
+++ b/src/panels/developer-tools/template/developer-tools-template.ts
@@ -290,6 +290,8 @@ class HaPanelDevTemplate extends LitElement {
position: absolute;
top: 8px;
right: 8px;
+ inset-inline-end: 8px;
+ inset-inline-start: initial;
}
ha-alert {
diff --git a/src/panels/energy/ha-panel-energy.ts b/src/panels/energy/ha-panel-energy.ts
index a9462d0edb..4dd6498ae4 100644
--- a/src/panels/energy/ha-panel-energy.ts
+++ b/src/panels/energy/ha-panel-energy.ts
@@ -7,7 +7,7 @@ import {
html,
nothing,
} from "lit";
-import { mdiPencil } from "@mdi/js";
+import { mdiPencil, mdiDownload } from "@mdi/js";
import { customElement, property, state } from "lit/decorators";
import "../../components/ha-menu-button";
import "../../components/ha-list-item";
@@ -19,6 +19,18 @@ import "../lovelace/components/hui-energy-period-selector";
import { Lovelace } from "../lovelace/types";
import "../lovelace/views/hui-view";
import { navigate } from "../../common/navigate";
+import {
+ getEnergyDataCollection,
+ getEnergyGasUnit,
+ getEnergyWaterUnit,
+ GridSourceTypeEnergyPreference,
+ SolarSourceTypeEnergyPreference,
+ BatterySourceTypeEnergyPreference,
+ GasSourceTypeEnergyPreference,
+ WaterSourceTypeEnergyPreference,
+ DeviceConsumptionEnergyPreference,
+} from "../../data/energy";
+import { fileDownload } from "../../util/file_download";
const ENERGY_LOVELACE_CONFIG: LovelaceConfig = {
views: [
@@ -86,6 +98,15 @@ class PanelEnergy extends LitElement {
${this.hass!.localize("ui.panel.energy.configure")}
+
+
+
+ ${this.hass!.localize("ui.panel.energy.download_data")}
+
`
: nothing}
@@ -122,6 +143,182 @@ class PanelEnergy extends LitElement {
navigate("/config/energy?historyBack=1");
}
+ private async _dumpCSV(ev) {
+ ev.stopPropagation();
+ const energyData = getEnergyDataCollection(this.hass, {
+ key: "energy_dashboard",
+ });
+
+ if (!energyData.prefs || !energyData.state.stats) {
+ return;
+ }
+
+ const gasUnit =
+ getEnergyGasUnit(
+ this.hass,
+ energyData.prefs,
+ energyData.state.statsMetadata
+ ) || "";
+ const waterUnit = getEnergyWaterUnit(this.hass);
+ const electricUnit = "kWh";
+
+ const energy_sources = energyData.prefs.energy_sources;
+ const device_consumption = energyData.prefs.device_consumption;
+ const stats = energyData.state.stats;
+
+ const timeSet = new Set();
+ Object.values(stats).forEach((stat) => {
+ stat.forEach((datapoint) => {
+ timeSet.add(datapoint.start);
+ });
+ });
+ const times = Array.from(timeSet).sort();
+
+ const headers =
+ "entity_id,type,unit," +
+ times.map((t) => new Date(t).toISOString()).join(",") +
+ "\n";
+ const csv: string[] = [];
+ csv[0] = headers;
+
+ const processStat = function (stat: string, type: string, unit: string) {
+ let n = 0;
+ const row: string[] = [];
+ if (!stats[stat]) {
+ return;
+ }
+ row.push(stat);
+ row.push(type);
+ row.push(unit.normalize("NFKD"));
+ times.forEach((t) => {
+ if (stats[stat][n].start > t) {
+ row.push("");
+ } else if (n < stats[stat].length && stats[stat][n].start === t) {
+ row.push((stats[stat][n].change ?? "").toString());
+ n++;
+ } else {
+ row.push("");
+ }
+ });
+ csv.push(row.join(",") + "\n");
+ };
+
+ const currency = this.hass.config.currency;
+
+ const printCategory = function (
+ type: string,
+ statIds: string[],
+ unit: string,
+ costType?: string
+ ) {
+ if (statIds.length) {
+ statIds.forEach((stat) => processStat(stat, type, unit));
+ if (costType) {
+ statIds.forEach((stat) => {
+ const costStat = energyData.state.info.cost_sensors[stat];
+ if (energyData.state.info.cost_sensors[stat]) {
+ processStat(costStat, costType, currency);
+ }
+ });
+ }
+ }
+ };
+
+ const grid_consumptions: string[] = [];
+ const grid_productions: string[] = [];
+ energy_sources
+ .filter((s) => s.type === "grid")
+ .forEach((source) => {
+ source = source as GridSourceTypeEnergyPreference;
+ source.flow_from.forEach((flowFrom) => {
+ grid_consumptions.push(flowFrom.stat_energy_from);
+ });
+ source.flow_to.forEach((flowTo) => {
+ grid_productions.push(flowTo.stat_energy_to);
+ });
+ });
+
+ printCategory(
+ "grid_consumption",
+ grid_consumptions,
+ electricUnit,
+ "grid_consumption_cost"
+ );
+ printCategory(
+ "grid_return",
+ grid_productions,
+ electricUnit,
+ "grid_return_compensation"
+ );
+
+ const battery_ins: string[] = [];
+ const battery_outs: string[] = [];
+ energy_sources
+ .filter((s) => s.type === "battery")
+ .forEach((source) => {
+ source = source as BatterySourceTypeEnergyPreference;
+ battery_ins.push(source.stat_energy_to);
+ battery_outs.push(source.stat_energy_from);
+ });
+
+ printCategory("battery_in", battery_ins, electricUnit);
+ printCategory("battery_out", battery_outs, electricUnit);
+
+ const solar_productions: string[] = [];
+ energy_sources
+ .filter((s) => s.type === "solar")
+ .forEach((source) => {
+ source = source as SolarSourceTypeEnergyPreference;
+ solar_productions.push(source.stat_energy_from);
+ });
+
+ printCategory("solar_production", solar_productions, electricUnit);
+
+ const gas_consumptions: string[] = [];
+ energy_sources
+ .filter((s) => s.type === "gas")
+ .forEach((source) => {
+ source = source as GasSourceTypeEnergyPreference;
+ gas_consumptions.push(source.stat_energy_from);
+ });
+
+ printCategory(
+ "gas_consumption",
+ gas_consumptions,
+ gasUnit,
+ "gas_consumption_cost"
+ );
+
+ const water_consumptions: string[] = [];
+ energy_sources
+ .filter((s) => s.type === "water")
+ .forEach((source) => {
+ source = source as WaterSourceTypeEnergyPreference;
+ water_consumptions.push(source.stat_energy_from);
+ });
+
+ printCategory(
+ "water_consumption",
+ water_consumptions,
+ waterUnit,
+ "water_consumption_cost"
+ );
+
+ const devices: string[] = [];
+ device_consumption.forEach((source) => {
+ source = source as DeviceConsumptionEnergyPreference;
+ devices.push(source.stat_consumption);
+ });
+
+ printCategory("device_consumption", devices, electricUnit);
+
+ const blob = new Blob(csv, {
+ type: "text/csv",
+ });
+ const url = window.URL.createObjectURL(blob);
+ fileDownload(url, "energy.csv");
+ }
+
private _reloadView() {
// Force strategy to be re-run by make a copy of the view
const config = this._lovelace!.config;
diff --git a/src/panels/energy/strategies/energy-view-strategy.ts b/src/panels/energy/strategies/energy-view-strategy.ts
index 27a0a91371..d41ea668ba 100644
--- a/src/panels/energy/strategies/energy-view-strategy.ts
+++ b/src/panels/energy/strategies/energy-view-strategy.ts
@@ -154,6 +154,13 @@ export class EnergyViewStrategy extends ReactiveElement {
// Only include if we have at least 1 device in the config.
if (prefs.device_consumption.length) {
+ view.cards!.push({
+ title: hass.localize(
+ "ui.panel.energy.cards.energy_devices_detail_graph_title"
+ ),
+ type: "energy-devices-detail-graph",
+ collection_key: "energy_dashboard",
+ });
view.cards!.push({
title: hass.localize(
"ui.panel.energy.cards.energy_devices_graph_title"
diff --git a/src/panels/history/ha-panel-history.ts b/src/panels/history/ha-panel-history.ts
index dae3bae725..49797dda56 100644
--- a/src/panels/history/ha-panel-history.ts
+++ b/src/panels/history/ha-panel-history.ts
@@ -433,6 +433,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
this._statisticsHistory = computeHistory(
this.hass,
statsHistoryStates,
+ [],
this.hass.localize,
sensorNumericDeviceClasses,
true
@@ -472,6 +473,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
this._stateHistory = computeHistory(
this.hass,
history,
+ entityIds,
this.hass.localize,
sensorNumericDeviceClasses,
true
diff --git a/src/panels/lovelace/card-features/hui-fan-preset-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-fan-preset-modes-card-feature.ts
new file mode 100644
index 0000000000..b4701dab84
--- /dev/null
+++ b/src/panels/lovelace/card-features/hui-fan-preset-modes-card-feature.ts
@@ -0,0 +1,231 @@
+import { mdiTuneVariant } from "@mdi/js";
+import { HassEntity } from "home-assistant-js-websocket";
+import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
+import { customElement, property, query, state } from "lit/decorators";
+import { stopPropagation } from "../../../common/dom/stop_propagation";
+import { computeDomain } from "../../../common/entity/compute_domain";
+import { supportsFeature } from "../../../common/entity/supports-feature";
+import "../../../components/ha-attribute-icon";
+import "../../../components/ha-control-select";
+import type { ControlSelectOption } from "../../../components/ha-control-select";
+import "../../../components/ha-control-select-menu";
+import type { HaControlSelectMenu } from "../../../components/ha-control-select-menu";
+import { FanEntity, FanEntityFeature } from "../../../data/fan";
+import { UNAVAILABLE } from "../../../data/entity";
+import { HomeAssistant } from "../../../types";
+import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
+import { FanPresetModesCardFeatureConfig } from "./types";
+
+export const supportsFanPresetModesCardFeature = (stateObj: HassEntity) => {
+ const domain = computeDomain(stateObj.entity_id);
+ return (
+ domain === "fan" && supportsFeature(stateObj, FanEntityFeature.PRESET_MODE)
+ );
+};
+
+@customElement("hui-fan-preset-modes-card-feature")
+class HuiFanPresetModesCardFeature
+ extends LitElement
+ implements LovelaceCardFeature
+{
+ @property({ attribute: false }) public hass?: HomeAssistant;
+
+ @property({ attribute: false }) public stateObj?: FanEntity;
+
+ @state() private _config?: FanPresetModesCardFeatureConfig;
+
+ @state() _currentPresetMode?: string;
+
+ @query("ha-control-select-menu", true)
+ private _haSelect?: HaControlSelectMenu;
+
+ static getStubConfig(
+ _,
+ stateObj?: HassEntity
+ ): FanPresetModesCardFeatureConfig {
+ return {
+ type: "fan-preset-modes",
+ style: "dropdown",
+ preset_modes: stateObj?.attributes.preset_modes || [],
+ };
+ }
+
+ public static async getConfigElement(): Promise {
+ await import(
+ "../editor/config-elements/hui-fan-preset-modes-card-feature-editor"
+ );
+ return document.createElement("hui-fan-preset-modes-card-feature-editor");
+ }
+
+ public setConfig(config: FanPresetModesCardFeatureConfig): void {
+ if (!config) {
+ throw new Error("Invalid configuration");
+ }
+ this._config = config;
+ }
+
+ protected willUpdate(changedProp: PropertyValues): void {
+ super.willUpdate(changedProp);
+ if (changedProp.has("stateObj") && this.stateObj) {
+ this._currentPresetMode = this.stateObj.attributes.preset_mode;
+ }
+ }
+
+ protected updated(changedProps: PropertyValues) {
+ super.updated(changedProps);
+ if (this._haSelect && changedProps.has("hass")) {
+ const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
+ if (
+ this.hass &&
+ this.hass.formatEntityAttributeValue !==
+ oldHass?.formatEntityAttributeValue
+ ) {
+ this._haSelect.layoutOptions();
+ }
+ }
+ }
+
+ private async _valueChanged(ev: CustomEvent) {
+ const presetMode =
+ (ev.detail as any).value ?? ((ev.target as any).value as string);
+
+ const oldPresetMode = this.stateObj!.attributes.preset_mode;
+
+ if (presetMode === oldPresetMode) return;
+
+ this._currentPresetMode = presetMode;
+
+ try {
+ await this._setMode(presetMode);
+ } catch (err) {
+ this._currentPresetMode = oldPresetMode;
+ }
+ }
+
+ private async _setMode(mode: string) {
+ await this.hass!.callService("fan", "set_preset_mode", {
+ entity_id: this.stateObj!.entity_id,
+ preset_mode: mode,
+ });
+ }
+
+ protected render(): TemplateResult | null {
+ if (
+ !this._config ||
+ !this.hass ||
+ !this.stateObj ||
+ !supportsFanPresetModesCardFeature(this.stateObj)
+ ) {
+ return null;
+ }
+
+ const stateObj = this.stateObj;
+
+ const modes = stateObj.attributes.preset_modes || [];
+
+ const options = modes
+ .filter((mode) => (this._config!.preset_modes || []).includes(mode))
+ .map((mode) => ({
+ value: mode,
+ label: this.hass!.formatEntityAttributeValue(
+ this.stateObj!,
+ "preset_mode",
+ mode
+ ),
+ icon: html` `,
+ }));
+
+ if (this._config.style === "icons") {
+ return html`
+
+
+
+
+ `;
+ }
+
+ return html`
+
+
+ ${this._currentPresetMode
+ ? html` `
+ : html`
+
+ `}
+ ${options.map(
+ (option) => html`
+
+ ${option.icon}${option.label}
+
+ `
+ )}
+
+
+ `;
+ }
+
+ static get styles() {
+ return css`
+ ha-control-select-menu {
+ box-sizing: border-box;
+ --control-select-menu-height: 40px;
+ --control-select-menu-border-radius: 10px;
+ line-height: 1.2;
+ display: block;
+ width: 100%;
+ }
+ ha-control-select {
+ --control-select-color: var(--feature-color);
+ --control-select-padding: 0;
+ --control-select-thickness: 40px;
+ --control-select-border-radius: 10px;
+ --control-select-button-border-radius: 10px;
+ }
+ .container {
+ padding: 0 12px 12px 12px;
+ width: auto;
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-fan-preset-modes-card-feature": HuiFanPresetModesCardFeature;
+ }
+}
diff --git a/src/panels/lovelace/card-features/types.ts b/src/panels/lovelace/card-features/types.ts
index e5c4d38858..f96427b4ba 100644
--- a/src/panels/lovelace/card-features/types.ts
+++ b/src/panels/lovelace/card-features/types.ts
@@ -26,6 +26,12 @@ export interface LightColorTempCardFeatureConfig {
type: "light-color-temp";
}
+export interface FanPresetModesCardFeatureConfig {
+ type: "fan-preset-modes";
+ style?: "dropdown" | "icons";
+ preset_modes?: string[];
+}
+
export interface FanSpeedCardFeatureConfig {
type: "fan-speed";
}
@@ -123,19 +129,20 @@ export type LovelaceCardFeatureConfig =
| CoverPositionCardFeatureConfig
| CoverTiltPositionCardFeatureConfig
| CoverTiltCardFeatureConfig
+ | FanPresetModesCardFeatureConfig
| FanSpeedCardFeatureConfig
| HumidifierToggleCardFeatureConfig
| HumidifierModesCardFeatureConfig
| LawnMowerCommandsCardFeatureConfig
| LightBrightnessCardFeatureConfig
| LightColorTempCardFeatureConfig
- | VacuumCommandsCardFeatureConfig
+ | NumericInputCardFeatureConfig
+ | SelectOptionsCardFeatureConfig
| TargetHumidityCardFeatureConfig
| TargetTemperatureCardFeatureConfig
- | WaterHeaterOperationModesCardFeatureConfig
- | SelectOptionsCardFeatureConfig
- | NumericInputCardFeatureConfig
- | UpdateActionsCardFeatureConfig;
+ | UpdateActionsCardFeatureConfig
+ | VacuumCommandsCardFeatureConfig
+ | WaterHeaterOperationModesCardFeatureConfig;
export type LovelaceCardFeatureContext = {
entity_id?: string;
diff --git a/src/panels/lovelace/cards/energy/common/color.ts b/src/panels/lovelace/cards/energy/common/color.ts
new file mode 100644
index 0000000000..f9f02f3674
--- /dev/null
+++ b/src/panels/lovelace/cards/energy/common/color.ts
@@ -0,0 +1,64 @@
+import colors from "color-name";
+import {
+ hex2rgb,
+ lab2rgb,
+ rgb2hex,
+ rgb2lab,
+} from "../../../../../common/color/convert-color";
+import { labBrighten, labDarken } from "../../../../../common/color/lab";
+
+export function getEnergyColor(
+ computedStyles: CSSStyleDeclaration,
+ darkMode: boolean,
+ background: boolean,
+ compare: boolean,
+ propertyName: string,
+ idx?: number
+): string {
+ const themeIdxColor = computedStyles
+ .getPropertyValue(propertyName + "-" + idx)
+ .trim();
+
+ const themeColor =
+ themeIdxColor.length > 0
+ ? themeIdxColor
+ : computedStyles.getPropertyValue(propertyName).trim();
+
+ let hexColor;
+ if (themeColor.startsWith("#")) {
+ hexColor = themeColor;
+ } else {
+ const rgbFromColorName = colors[themeColor];
+ if (!rgbFromColorName) {
+ // We have a named color, and there's nothing in the table,
+ // so nothing further we can do with it.
+ // Compare/border/background color will all be the same.
+ return themeColor;
+ }
+ hexColor = rgb2hex(rgbFromColorName);
+ }
+
+ if (themeIdxColor.length === 0 && idx) {
+ // Brighten or darken the color based on set position.
+ // Skip if theme already provides a color for this set.
+
+ hexColor = rgb2hex(
+ lab2rgb(
+ darkMode
+ ? labBrighten(rgb2lab(hex2rgb(hexColor)), idx)
+ : labDarken(rgb2lab(hex2rgb(hexColor)), idx)
+ )
+ );
+ }
+
+ if (compare) {
+ if (background) {
+ hexColor += "32";
+ } else {
+ hexColor += "7F";
+ }
+ } else if (background) {
+ hexColor += "7F";
+ }
+ return hexColor;
+}
diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts
new file mode 100644
index 0000000000..5bd0e8ce33
--- /dev/null
+++ b/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts
@@ -0,0 +1,358 @@
+import {
+ ChartData,
+ ChartDataset,
+ ChartOptions,
+ ScatterDataPoint,
+} from "chart.js";
+import { endOfToday, startOfToday } from "date-fns/esm";
+import { HassConfig, UnsubscribeFunc } from "home-assistant-js-websocket";
+import {
+ css,
+ CSSResultGroup,
+ html,
+ LitElement,
+ nothing,
+ PropertyValues,
+} from "lit";
+import { customElement, property, state } from "lit/decorators";
+import { classMap } from "lit/directives/class-map";
+import memoizeOne from "memoize-one";
+import { getColorByIndex } from "../../../../common/color/colors";
+import { ChartDatasetExtra } from "../../../../components/chart/ha-chart-base";
+import "../../../../components/ha-card";
+import {
+ DeviceConsumptionEnergyPreference,
+ EnergyData,
+ getEnergyDataCollection,
+} from "../../../../data/energy";
+import {
+ calculateStatisticSumGrowth,
+ getStatisticLabel,
+ Statistics,
+ StatisticsMetaData,
+} from "../../../../data/recorder";
+import { FrontendLocaleData } from "../../../../data/translation";
+import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
+import { HomeAssistant } from "../../../../types";
+import { LovelaceCard } from "../../types";
+import { EnergyDevicesDetailGraphCardConfig } from "../types";
+import { hasConfigChanged } from "../../common/has-changed";
+import { getCommonOptions } from "./common/energy-chart-options";
+
+const UNIT = "kWh";
+
+@customElement("hui-energy-devices-detail-graph-card")
+export class HuiEnergyDevicesDetailGraphCard
+ extends SubscribeMixin(LitElement)
+ implements LovelaceCard
+{
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @state() private _config?: EnergyDevicesDetailGraphCardConfig;
+
+ @state() private _chartData: ChartData = { datasets: [] };
+
+ @state() private _chartDatasetExtra: ChartDatasetExtra[] = [];
+
+ @state() private _data?: EnergyData;
+
+ @state() private _start = startOfToday();
+
+ @state() private _end = endOfToday();
+
+ @state() private _compareStart?: Date;
+
+ @state() private _compareEnd?: Date;
+
+ @state() private _hiddenStats = new Set();
+
+ protected hassSubscribeRequiredHostProps = ["_config"];
+
+ public hassSubscribe(): UnsubscribeFunc[] {
+ return [
+ getEnergyDataCollection(this.hass, {
+ key: this._config?.collection_key,
+ }).subscribe((data) => {
+ this._data = data;
+ this._processStatistics();
+ }),
+ ];
+ }
+
+ public getCardSize(): Promise | number {
+ return 3;
+ }
+
+ public setConfig(config: EnergyDevicesDetailGraphCardConfig): void {
+ this._config = config;
+ }
+
+ protected shouldUpdate(changedProps: PropertyValues): boolean {
+ return (
+ hasConfigChanged(this, changedProps) ||
+ changedProps.size > 1 ||
+ !changedProps.has("hass")
+ );
+ }
+
+ protected willUpdate(changedProps: PropertyValues) {
+ if (changedProps.has("_hiddenStats") && this._data) {
+ this._processStatistics();
+ }
+ }
+
+ protected render() {
+ if (!this.hass || !this._config) {
+ return nothing;
+ }
+
+ return html`
+
+ ${this._config.title
+ ? html``
+ : ""}
+
+
+
+
+ `;
+ }
+
+ private _datasetHidden(ev) {
+ ev.stopPropagation();
+ this._hiddenStats.add(
+ this._data!.prefs.device_consumption[ev.detail.index].stat_consumption
+ );
+ this.requestUpdate("_hiddenStats");
+ }
+
+ private _datasetUnhidden(ev) {
+ ev.stopPropagation();
+ this._hiddenStats.delete(
+ this._data!.prefs.device_consumption[ev.detail.index].stat_consumption
+ );
+ this.requestUpdate("_hiddenStats");
+ }
+
+ private _createOptions = memoizeOne(
+ (
+ start: Date,
+ end: Date,
+ locale: FrontendLocaleData,
+ config: HassConfig,
+ unit?: string,
+ compareStart?: Date,
+ compareEnd?: Date
+ ): ChartOptions => {
+ const commonOptions = getCommonOptions(
+ start,
+ end,
+ locale,
+ config,
+ unit,
+ compareStart,
+ compareEnd
+ );
+
+ const options: ChartOptions = {
+ ...commonOptions,
+ interaction: {
+ mode: "nearest",
+ },
+ plugins: {
+ ...commonOptions.plugins!,
+ legend: {
+ display: true,
+ labels: {
+ usePointStyle: true,
+ },
+ },
+ },
+ };
+ return options;
+ }
+ );
+
+ private _processStatistics() {
+ const energyData = this._data!;
+ const data = energyData.stats;
+ const compareData = energyData.statsCompare;
+
+ const growthValues = {};
+ energyData.prefs.device_consumption.forEach((device) => {
+ const value =
+ device.stat_consumption in data
+ ? calculateStatisticSumGrowth(data[device.stat_consumption]) || 0
+ : 0;
+
+ growthValues[device.stat_consumption] = value;
+ });
+
+ const sorted_devices = energyData.prefs.device_consumption.map(
+ (device) => device.stat_consumption
+ );
+ sorted_devices.sort((a, b) => growthValues[b] - growthValues[a]);
+
+ const datasets: ChartDataset<"bar", ScatterDataPoint[]>[] = [];
+ const datasetExtras: ChartDatasetExtra[] = [];
+
+ datasets.push(
+ ...this._processDataSet(
+ data,
+ energyData.statsMetadata,
+ energyData.prefs.device_consumption,
+ sorted_devices
+ )
+ );
+
+ const items = datasets.length;
+ datasetExtras.push(...Array(items).fill({}));
+
+ if (compareData) {
+ // Add empty dataset to align the bars
+ datasets.push({
+ order: 0,
+ data: [],
+ });
+ datasetExtras.push({
+ show_legend: false,
+ });
+ datasets.push({
+ order: 999,
+ data: [],
+ xAxisID: "xAxisCompare",
+ });
+ datasetExtras.push({
+ show_legend: false,
+ });
+
+ datasets.push(
+ ...this._processDataSet(
+ compareData,
+ energyData.statsMetadata,
+ energyData.prefs.device_consumption,
+ sorted_devices,
+ true
+ )
+ );
+ datasetExtras.push(
+ ...Array(items).fill({ show_legend: false })
+ );
+ }
+
+ this._start = energyData.start;
+ this._end = energyData.end || endOfToday();
+
+ this._compareStart = energyData.startCompare;
+ this._compareEnd = energyData.endCompare;
+
+ this._chartData = {
+ datasets,
+ };
+ this._chartDatasetExtra = datasetExtras;
+ }
+
+ private _processDataSet(
+ statistics: Statistics,
+ statisticsMetaData: Record,
+ devices: DeviceConsumptionEnergyPreference[],
+ sorted_devices: string[],
+ compare = false
+ ) {
+ const data: ChartDataset<"bar", ScatterDataPoint[]>[] = [];
+
+ devices.forEach((source, idx) => {
+ const color = getColorByIndex(idx);
+
+ let prevStart: number | null = null;
+
+ const consumptionData: ScatterDataPoint[] = [];
+
+ // Process gas consumption data.
+ if (source.stat_consumption in statistics) {
+ const stats = statistics[source.stat_consumption];
+ let end;
+
+ for (const point of stats) {
+ if (point.change === null || point.change === undefined) {
+ continue;
+ }
+ if (prevStart === point.start) {
+ continue;
+ }
+ const date = new Date(point.start);
+ consumptionData.push({
+ x: date.getTime(),
+ y: point.change,
+ });
+ prevStart = point.start;
+ end = point.end;
+ }
+ if (consumptionData.length === 1) {
+ consumptionData.push({
+ x: end,
+ y: 0,
+ });
+ }
+ }
+
+ data.push({
+ label: getStatisticLabel(
+ this.hass,
+ source.stat_consumption,
+ statisticsMetaData[source.stat_consumption]
+ ),
+ hidden: this._hiddenStats.has(source.stat_consumption),
+ borderColor: compare ? color + "7F" : color,
+ backgroundColor: compare ? color + "32" : color + "7F",
+ data: consumptionData,
+ order: 1 + sorted_devices.indexOf(source.stat_consumption),
+ stack: "devices",
+ pointStyle: compare ? false : "circle",
+ xAxisID: compare ? "xAxisCompare" : undefined,
+ });
+ });
+ return data;
+ }
+
+ static get styles(): CSSResultGroup {
+ return css`
+ .card-header {
+ padding-bottom: 0;
+ }
+ .content {
+ padding: 16px;
+ }
+ .has-header {
+ padding-top: 0;
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-energy-devices-detail-graph-card": HuiEnergyDevicesDetailGraphCard;
+ }
+}
diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts
index 64a6b5eb84..19a69db447 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts
@@ -6,7 +6,6 @@ import {
ScatterDataPoint,
} from "chart.js";
import { getRelativePosition } from "chart.js/helpers";
-import { differenceInDays } from "date-fns/esm";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import {
css,
@@ -31,10 +30,7 @@ import "../../../../components/ha-card";
import { EnergyData, getEnergyDataCollection } from "../../../../data/energy";
import {
calculateStatisticSumGrowth,
- fetchStatistics,
getStatisticLabel,
- Statistics,
- StatisticsUnitConfiguration,
} from "../../../../data/recorder";
import { FrontendLocaleData } from "../../../../data/translation";
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
@@ -186,47 +182,8 @@ export class HuiEnergyDevicesGraphCard
);
private async _getStatistics(energyData: EnergyData): Promise {
- const dayDifference = differenceInDays(
- energyData.end || new Date(),
- energyData.start
- );
-
- const devices = energyData.prefs.device_consumption.map(
- (device) => device.stat_consumption
- );
-
- const period =
- dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour";
-
- const lengthUnit = this.hass.config.unit_system.length || "";
- const units: StatisticsUnitConfiguration = {
- energy: "kWh",
- volume: lengthUnit === "km" ? "m³" : "ft³",
- };
-
- const data = await fetchStatistics(
- this.hass,
- energyData.start,
- energyData.end,
- devices,
- period,
- units,
- ["change"]
- );
-
- let compareData: Statistics | undefined;
-
- if (energyData.startCompare && energyData.endCompare) {
- compareData = await fetchStatistics(
- this.hass,
- energyData.startCompare,
- energyData.endCompare,
- devices,
- period,
- units,
- ["change"]
- );
- }
+ const data = energyData.stats;
+ const compareData = energyData.statsCompare;
const chartData: Array>["data"]> =
[];
diff --git a/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts
index e55383015b..baf3b2a7a7 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts
@@ -17,13 +17,7 @@ import {
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
-import {
- hex2rgb,
- lab2rgb,
- rgb2hex,
- rgb2lab,
-} from "../../../../common/color/convert-color";
-import { labBrighten, labDarken } from "../../../../common/color/lab";
+import { getEnergyColor } from "./common/color";
import { formatNumber } from "../../../../common/number/format_number";
import "../../../../components/chart/ha-chart-base";
import "../../../../components/ha-card";
@@ -204,16 +198,12 @@ export class HuiEnergyGasGraphCard
const datasets: ChartDataset<"bar", ScatterDataPoint[]>[] = [];
const computedStyles = getComputedStyle(this);
- const gasColor = computedStyles
- .getPropertyValue("--energy-gas-color")
- .trim();
datasets.push(
...this._processDataSet(
energyData.stats,
energyData.statsMetadata,
gasSources,
- gasColor,
computedStyles
)
);
@@ -235,7 +225,6 @@ export class HuiEnergyGasGraphCard
energyData.statsCompare,
energyData.statsMetadata,
gasSources,
- gasColor,
computedStyles,
true
)
@@ -257,28 +246,12 @@ export class HuiEnergyGasGraphCard
statistics: Statistics,
statisticsMetaData: Record,
gasSources: GasSourceTypeEnergyPreference[],
- gasColor: string,
computedStyles: CSSStyleDeclaration,
compare = false
) {
const data: ChartDataset<"bar", ScatterDataPoint[]>[] = [];
gasSources.forEach((source, idx) => {
- let borderColor = computedStyles
- .getPropertyValue("--energy-gas-color-" + idx)
- .trim();
- if (borderColor.length === 0) {
- const modifiedColor =
- idx > 0
- ? this.hass.themes.darkMode
- ? labBrighten(rgb2lab(hex2rgb(gasColor)), idx)
- : labDarken(rgb2lab(hex2rgb(gasColor)), idx)
- : undefined;
- borderColor = modifiedColor
- ? rgb2hex(lab2rgb(modifiedColor))
- : gasColor;
- }
-
let prevStart: number | null = null;
const gasConsumptionData: ScatterDataPoint[] = [];
@@ -317,8 +290,22 @@ export class HuiEnergyGasGraphCard
source.stat_energy_from,
statisticsMetaData[source.stat_energy_from]
),
- borderColor: compare ? borderColor + "7F" : borderColor,
- backgroundColor: compare ? borderColor + "32" : borderColor + "7F",
+ borderColor: getEnergyColor(
+ computedStyles,
+ this.hass.themes.darkMode,
+ false,
+ compare,
+ "--energy-gas-color",
+ idx
+ ),
+ backgroundColor: getEnergyColor(
+ computedStyles,
+ this.hass.themes.darkMode,
+ true,
+ compare,
+ "--energy-gas-color",
+ idx
+ ),
data: gasConsumptionData,
order: 1,
stack: "gas",
diff --git a/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts
index d5f3e767d0..40d91584dc 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts
@@ -22,13 +22,7 @@ import {
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
-import {
- hex2rgb,
- lab2rgb,
- rgb2hex,
- rgb2lab,
-} from "../../../../common/color/convert-color";
-import { labBrighten, labDarken } from "../../../../common/color/lab";
+import { getEnergyColor } from "./common/color";
import { formatNumber } from "../../../../common/number/format_number";
import "../../../../components/chart/ha-chart-base";
import "../../../../components/ha-card";
@@ -226,16 +220,12 @@ export class HuiEnergySolarGraphCard
const datasets: ChartDataset<"bar" | "line">[] = [];
const computedStyles = getComputedStyle(this);
- const solarColor = computedStyles
- .getPropertyValue("--energy-solar-color")
- .trim();
datasets.push(
...this._processDataSet(
energyData.stats,
energyData.statsMetadata,
solarSources,
- solarColor,
computedStyles
)
);
@@ -257,7 +247,6 @@ export class HuiEnergySolarGraphCard
energyData.statsCompare,
energyData.statsMetadata,
solarSources,
- solarColor,
computedStyles,
true
)
@@ -292,28 +281,12 @@ export class HuiEnergySolarGraphCard
statistics: Statistics,
statisticsMetaData: Record,
solarSources: SolarSourceTypeEnergyPreference[],
- solarColor: string,
computedStyles: CSSStyleDeclaration,
compare = false
) {
const data: ChartDataset<"bar", ScatterDataPoint[]>[] = [];
solarSources.forEach((source, idx) => {
- let borderColor = computedStyles
- .getPropertyValue("--energy-solar-color-" + idx)
- .trim();
- if (borderColor.length === 0) {
- const modifiedColor =
- idx > 0
- ? this.hass.themes.darkMode
- ? labBrighten(rgb2lab(hex2rgb(solarColor)), idx)
- : labDarken(rgb2lab(hex2rgb(solarColor)), idx)
- : undefined;
- borderColor = modifiedColor
- ? rgb2hex(lab2rgb(modifiedColor))
- : solarColor;
- }
-
let prevStart: number | null = null;
const solarProductionData: ScatterDataPoint[] = [];
@@ -357,8 +330,22 @@ export class HuiEnergySolarGraphCard
),
}
),
- borderColor: compare ? borderColor + "7F" : borderColor,
- backgroundColor: compare ? borderColor + "32" : borderColor + "7F",
+ borderColor: getEnergyColor(
+ computedStyles,
+ this.hass.themes.darkMode,
+ false,
+ compare,
+ "--energy-solar-color",
+ idx
+ ),
+ backgroundColor: getEnergyColor(
+ computedStyles,
+ this.hass.themes.darkMode,
+ true,
+ compare,
+ "--energy-solar-color",
+ idx
+ ),
data: solarProductionData,
order: 1,
stack: "solar",
diff --git a/src/panels/lovelace/cards/energy/hui-energy-sources-table-card.ts b/src/panels/lovelace/cards/energy/hui-energy-sources-table-card.ts
index 2be70f203b..4373c30bd1 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-sources-table-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-sources-table-card.ts
@@ -12,14 +12,8 @@ import {
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { styleMap } from "lit/directives/style-map";
-import {
- hex2rgb,
- lab2rgb,
- rgb2hex,
- rgb2lab,
-} from "../../../../common/color/convert-color";
-import { labBrighten, labDarken } from "../../../../common/color/lab";
import { formatNumber } from "../../../../common/number/format_number";
+import { getEnergyColor } from "./common/color";
import "../../../../components/ha-card";
import {
EnergyData,
@@ -38,6 +32,16 @@ import { LovelaceCard } from "../../types";
import { EnergySourcesTableCardConfig } from "../types";
import { hasConfigChanged } from "../../common/has-changed";
+const colorPropertyMap = {
+ grid_return: "--energy-grid-return-color",
+ grid_consumption: "--energy-grid-consumption-color",
+ battery_in: "--energy-battery-in-color",
+ battery_out: "--energy-battery-out-color",
+ solar: "--energy-solar-color",
+ gas: "--energy-gas-color",
+ water: "--energy-water-color",
+};
+
@customElement("hui-energy-sources-table-card")
export class HuiEnergySourcesTableCard
extends SubscribeMixin(LitElement)
@@ -77,27 +81,6 @@ export class HuiEnergySourcesTableCard
);
}
- private _getColor(
- computedStyles: CSSStyleDeclaration,
- propertyName: string,
- baseColor: string,
- idx: number
- ): string {
- let color = computedStyles
- .getPropertyValue(propertyName + "-" + idx)
- .trim();
- if (color.length === 0) {
- const modifiedColor =
- idx > 0
- ? this.hass.themes.darkMode
- ? labBrighten(rgb2lab(hex2rgb(baseColor)), idx)
- : labDarken(rgb2lab(hex2rgb(baseColor)), idx)
- : undefined;
- color = modifiedColor ? rgb2hex(lab2rgb(modifiedColor)) : baseColor;
- }
- return color;
- }
-
protected render() {
if (!this.hass || !this._config) {
return nothing;
@@ -133,38 +116,7 @@ export class HuiEnergySourcesTableCard
const types = energySourcesByType(this._data.prefs);
- const colorPropertyMap = {
- grid_return: "--energy-grid-return-color",
- grid_consumption: "--energy-grid-consumption-color",
- battery_in: "--energy-battery-in-color",
- battery_out: "--energy-battery-out-color",
- solar: "--energy-solar-color",
- gas: "--energy-gas-color",
- water: "--energy-water-color",
- };
-
const computedStyles = getComputedStyle(this);
- const solarColor = computedStyles
- .getPropertyValue(colorPropertyMap.solar)
- .trim();
- const batteryFromColor = computedStyles
- .getPropertyValue(colorPropertyMap.battery_out)
- .trim();
- const batteryToColor = computedStyles
- .getPropertyValue(colorPropertyMap.battery_in)
- .trim();
- const returnColor = computedStyles
- .getPropertyValue(colorPropertyMap.grid_return)
- .trim();
- const consumptionColor = computedStyles
- .getPropertyValue(colorPropertyMap.grid_consumption)
- .trim();
- const gasColor = computedStyles
- .getPropertyValue(colorPropertyMap.gas)
- .trim();
- const waterColor = computedStyles
- .getPropertyValue(colorPropertyMap.water)
- .trim();
const showCosts =
types.grid?.[0].flow_from.some(
@@ -273,20 +225,27 @@ export class HuiEnergySourcesTableCard
0;
totalSolarCompare += compareEnergy;
- const color = this._getColor(
- computedStyles,
- colorPropertyMap.solar,
- solarColor,
- idx
- );
-
return html`
@@ -371,26 +330,27 @@ export class HuiEnergySourcesTableCard
0;
totalBatteryCompare += energyFromCompare - energyToCompare;
- const fromColor = this._getColor(
- computedStyles,
- colorPropertyMap.battery_out,
- batteryFromColor,
- idx
- );
- const toColor = this._getColor(
- computedStyles,
- colorPropertyMap.battery_in,
- batteryToColor,
- idx
- );
-
return html`
@@ -426,8 +386,22 @@ export class HuiEnergySourcesTableCard
@@ -534,20 +508,27 @@ export class HuiEnergySourcesTableCard
totalGridCostCompare += costCompare;
}
- const color = this._getColor(
- computedStyles,
- colorPropertyMap.grid_consumption,
- consumptionColor,
- idx
- );
-
return html`
@@ -638,20 +619,27 @@ export class HuiEnergySourcesTableCard
totalGridCostCompare += costCompare;
}
- const color = this._getColor(
- computedStyles,
- colorPropertyMap.grid_return,
- returnColor,
- idx
- );
-
return html`
@@ -794,20 +782,27 @@ export class HuiEnergySourcesTableCard
totalGasCostCompare += costCompare;
}
- const color = this._getColor(
- computedStyles,
- colorPropertyMap.gas,
- gasColor,
- idx
- );
-
return html`
@@ -945,20 +940,27 @@ export class HuiEnergySourcesTableCard
totalWaterCostCompare += costCompare;
}
- const color = this._getColor(
- computedStyles,
- colorPropertyMap.water,
- waterColor,
- idx
- );
-
return html`
diff --git a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts
index 5b28a4195b..7b7c45db80 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts
@@ -17,13 +17,7 @@ import {
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
-import {
- hex2rgb,
- lab2rgb,
- rgb2hex,
- rgb2lab,
-} from "../../../../common/color/convert-color";
-import { labBrighten, labDarken } from "../../../../common/color/lab";
+import { getEnergyColor } from "./common/color";
import { formatNumber } from "../../../../common/number/format_number";
import "../../../../components/chart/ha-chart-base";
import "../../../../components/ha-card";
@@ -41,10 +35,14 @@ import { EnergyUsageGraphCardConfig } from "../types";
import { hasConfigChanged } from "../../common/has-changed";
import { getCommonOptions } from "./common/energy-chart-options";
-interface ColorSet {
- base: string;
- overrides?: Record;
-}
+const colorPropertyMap = {
+ to_grid: "--energy-grid-return-color",
+ to_battery: "--energy-battery-in-color",
+ from_grid: "--energy-grid-consumption-color",
+ used_grid: "--energy-grid-consumption-color",
+ used_solar: "--energy-solar-color",
+ used_battery: "--energy-battery-out-color",
+};
@customElement("hui-energy-usage-graph-card")
export class HuiEnergyUsageGraphCard
@@ -263,47 +261,9 @@ export class HuiEnergyUsageGraphCard
const computedStyles = getComputedStyle(this);
- const colorPropertyMap = {
- to_grid: "--energy-grid-return-color",
- to_battery: "--energy-battery-in-color",
- from_grid: "--energy-grid-consumption-color",
- used_grid: "--energy-grid-consumption-color",
- used_solar: "--energy-solar-color",
- used_battery: "--energy-battery-out-color",
- };
-
- const colors = {
- to_grid: {
- base: computedStyles.getPropertyValue(colorPropertyMap.to_grid).trim(),
- },
- to_battery: {
- base: computedStyles
- .getPropertyValue(colorPropertyMap.to_battery)
- .trim(),
- },
- from_grid: {
- base: computedStyles
- .getPropertyValue(colorPropertyMap.from_grid)
- .trim(),
- },
- used_grid: {
- base: computedStyles
- .getPropertyValue(colorPropertyMap.used_grid)
- .trim(),
- },
- used_solar: {
- base: computedStyles
- .getPropertyValue(colorPropertyMap.used_solar)
- .trim(),
- },
- used_battery: {
- base: computedStyles
- .getPropertyValue(colorPropertyMap.used_battery)
- .trim(),
- },
- };
-
- Object.entries(colorPropertyMap).forEach(([key, colorProp]) => {
+ const colorIndices: Record> = {};
+ Object.keys(colorPropertyMap).forEach((key) => {
+ colorIndices[key] = {};
if (
key === "used_grid" ||
key === "used_solar" ||
@@ -311,15 +271,9 @@ export class HuiEnergyUsageGraphCard
) {
return;
}
- colors[key].overrides = [];
if (statIds[key]) {
Object.values(statIds[key]).forEach((id, idx) => {
- const override = computedStyles
- .getPropertyValue(colorProp + "-" + idx)
- .trim();
- if (override.length > 0) {
- colors[key].overrides[id] = override;
- }
+ colorIndices[key][id as string] = idx;
});
}
});
@@ -347,7 +301,8 @@ export class HuiEnergyUsageGraphCard
energyData.stats,
energyData.statsMetadata,
statIds,
- colors,
+ colorIndices,
+ computedStyles,
labels,
false
)
@@ -370,7 +325,8 @@ export class HuiEnergyUsageGraphCard
energyData.statsCompare,
energyData.statsMetadata,
statIds,
- colors,
+ colorIndices,
+ computedStyles,
labels,
true
)
@@ -392,14 +348,8 @@ export class HuiEnergyUsageGraphCard
to_battery?: string[] | undefined;
from_battery?: string[] | undefined;
},
- colors: {
- to_grid: ColorSet;
- to_battery: ColorSet;
- from_grid: ColorSet;
- used_grid: ColorSet;
- used_solar: ColorSet;
- used_battery: ColorSet;
- },
+ colorIndices: Record>,
+ computedStyles: CSSStyleDeclaration,
labels: {
used_grid: string;
used_solar: string;
@@ -553,19 +503,6 @@ export class HuiEnergyUsageGraphCard
Object.entries(combinedData).forEach(([type, sources]) => {
Object.entries(sources).forEach(([statId, source], idx) => {
- let borderColor = colors[type].overrides?.[statId];
- if (!borderColor) {
- const modifiedColor =
- idx > 0
- ? this.hass.themes.darkMode
- ? labBrighten(rgb2lab(hex2rgb(colors[type].base)), idx)
- : labDarken(rgb2lab(hex2rgb(colors[type].base)), idx)
- : undefined;
- borderColor = modifiedColor
- ? rgb2hex(lab2rgb(modifiedColor))
- : colors[type].base;
- }
-
const points: ScatterDataPoint[] = [];
// Process chart data.
for (const key of uniqueKeys) {
@@ -600,8 +537,22 @@ export class HuiEnergyUsageGraphCard
: type === "to_battery"
? Object.keys(combinedData).length
: idx + 2,
- borderColor: compare ? borderColor + "7F" : borderColor,
- backgroundColor: compare ? borderColor + "32" : borderColor + "7F",
+ borderColor: getEnergyColor(
+ computedStyles,
+ this.hass.themes.darkMode,
+ false,
+ compare,
+ colorPropertyMap[type],
+ colorIndices[type]?.[statId]
+ ),
+ backgroundColor: getEnergyColor(
+ computedStyles,
+ this.hass.themes.darkMode,
+ true,
+ compare,
+ colorPropertyMap[type],
+ colorIndices[type]?.[statId]
+ ),
stack: "stack",
data: points,
xAxisID: compare ? "xAxisCompare" : undefined,
diff --git a/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts
index e05d6fb665..d5011fc9cb 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts
@@ -17,13 +17,7 @@ import {
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
-import {
- hex2rgb,
- lab2rgb,
- rgb2hex,
- rgb2lab,
-} from "../../../../common/color/convert-color";
-import { labBrighten, labDarken } from "../../../../common/color/lab";
+import { getEnergyColor } from "./common/color";
import { formatNumber } from "../../../../common/number/format_number";
import "../../../../components/chart/ha-chart-base";
import "../../../../components/ha-card";
@@ -202,16 +196,12 @@ export class HuiEnergyWaterGraphCard
const datasets: ChartDataset<"bar", ScatterDataPoint[]>[] = [];
const computedStyles = getComputedStyle(this);
- const waterColor = computedStyles
- .getPropertyValue("--energy-water-color")
- .trim();
datasets.push(
...this._processDataSet(
energyData.stats,
energyData.statsMetadata,
waterSources,
- waterColor,
computedStyles
)
);
@@ -233,7 +223,6 @@ export class HuiEnergyWaterGraphCard
energyData.statsCompare,
energyData.statsMetadata,
waterSources,
- waterColor,
computedStyles,
true
)
@@ -255,28 +244,12 @@ export class HuiEnergyWaterGraphCard
statistics: Statistics,
statisticsMetaData: Record,
waterSources: WaterSourceTypeEnergyPreference[],
- waterColor: string,
computedStyles: CSSStyleDeclaration,
compare = false
) {
const data: ChartDataset<"bar", ScatterDataPoint[]>[] = [];
waterSources.forEach((source, idx) => {
- let borderColor = computedStyles
- .getPropertyValue("--energy-water-color-" + idx)
- .trim();
- if (borderColor.length === 0) {
- const modifiedColor =
- idx > 0
- ? this.hass.themes.darkMode
- ? labBrighten(rgb2lab(hex2rgb(waterColor)), idx)
- : labDarken(rgb2lab(hex2rgb(waterColor)), idx)
- : undefined;
- borderColor = modifiedColor
- ? rgb2hex(lab2rgb(modifiedColor))
- : waterColor;
- }
-
let prevStart: number | null = null;
const waterConsumptionData: ScatterDataPoint[] = [];
@@ -315,8 +288,22 @@ export class HuiEnergyWaterGraphCard
source.stat_energy_from,
statisticsMetaData[source.stat_energy_from]
),
- borderColor: compare ? borderColor + "7F" : borderColor,
- backgroundColor: compare ? borderColor + "32" : borderColor + "7F",
+ borderColor: getEnergyColor(
+ computedStyles,
+ this.hass.themes.darkMode,
+ false,
+ compare,
+ "--energy-water-color",
+ idx
+ ),
+ backgroundColor: getEnergyColor(
+ computedStyles,
+ this.hass.themes.darkMode,
+ true,
+ compare,
+ "--energy-water-color",
+ idx
+ ),
data: waterConsumptionData,
order: 1,
stack: "water",
diff --git a/src/panels/lovelace/cards/hui-button-card.ts b/src/panels/lovelace/cards/hui-button-card.ts
index d738a1be6c..3a37329b27 100644
--- a/src/panels/lovelace/cards/hui-button-card.ts
+++ b/src/panels/lovelace/cards/hui-button-card.ts
@@ -134,11 +134,7 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
private getStateColor(stateObj: HassEntity, config: ButtonCardConfig) {
const domain = stateObj ? computeStateDomain(stateObj) : undefined;
- return (
- config &&
- (config.state_color ||
- (domain === "light" && config.state_color !== false))
- );
+ return config && (config.state_color ?? domain === "light");
}
public getCardSize(): number {
@@ -147,6 +143,16 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
);
}
+ public getGridSize(): [number, number] {
+ if (
+ this._config?.show_icon &&
+ (this._config?.show_name || this._config?.show_state)
+ ) {
+ return [2, 2];
+ }
+ return [1, 1];
+ }
+
public setConfig(config: ButtonCardConfig): void {
if (config.entity && !isValidEntityId(config.entity)) {
throw new Error("Invalid entity");
diff --git a/src/panels/lovelace/cards/hui-calendar-card.ts b/src/panels/lovelace/cards/hui-calendar-card.ts
index 047118828a..1a31a6d1cf 100644
--- a/src/panels/lovelace/cards/hui-calendar-card.ts
+++ b/src/panels/lovelace/cards/hui-calendar-card.ts
@@ -69,8 +69,6 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
@state() private _narrow = false;
- @state() private _veryNarrow = false;
-
@state() private _error?: string = undefined;
private _startDate?: Date;
@@ -121,9 +119,11 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
return nothing;
}
- const views: FullCalendarView[] = this._veryNarrow
- ? ["listWeek"]
- : ["dayGridMonth", "dayGridDay", "listWeek"];
+ const views: FullCalendarView[] = [
+ "dayGridMonth",
+ "dayGridDay",
+ "listWeek",
+ ];
return html`
@@ -206,7 +206,6 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
return;
}
this._narrow = card.offsetWidth < 870;
- this._veryNarrow = card.offsetWidth < 350;
}
private async _attachObserver(): Promise {
diff --git a/src/panels/lovelace/cards/hui-entities-card.ts b/src/panels/lovelace/cards/hui-entities-card.ts
index 3d5b46449e..4fb12c4661 100644
--- a/src/panels/lovelace/cards/hui-entities-card.ts
+++ b/src/panels/lovelace/cards/hui-entities-card.ts
@@ -297,9 +297,9 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
private renderEntity(entityConf: LovelaceRowConfig): TemplateResult {
const element = createRowElement(
(!("type" in entityConf) || entityConf.type === "conditional") &&
- this._config!.state_color
+ "state_color" in this._config!
? ({
- state_color: true,
+ state_color: this._config.state_color,
...(entityConf as EntityConfig),
} as EntityConfig)
: entityConf
diff --git a/src/panels/lovelace/cards/hui-entity-card.ts b/src/panels/lovelace/cards/hui-entity-card.ts
index fd1b63e13e..e6366cd28b 100644
--- a/src/panels/lovelace/cards/hui-entity-card.ts
+++ b/src/panels/lovelace/cards/hui-entity-card.ts
@@ -75,11 +75,7 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
private getStateColor(stateObj: HassEntity, config: EntityCardConfig) {
const domain = stateObj ? computeStateDomain(stateObj) : undefined;
- return (
- config &&
- (config.state_color ||
- (domain === "light" && config.state_color !== false))
- );
+ return config && (config.state_color ?? domain === "light");
}
public setConfig(config: EntityCardConfig): void {
diff --git a/src/panels/lovelace/cards/hui-glance-card.ts b/src/panels/lovelace/cards/hui-glance-card.ts
index d48fb68cfe..8217da7501 100644
--- a/src/panels/lovelace/cards/hui-glance-card.ts
+++ b/src/panels/lovelace/cards/hui-glance-card.ts
@@ -89,12 +89,12 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
state_color: true,
...config,
};
- const entities = processConfigEntities(
- config.entities
- ).map((entityConf) => ({
- hold_action: { action: "more-info" } as MoreInfoActionConfig,
- ...entityConf,
- }));
+ const entities = processConfigEntities(config.entities).map(
+ (entityConf) => ({
+ hold_action: { action: "more-info" } as MoreInfoActionConfig,
+ ...entityConf,
+ })
+ );
for (const entity of entities) {
if (
@@ -237,7 +237,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
`;
}
- private renderEntity(entityConf): TemplateResult {
+ private renderEntity(entityConf: GlanceConfigEntity): TemplateResult {
const stateObj = this.hass!.states[entityConf.entity];
if (!stateObj) {
@@ -294,8 +294,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
.stateObj=${stateObj}
.overrideIcon=${entityConf.icon}
.overrideImage=${entityConf.image}
- .stateColor=${(entityConf.state_color === false ||
- entityConf.state_color) ??
+ .stateColor=${entityConf.state_color ??
this._config!.state_color}
>
`
diff --git a/src/panels/lovelace/cards/hui-history-graph-card.ts b/src/panels/lovelace/cards/hui-history-graph-card.ts
index 1229ff7190..d8af4508b7 100644
--- a/src/panels/lovelace/cards/hui-history-graph-card.ts
+++ b/src/panels/lovelace/cards/hui-history-graph-card.ts
@@ -120,6 +120,7 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
this._stateHistory = computeHistory(
this.hass!,
combinedHistory,
+ this._entityIds,
this.hass!.localize,
sensorNumericDeviceClasses,
this._config?.split_device_classes
diff --git a/src/panels/lovelace/cards/hui-horizontal-stack-card.ts b/src/panels/lovelace/cards/hui-horizontal-stack-card.ts
index 83a1c9ae08..502e54db4d 100644
--- a/src/panels/lovelace/cards/hui-horizontal-stack-card.ts
+++ b/src/panels/lovelace/cards/hui-horizontal-stack-card.ts
@@ -28,27 +28,12 @@ export class HuiHorizontalStackCard extends HuiStackCard {
#root {
display: flex;
height: 100%;
+ gap: var(--horizontal-stack-card-gap, var(--stack-card-gap, 8px));
}
#root > * {
flex: 1 1 0;
- margin: var(
- --horizontal-stack-card-margin,
- var(--stack-card-margin, 0 4px)
- );
min-width: 0;
}
- #root[dir="ltr"] > *:first-child {
- margin-left: 0;
- }
- #root[dir="ltr"] > *:last-child {
- margin-right: 0;
- }
- #root[dir="rtl"] > *:first-child {
- margin-right: 0;
- }
- #root[dir="rtl"] > *:last-child {
- margin-left: 0;
- }
`,
];
}
diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts
index 7d5a1d8cc3..d28d0f612f 100644
--- a/src/panels/lovelace/cards/hui-media-control-card.ts
+++ b/src/panels/lovelace/cards/hui-media-control-card.ts
@@ -726,6 +726,8 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
position: absolute;
right: 4px;
--mdc-icon-size: 24px;
+ inset-inline-end: 4px;
+ inset-inline-start: initial;
}
.top-info {
diff --git a/src/panels/lovelace/cards/hui-sensor-card.ts b/src/panels/lovelace/cards/hui-sensor-card.ts
index ee7937e544..709a6591d9 100644
--- a/src/panels/lovelace/cards/hui-sensor-card.ts
+++ b/src/panels/lovelace/cards/hui-sensor-card.ts
@@ -72,6 +72,10 @@ class HuiSensorCard extends HuiEntityCard {
super.setConfig(entityCardConfig);
}
+ public getGridSize(): [number, number] {
+ return [2, 2];
+ }
+
static get styles(): CSSResultGroup {
return [
HuiEntityCard.styles,
diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts
index b1c279091a..1d56cc66bd 100644
--- a/src/panels/lovelace/cards/hui-tile-card.ts
+++ b/src/panels/lovelace/cards/hui-tile-card.ts
@@ -117,7 +117,23 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
}
public getCardSize(): number {
- return 1;
+ return (
+ 1 +
+ (this._config?.vertical ? 1 : 0) +
+ (this._config?.features?.length || 0)
+ );
+ }
+
+ public getGridSize(): [number, number] {
+ const width = 2;
+ let height = 1;
+ if (this._config?.features?.length) {
+ height += Math.ceil((this._config.features.length * 2) / 3);
+ }
+ if (this._config?.vertical) {
+ height++;
+ }
+ return [width, height];
}
private _handleAction(ev: ActionHandlerEvent) {
@@ -437,12 +453,16 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
.secondary=${localizedState}
>
-
+ ${this._config.features
+ ? html`
+
+ `
+ : nothing}
`;
}
@@ -465,6 +485,9 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
transition:
box-shadow 180ms ease-in-out,
border-color 180ms ease-in-out;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
}
ha-card.active {
--tile-color: var(--state-icon-color);
diff --git a/src/panels/lovelace/cards/hui-todo-list-card.ts b/src/panels/lovelace/cards/hui-todo-list-card.ts
index 5094ea3d73..bed42344a7 100644
--- a/src/panels/lovelace/cards/hui-todo-list-card.ts
+++ b/src/panels/lovelace/cards/hui-todo-list-card.ts
@@ -732,6 +732,8 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
.deleteItemButton {
position: relative;
left: 8px;
+ inset-inline-start: 8px;
+ inset-inline-end: initial;
}
ha-textfield {
diff --git a/src/panels/lovelace/cards/hui-vertical-stack-card.ts b/src/panels/lovelace/cards/hui-vertical-stack-card.ts
index e4915feea8..f03b4524d4 100644
--- a/src/panels/lovelace/cards/hui-vertical-stack-card.ts
+++ b/src/panels/lovelace/cards/hui-vertical-stack-card.ts
@@ -27,18 +27,7 @@ class HuiVerticalStackCard extends HuiStackCard {
display: flex;
flex-direction: column;
height: 100%;
- }
- #root > * {
- margin: var(
- --vertical-stack-card-margin,
- var(--stack-card-margin, 4px 0)
- );
- }
- #root > *:first-child {
- margin-top: 0;
- }
- #root > *:last-child {
- margin-bottom: 0;
+ gap: var(--vertical-stack-card-gap, var(--stack-card-gap, 8px));
}
`,
];
diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts
index d9a26be158..9c353c02b6 100644
--- a/src/panels/lovelace/cards/types.ts
+++ b/src/panels/lovelace/cards/types.ts
@@ -4,8 +4,10 @@ import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
import { Statistic, StatisticType } from "../../../data/recorder";
import { ForecastType } from "../../../data/weather";
import { FullCalendarView, TranslationDict } from "../../../types";
+import { LovelaceCardFeatureConfig } from "../card-features/types";
import { Condition, LegacyCondition } from "../common/validate-condition";
import { HuiImage } from "../components/hui-image";
+import { TimestampRenderingFormat } from "../components/types";
import { LovelaceElementConfig } from "../elements/types";
import {
EntityConfig,
@@ -13,7 +15,6 @@ import {
LovelaceRowConfig,
} from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
-import { LovelaceCardFeatureConfig } from "../card-features/types";
export type AlarmPanelCardConfigState =
| "arm_away"
@@ -159,6 +160,13 @@ export interface EnergyDevicesGraphCardConfig extends LovelaceCardConfig {
max_devices?: number;
}
+export interface EnergyDevicesDetailGraphCardConfig extends LovelaceCardConfig {
+ type: "energy-devices-detail-graph";
+ title?: string;
+ collection_key?: string;
+ max_devices?: number;
+}
+
export interface EnergySourcesTableCardConfig extends LovelaceCardConfig {
type: "energy-sources-table";
title?: string;
@@ -245,6 +253,7 @@ export interface GlanceConfigEntity extends ConfigEntity {
image?: string;
show_state?: boolean;
state_color?: boolean;
+ format: TimestampRenderingFormat;
}
export interface GlanceCardConfig extends LovelaceCardConfig {
@@ -253,7 +262,7 @@ export interface GlanceCardConfig extends LovelaceCardConfig {
show_icon?: boolean;
title?: string;
theme?: string;
- entities: Array;
+ entities: (string | GlanceConfigEntity)[];
columns?: number;
state_color?: boolean;
}
@@ -538,7 +547,7 @@ export interface TileCardConfig extends LovelaceCardConfig {
state_content?: string | string[];
icon?: string;
color?: string;
- show_entity_picture?: string;
+ show_entity_picture?: boolean;
vertical?: boolean;
tap_action?: ActionConfig;
hold_action?: ActionConfig;
diff --git a/src/panels/lovelace/common/generate-lovelace-config.ts b/src/panels/lovelace/common/generate-lovelace-config.ts
index 2b5437a93d..c609f66dbd 100644
--- a/src/panels/lovelace/common/generate-lovelace-config.ts
+++ b/src/panels/lovelace/common/generate-lovelace-config.ts
@@ -8,12 +8,14 @@ import { stripPrefixFromEntityName } from "../../../common/entity/strip_prefix_f
import { stringCompare } from "../../../common/string/compare";
import { LocalizeFunc } from "../../../common/translations/localize";
import type { AreaFilterValue } from "../../../components/ha-area-filter";
+import { areaCompare } from "../../../data/area_registry";
import {
EnergyPreferences,
GridSourceTypeEnergyPreference,
} from "../../../data/energy";
import { domainToName } from "../../../data/integration";
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import { computeUserInitials } from "../../../data/user";
import { HomeAssistant } from "../../../types";
@@ -25,10 +27,10 @@ import {
PictureCardConfig,
PictureEntityCardConfig,
ThermostatCardConfig,
+ TileCardConfig,
} from "../cards/types";
import { EntityConfig } from "../entity-rows/types";
import { ButtonsHeaderFooterConfig } from "../header-footer/types";
-import { areaCompare } from "../../../data/area_registry";
const HIDE_DOMAIN = new Set([
"automation",
@@ -100,6 +102,24 @@ const splitByAreaDevice = (
};
};
+export const computeSection = (
+ entityIds: string[],
+ sectionOptions?: Partial
+): LovelaceSectionConfig => ({
+ type: "grid",
+ cards: entityIds.map(
+ (entity) =>
+ ({
+ type: "tile",
+ entity,
+ show_entity_picture: ["person", "camera", "image"].includes(
+ computeDomain(entity)
+ ),
+ }) as TileCardConfig
+ ),
+ ...sectionOptions,
+});
+
export const computeCards = (
states: HassEntities,
entityIds: string[],
diff --git a/src/panels/lovelace/components/hui-card-edit-mode.ts b/src/panels/lovelace/components/hui-card-edit-mode.ts
new file mode 100644
index 0000000000..bae22490ba
--- /dev/null
+++ b/src/panels/lovelace/components/hui-card-edit-mode.ts
@@ -0,0 +1,303 @@
+import "@material/mwc-button";
+import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
+import {
+ mdiContentCopy,
+ mdiContentCut,
+ mdiContentDuplicate,
+ mdiDelete,
+ mdiDotsVertical,
+ mdiPencil,
+} from "@mdi/js";
+import deepClone from "deep-clone-simple";
+import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import { classMap } from "lit/directives/class-map";
+import { storage } from "../../../common/decorators/storage";
+import { fireEvent } from "../../../common/dom/fire_event";
+import "../../../components/ha-button-menu";
+import "../../../components/ha-icon-button";
+import "../../../components/ha-list-item";
+import "../../../components/ha-svg-icon";
+import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import { haStyle } from "../../../resources/styles";
+import { HomeAssistant } from "../../../types";
+import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
+import {
+ LovelaceCardPath,
+ findLovelaceCards,
+ getLovelaceContainerPath,
+ parseLovelaceCardPath,
+} from "../editor/lovelace-path";
+import { Lovelace } from "../types";
+
+@customElement("hui-card-edit-mode")
+export class HuiCardEditMode extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false }) public lovelace!: Lovelace;
+
+ @property({ type: Array }) public path!: LovelaceCardPath;
+
+ @property({ type: Boolean }) public hiddenOverlay = false;
+
+ @state()
+ public _menuOpened: boolean = false;
+
+ @state()
+ public _hover: boolean = false;
+
+ @state()
+ public _focused: boolean = false;
+
+ @storage({
+ key: "lovelaceClipboard",
+ state: false,
+ subscribe: false,
+ storage: "sessionStorage",
+ })
+ protected _clipboard?: LovelaceCardConfig;
+
+ private get _cards() {
+ const containerPath = getLovelaceContainerPath(this.path!);
+ return findLovelaceCards(this.lovelace!.config, containerPath)!;
+ }
+
+ private _touchStarted = false;
+
+ protected firstUpdated(): void {
+ this.addEventListener("focus", () => {
+ this._focused = true;
+ });
+ this.addEventListener("blur", () => {
+ this._focused = false;
+ });
+ this.addEventListener("touchstart", () => {
+ this._touchStarted = true;
+ });
+ this.addEventListener("touchend", () => {
+ setTimeout(() => {
+ this._touchStarted = false;
+ }, 10);
+ });
+ this.addEventListener("mouseenter", () => {
+ if (this._touchStarted) return;
+ this._hover = true;
+ });
+ this.addEventListener("mouseout", () => {
+ this._hover = false;
+ });
+ this.addEventListener("click", () => {
+ this._hover = true;
+ document.addEventListener("click", this._documentClicked);
+ });
+ }
+
+ disconnectedCallback(): void {
+ super.disconnectedCallback();
+ document.removeEventListener("click", this._documentClicked);
+ }
+
+ _documentClicked = (ev) => {
+ this._hover = ev.composedPath().includes(this);
+ document.removeEventListener("click", this._documentClicked);
+ };
+
+ protected render(): TemplateResult {
+ const showOverlay =
+ (this._hover || this._menuOpened || this._focused) && !this.hiddenOverlay;
+
+ return html`
+
+
+
+
+
+
+
+
+ ${this.hass.localize(
+ "ui.panel.lovelace.editor.edit_card.duplicate"
+ )}
+
+
+
+ ${this.hass.localize("ui.panel.lovelace.editor.edit_card.copy")}
+
+
+
+ ${this.hass.localize("ui.panel.lovelace.editor.edit_card.cut")}
+
+
+
+ ${this.hass.localize("ui.panel.lovelace.editor.edit_card.delete")}
+
+
+
+
+ `;
+ }
+
+ private _handleOpened() {
+ this._menuOpened = true;
+ }
+
+ private _handleClosed() {
+ this._menuOpened = false;
+ }
+
+ private _handleAction(ev: CustomEvent) {
+ switch (ev.detail.index) {
+ case 0:
+ this._duplicateCard();
+ break;
+ case 1:
+ this._copyCard();
+ break;
+ case 2:
+ this._cutCard();
+ break;
+ case 3:
+ this._deleteCard(true);
+ break;
+ }
+ }
+
+ private _duplicateCard(): void {
+ const { cardIndex } = parseLovelaceCardPath(this.path!);
+ const containerPath = getLovelaceContainerPath(this.path!);
+ const cardConfig = this._cards![cardIndex];
+ showEditCardDialog(this, {
+ lovelaceConfig: this.lovelace!.config,
+ saveConfig: this.lovelace!.saveConfig,
+ path: containerPath,
+ cardConfig,
+ });
+ }
+
+ private _editCard(ev): void {
+ if (ev.defaultPrevented) {
+ return;
+ }
+ if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
+ return;
+ }
+ ev.preventDefault();
+ ev.stopPropagation();
+ fireEvent(this, "ll-edit-card", { path: this.path! });
+ }
+
+ private _cutCard(): void {
+ this._copyCard();
+ this._deleteCard(false);
+ }
+
+ private _copyCard(): void {
+ const { cardIndex } = parseLovelaceCardPath(this.path!);
+ const cardConfig = this._cards[cardIndex];
+ this._clipboard = deepClone(cardConfig);
+ }
+
+ private _deleteCard(confirm: boolean): void {
+ fireEvent(this, "ll-delete-card", { path: this.path!, confirm });
+ }
+
+ static get styles(): CSSResultGroup {
+ return [
+ haStyle,
+ css`
+ .card-overlay {
+ position: absolute;
+ opacity: 0;
+ pointer-events: none;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: opacity 180ms ease-in-out;
+ }
+
+ .card-overlay.visible {
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ .card-wrapper {
+ position: relative;
+ height: 100%;
+ z-index: 0;
+ }
+
+ .edit {
+ outline: none !important;
+ cursor: pointer;
+ position: absolute;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: var(--ha-card-border-radius, 12px);
+ z-index: 0;
+ }
+ .edit-overlay {
+ position: absolute;
+ inset: 0;
+ opacity: 0.8;
+ background-color: var(--primary-background-color);
+ border: 1px solid var(--divider-color);
+ border-radius: var(--ha-card-border-radius, 12px);
+ z-index: 0;
+ }
+ .edit ha-svg-icon {
+ display: flex;
+ position: relative;
+ color: var(--primary-text-color);
+ border-radius: 50%;
+ padding: 12px;
+ background: var(--secondary-background-color);
+ --mdc-icon-size: 24px;
+ }
+ .more {
+ position: absolute;
+ right: -6px;
+ top: -6px;
+ }
+ .more ha-icon-button {
+ cursor: pointer;
+ border-radius: 50%;
+ background: var(--secondary-background-color);
+ --mdc-icon-button-size: 32px;
+ --mdc-icon-size: 20px;
+ }
+ `,
+ ];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-card-edit-mode": HuiCardEditMode;
+ }
+}
diff --git a/src/panels/lovelace/components/hui-card-options.ts b/src/panels/lovelace/components/hui-card-options.ts
index 7f59aaf3e9..ec444bb954 100644
--- a/src/panels/lovelace/components/hui-card-options.ts
+++ b/src/panels/lovelace/components/hui-card-options.ts
@@ -28,7 +28,6 @@ import "../../../components/ha-icon-button";
import "../../../components/ha-list-item";
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
import { saveConfig } from "../../../data/lovelace/config/types";
-import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import {
showAlertDialog,
showPromptDialog,
@@ -41,10 +40,15 @@ import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog"
import {
addCard,
deleteCard,
- moveCard,
- moveCardToPosition,
- swapCard,
+ moveCardToContainer,
+ moveCardToIndex,
} from "../editor/config-util";
+import {
+ LovelaceCardPath,
+ findLovelaceCards,
+ getLovelaceContainerPath,
+ parseLovelaceCardPath,
+} from "../editor/lovelace-path";
import { showSelectViewDialog } from "../editor/select-view/show-select-view-dialog";
import { Lovelace, LovelaceCard } from "../types";
@@ -54,7 +58,7 @@ export class HuiCardOptions extends LitElement {
@property({ attribute: false }) public lovelace?: Lovelace;
- @property({ type: Array }) public path?: [number, number];
+ @property({ type: Array }) public path?: LovelaceCardPath;
@queryAssignedNodes() private _assignedNodes?: NodeListOf;
@@ -76,17 +80,21 @@ export class HuiCardOptions extends LitElement {
if (!changedProps.has("path") || !this.path) {
return;
}
+ const { viewIndex } = parseLovelaceCardPath(this.path);
this.classList.toggle(
"panel",
- this.lovelace!.config.views[this.path![0]].panel
+ this.lovelace!.config.views[viewIndex].panel
);
}
- private get _currentView() {
- return this.lovelace!.config.views[this.path![0]] as LovelaceViewConfig;
+ private get _cards() {
+ const containerPath = getLovelaceContainerPath(this.path!);
+ return findLovelaceCards(this.lovelace!.config, containerPath)!;
}
protected render(): TemplateResult {
+ const { cardIndex } = parseLovelaceCardPath(this.path!);
+
return html`
@@ -107,7 +115,7 @@ export class HuiCardOptions extends LitElement {
.path=${mdiMinus}
class="move-arrow"
@click=${this._decreaseCardPosiion}
- ?disabled=${this.path![1] === 0}
+ ?disabled=${cardIndex === 0}
>
- ${this.path![1] + 1}
+ ${cardIndex + 1}
`
: nothing}
@@ -271,13 +278,14 @@ export class HuiCardOptions extends LitElement {
}
private _duplicateCard(): void {
- const path = this.path!;
- const cardConfig = this._currentView.cards![path[1]];
+ const { cardIndex } = parseLovelaceCardPath(this.path!);
+ const containerPath = getLovelaceContainerPath(this.path!);
+ const cardConfig = this._cards![cardIndex];
showEditCardDialog(this, {
lovelaceConfig: this.lovelace!.config,
- cardConfig,
saveConfig: this.lovelace!.saveConfig,
- path: [path[0]],
+ path: containerPath,
+ cardConfig,
});
}
@@ -291,30 +299,29 @@ export class HuiCardOptions extends LitElement {
}
private _copyCard(): void {
- const cardConfig = this._currentView.cards![this.path![1]];
+ const { cardIndex } = parseLovelaceCardPath(this.path!);
+ const cardConfig = this._cards[cardIndex];
this._clipboard = deepClone(cardConfig);
}
private _decreaseCardPosiion(): void {
const lovelace = this.lovelace!;
const path = this.path!;
- lovelace.saveConfig(
- swapCard(lovelace.config, path, [path[0], path[1] - 1])
- );
+ const { cardIndex } = parseLovelaceCardPath(path);
+ lovelace.saveConfig(moveCardToIndex(lovelace.config, path, cardIndex - 1));
}
private _increaseCardPosition(): void {
const lovelace = this.lovelace!;
const path = this.path!;
- lovelace.saveConfig(
- swapCard(lovelace.config, path, [path[0], path[1] + 1])
- );
+ const { cardIndex } = parseLovelaceCardPath(path);
+ lovelace.saveConfig(moveCardToIndex(lovelace.config, path, cardIndex + 1));
}
private async _changeCardPosition(): Promise {
const lovelace = this.lovelace!;
const path = this.path!;
-
+ const { cardIndex } = parseLovelaceCardPath(path);
const positionString = await showPromptDialog(this, {
title: this.hass!.localize(
"ui.panel.lovelace.editor.change_position.title"
@@ -324,7 +331,7 @@ export class HuiCardOptions extends LitElement {
),
inputType: "number",
inputMin: "1",
- placeholder: String(path[1] + 1),
+ placeholder: String(cardIndex + 1),
});
if (!positionString) return;
@@ -333,7 +340,8 @@ export class HuiCardOptions extends LitElement {
if (isNaN(position)) return;
- lovelace.saveConfig(moveCardToPosition(lovelace.config, path, position));
+ const newIndex = position - 1;
+ lovelace.saveConfig(moveCardToIndex(lovelace.config, path, newIndex));
}
private _moveCard(): void {
@@ -345,20 +353,17 @@ export class HuiCardOptions extends LitElement {
viewSelectedCallback: async (urlPath, selectedDashConfig, viewIndex) => {
if (urlPath === this.lovelace!.urlPath) {
this.lovelace!.saveConfig(
- moveCard(this.lovelace!.config, this.path!, [viewIndex])
+ moveCardToContainer(this.lovelace!.config, this.path!, [viewIndex])
);
showSaveSuccessToast(this, this.hass!);
return;
}
try {
+ const { cardIndex } = parseLovelaceCardPath(this.path!);
await saveConfig(
this.hass!,
urlPath,
- addCard(
- selectedDashConfig,
- [viewIndex],
- this._currentView.cards![this.path![1]]
- )
+ addCard(selectedDashConfig, [viewIndex], this._cards[cardIndex])
);
this.lovelace!.saveConfig(
deleteCard(this.lovelace!.config, this.path!)
diff --git a/src/panels/lovelace/create-element/create-card-element.ts b/src/panels/lovelace/create-element/create-card-element.ts
index 1884c79cc1..4a9a02fd67 100644
--- a/src/panels/lovelace/create-element/create-card-element.ts
+++ b/src/panels/lovelace/create-element/create-card-element.ts
@@ -24,6 +24,7 @@ const ALWAYS_LOADED_TYPES = new Set([
"entity-button",
"glance",
"grid",
+ "section",
"light",
"sensor",
"thermostat",
@@ -44,6 +45,8 @@ const LAZY_LOAD_TYPES = {
import("../cards/energy/hui-energy-date-selection-card"),
"energy-devices-graph": () =>
import("../cards/energy/hui-energy-devices-graph-card"),
+ "energy-devices-detail-graph": () =>
+ import("../cards/energy/hui-energy-devices-detail-graph-card"),
"energy-distribution": () =>
import("../cards/energy/hui-energy-distribution-card"),
"energy-gas-graph": () => import("../cards/energy/hui-energy-gas-graph-card"),
diff --git a/src/panels/lovelace/create-element/create-card-feature-element.ts b/src/panels/lovelace/create-element/create-card-feature-element.ts
index 5508221430..8aec1360e3 100644
--- a/src/panels/lovelace/create-element/create-card-feature-element.ts
+++ b/src/panels/lovelace/create-element/create-card-feature-element.ts
@@ -6,6 +6,7 @@ import "../card-features/hui-cover-open-close-card-feature";
import "../card-features/hui-cover-position-card-feature";
import "../card-features/hui-cover-tilt-card-feature";
import "../card-features/hui-cover-tilt-position-card-feature";
+import "../card-features/hui-fan-preset-modes-card-feature";
import "../card-features/hui-fan-speed-card-feature";
import "../card-features/hui-humidifier-modes-card-feature";
import "../card-features/hui-humidifier-toggle-card-feature";
@@ -16,9 +17,9 @@ import "../card-features/hui-numeric-input-card-feature";
import "../card-features/hui-select-options-card-feature";
import "../card-features/hui-target-temperature-card-feature";
import "../card-features/hui-target-humidity-card-feature";
+import "../card-features/hui-update-actions-card-feature";
import "../card-features/hui-vacuum-commands-card-feature";
import "../card-features/hui-water-heater-operation-modes-card-feature";
-import "../card-features/hui-update-actions-card-feature";
import { LovelaceCardFeatureConfig } from "../card-features/types";
import {
@@ -35,6 +36,7 @@ const TYPES: Set = new Set([
"cover-position",
"cover-tilt-position",
"cover-tilt",
+ "fan-preset-modes",
"fan-speed",
"humidifier-modes",
"humidifier-toggle",
@@ -45,9 +47,9 @@ const TYPES: Set = new Set([
"select-options",
"target-humidity",
"target-temperature",
+ "update-actions",
"vacuum-commands",
"water-heater-operation-modes",
- "update-actions",
]);
export const createCardFeatureElement = (config: LovelaceCardFeatureConfig) =>
diff --git a/src/panels/lovelace/create-element/create-element-base.ts b/src/panels/lovelace/create-element/create-element-base.ts
index d6d4c8d53f..48bf11bef9 100644
--- a/src/panels/lovelace/create-element/create-element-base.ts
+++ b/src/panels/lovelace/create-element/create-element-base.ts
@@ -1,27 +1,31 @@
import { fireEvent } from "../../../common/dom/fire_event";
-import { LovelaceViewElement } from "../../../data/lovelace";
+import {
+ LovelaceSectionElement,
+ LovelaceViewElement,
+} from "../../../data/lovelace";
import { LovelaceBadgeConfig } from "../../../data/lovelace/config/badge";
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import {
isCustomType,
stripCustomPrefix,
} from "../../../data/lovelace_custom_cards";
+import { LovelaceCardFeatureConfig } from "../card-features/types";
import type { HuiErrorCard } from "../cards/hui-error-card";
import type { ErrorCardConfig } from "../cards/types";
import { LovelaceElement, LovelaceElementConfig } from "../elements/types";
import { LovelaceRow, LovelaceRowConfig } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
-import { LovelaceCardFeatureConfig } from "../card-features/types";
import {
LovelaceBadge,
LovelaceCard,
LovelaceCardConstructor,
+ LovelaceCardFeature,
+ LovelaceCardFeatureConstructor,
LovelaceHeaderFooter,
LovelaceHeaderFooterConstructor,
LovelaceRowConstructor,
- LovelaceCardFeature,
- LovelaceCardFeatureConstructor,
} from "../types";
const TIMEOUT = 2000;
@@ -62,6 +66,11 @@ interface CreateElementConfigTypes {
element: LovelaceCardFeature;
constructor: LovelaceCardFeatureConstructor;
};
+ section: {
+ config: LovelaceSectionConfig;
+ element: LovelaceSectionElement;
+ constructor: unknown;
+ };
}
export const createErrorCardElement = (config: ErrorCardConfig) => {
diff --git a/src/panels/lovelace/create-element/create-section-element.ts b/src/panels/lovelace/create-element/create-section-element.ts
new file mode 100644
index 0000000000..7b63d2742e
--- /dev/null
+++ b/src/panels/lovelace/create-element/create-section-element.ts
@@ -0,0 +1,19 @@
+import { LovelaceSectionElement } from "../../../data/lovelace";
+import { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
+import { HuiErrorCard } from "../cards/hui-error-card";
+import "../sections/hui-grid-section";
+import { createLovelaceElement } from "./create-element-base";
+
+const ALWAYS_LOADED_LAYOUTS = new Set(["grid"]);
+
+const LAZY_LOAD_LAYOUTS = {};
+
+export const createSectionElement = (
+ config: LovelaceSectionConfig
+): LovelaceSectionElement | HuiErrorCard =>
+ createLovelaceElement(
+ "section",
+ config,
+ ALWAYS_LOADED_LAYOUTS,
+ LAZY_LOAD_LAYOUTS
+ );
diff --git a/src/panels/lovelace/create-element/create-view-element.ts b/src/panels/lovelace/create-element/create-view-element.ts
index 158cf2da31..65bd3e30b2 100644
--- a/src/panels/lovelace/create-element/create-view-element.ts
+++ b/src/panels/lovelace/create-element/create-view-element.ts
@@ -9,6 +9,7 @@ const ALWAYS_LOADED_LAYOUTS = new Set(["masonry"]);
const LAZY_LOAD_LAYOUTS = {
panel: () => import("../views/hui-panel-view"),
sidebar: () => import("../views/hui-sidebar-view"),
+ sections: () => import("../views/hui-sections-view"),
};
export const createViewElement = (
diff --git a/src/panels/lovelace/editor/add-entities-to-view.ts b/src/panels/lovelace/editor/add-entities-to-view.ts
index 03b9a44ac2..8706287c03 100644
--- a/src/panels/lovelace/editor/add-entities-to-view.ts
+++ b/src/panels/lovelace/editor/add-entities-to-view.ts
@@ -1,5 +1,6 @@
import { LovelacePanelConfig } from "../../../data/lovelace";
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
import {
LovelaceConfig,
fetchConfig,
@@ -15,6 +16,7 @@ export const addEntitiesToLovelaceView = async (
element: HTMLElement,
hass: HomeAssistant,
cardConfig: LovelaceCardConfig[],
+ sectionConfig?: LovelaceSectionConfig,
entities?: string[]
) => {
hass.loadFragmentTranslation("lovelace");
@@ -71,6 +73,7 @@ export const addEntitiesToLovelaceView = async (
// all storage dashboards are generated, but we have YAML dashboards just show the YAML config
showSuggestCardDialog(element, {
cardConfig,
+ sectionConfig,
entities,
yaml: true,
});
@@ -93,6 +96,7 @@ export const addEntitiesToLovelaceView = async (
if (!storageDashs.length && lovelaceConfig.views.length === 1) {
showSuggestCardDialog(element, {
cardConfig,
+ sectionConfig,
lovelaceConfig: lovelaceConfig!,
saveConfig: async (newConfig: LovelaceConfig): Promise => {
try {
@@ -116,6 +120,7 @@ export const addEntitiesToLovelaceView = async (
viewSelectedCallback: (newUrlPath, selectedDashConfig, viewIndex) => {
showSuggestCardDialog(element, {
cardConfig,
+ sectionConfig,
lovelaceConfig: selectedDashConfig,
saveConfig: async (newConfig: LovelaceConfig): Promise => {
try {
diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts
index 382914e87f..2577822756 100644
--- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts
+++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts
@@ -15,6 +15,7 @@ import { until } from "lit/directives/until";
import memoizeOne from "memoize-one";
import { storage } from "../../../../common/decorators/storage";
import { fireEvent } from "../../../../common/dom/fire_event";
+import { stringCompare } from "../../../../common/string/compare";
import "../../../../components/ha-circular-progress";
import "../../../../components/search-input";
import { isUnavailableState } from "../../../../data/entity";
@@ -46,6 +47,8 @@ interface CardElement {
export class HuiCardPicker extends LitElement {
@property({ attribute: false }) public hass?: HomeAssistant;
+ @property({ attribute: false }) public suggestedCards?: string[];
+
@storage({
key: "lovelaceClipboard",
state: true,
@@ -92,6 +95,29 @@ export class HuiCardPicker extends LitElement {
}
);
+ private _suggestedCards = memoizeOne(
+ (cardElements: CardElement[]): CardElement[] =>
+ cardElements.filter(
+ (cardElement: CardElement) => cardElement.card.isSuggested
+ )
+ );
+
+ private _customCards = memoizeOne(
+ (cardElements: CardElement[]): CardElement[] =>
+ cardElements.filter(
+ (cardElement: CardElement) =>
+ cardElement.card.isCustom && !cardElement.card.isSuggested
+ )
+ );
+
+ private _otherCards = memoizeOne(
+ (cardElements: CardElement[]): CardElement[] =>
+ cardElements.filter(
+ (cardElement: CardElement) =>
+ !cardElement.card.isSuggested && !cardElement.card.isCustom
+ )
+ );
+
protected render() {
if (
!this.hass ||
@@ -102,6 +128,10 @@ export class HuiCardPicker extends LitElement {
return nothing;
}
+ const suggestedCards = this._suggestedCards(this._cards);
+ const othersCards = this._otherCards(this._cards);
+ const customCardsItems = this._customCards(this._cards);
+
return html`
- ${this._clipboard && !this._filter
- ? html`
- ${until(
- this._renderCardElement(
- {
- type: this._clipboard.type,
- showElement: true,
- isCustom: false,
- name: this.hass!.localize(
- "ui.panel.lovelace.editor.card.generic.paste"
- ),
- description: `${this.hass!.localize(
- "ui.panel.lovelace.editor.card.generic.paste_description",
- {
- type: this._clipboard.type,
- }
- )}`,
- },
- this._clipboard
- ),
- html`
-
-
-
- `
+ ${this._filter
+ ? this._filterCards(this._cards, this._filter).map(
+ (cardElement: CardElement) => cardElement.element
+ )
+ : html`
+ ${suggestedCards.length > 0
+ ? html`
+
+ `
+ : nothing}
+ ${this._renderClipboardCard()}
+ ${suggestedCards.map(
+ (cardElement: CardElement) => cardElement.element
)}
- `
- : nothing}
- ${this._filterCards(this._cards, this._filter).map(
- (cardElement: CardElement) => cardElement.element
- )}
+ ${suggestedCards.length > 0
+ ? html`
+
+ `
+ : nothing}
+ ${othersCards.map(
+ (cardElement: CardElement) => cardElement.element
+ )}
+ ${customCardsItems.length > 0
+ ? html`
+
+ `
+ : nothing}
+ ${customCardsItems.map(
+ (cardElement: CardElement) => cardElement.element
+ )}
+ `}
{
+ if (a.isSuggested && !b.isSuggested) {
+ return -1;
+ }
+ if (!a.isSuggested && b.isSuggested) {
+ return 1;
+ }
+ return stringCompare(
+ a.name || a.type,
+ b.name || b.type,
+ this.hass?.language
+ );
+ });
+
if (customCards.length > 0) {
cards = cards.concat(
customCards.map((ccard: CustomCardEntry) => ({
@@ -244,6 +300,37 @@ export class HuiCardPicker extends LitElement {
}));
}
+ private _renderClipboardCard() {
+ if (!this._clipboard) {
+ return nothing;
+ }
+
+ return html` ${until(
+ this._renderCardElement(
+ {
+ type: this._clipboard.type,
+ showElement: true,
+ isCustom: false,
+ name: this.hass!.localize(
+ "ui.panel.lovelace.editor.card.generic.paste"
+ ),
+ description: `${this.hass!.localize(
+ "ui.panel.lovelace.editor.card.generic.paste_description",
+ {
+ type: this._clipboard.type,
+ }
+ )}`,
+ },
+ this._clipboard
+ ),
+ html`
+
+
+
+ `
+ )}`;
+ }
+
private _handleSearchChange(ev: CustomEvent) {
const value = ev.detail.value;
@@ -381,6 +468,14 @@ export class HuiCardPicker extends LitElement {
margin: var(--card-picker-search-margin);
}
+ .cards-container-header {
+ font-size: 16px;
+ font-weight: 500;
+ padding: 12px 8px 4px 8px;
+ margin: 0;
+ grid-column: 1 / -1;
+ }
+
.cards-container {
display: grid;
grid-gap: 8px 8px;
@@ -455,6 +550,23 @@ export class HuiCardPicker extends LitElement {
.manual {
max-width: none;
}
+
+ .icon {
+ position: absolute;
+ top: 8px;
+ right: 8px
+ inset-inline-start: 8px;
+ inset-inline-end: 8px;
+ border-radius: 50%;
+ --mdc-icon-size: 16px;
+ line-height: 16px;
+ box-sizing: border-box;
+ color: var(--text-primary-color);
+ padding: 4px;
+ }
+ .icon.custom {
+ background: var(--warning-color);
+ }
`,
];
}
diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts
index 4ce93735d4..89a20ab0f5 100644
--- a/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts
+++ b/src/panels/lovelace/editor/card-editor/hui-dialog-create-card.ts
@@ -12,16 +12,27 @@ import { computeStateName } from "../../../../common/entity/compute_state_name";
import { DataTableRowData } from "../../../../components/data-table/ha-data-table";
import "../../../../components/ha-dialog";
import "../../../../components/ha-dialog-header";
+import {
+ isStrategySection,
+ LovelaceSectionConfig,
+} from "../../../../data/lovelace/config/section";
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
import { haStyleDialog } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types";
+import {
+ computeCards,
+ computeSection,
+} from "../../common/generate-lovelace-config";
import "./hui-card-picker";
import "./hui-entity-picker-table";
import { CreateCardDialogParams } from "./show-create-card-dialog";
import { showEditCardDialog } from "./show-edit-card-dialog";
import { showSuggestCardDialog } from "./show-suggest-card-dialog";
-import { computeCards } from "../../common/generate-lovelace-config";
+import {
+ findLovelaceContainer,
+ parseLovelaceContainerPath,
+} from "../lovelace-path";
declare global {
interface HASSDomEvents {
@@ -42,7 +53,9 @@ export class HuiCreateDialogCard
@state() private _params?: CreateCardDialogParams;
- @state() private _viewConfig!: LovelaceViewConfig;
+ @state() private _containerConfig!:
+ | LovelaceViewConfig
+ | LovelaceSectionConfig;
@state() private _selectedEntities: string[] = [];
@@ -50,8 +63,17 @@ export class HuiCreateDialogCard
public async showDialog(params: CreateCardDialogParams): Promise
{
this._params = params;
- const [view] = params.path;
- this._viewConfig = params.lovelaceConfig.views[view];
+
+ const containerConfig = findLovelaceContainer(
+ params.lovelaceConfig,
+ params.path
+ );
+
+ if ("strategy" in containerConfig) {
+ throw new Error("Can't edit strategy");
+ }
+
+ this._containerConfig = containerConfig;
}
public closeDialog(): boolean {
@@ -67,10 +89,10 @@ export class HuiCreateDialogCard
return nothing;
}
- const title = this._viewConfig.title
+ const title = this._containerConfig.title
? this.hass!.localize(
- "ui.panel.lovelace.editor.edit_card.pick_card_view_title",
- { name: `"${this._viewConfig.title}"` }
+ "ui.panel.lovelace.editor.edit_card.pick_card_title",
+ { name: `"${this._containerConfig.title}"` }
)
: this.hass!.localize("ui.panel.lovelace.editor.edit_card.pick_card");
@@ -112,6 +134,7 @@ export class HuiCreateDialogCard
this._currTabIndex === 0
? html`
= {};
+
+ const { sectionIndex } = parseLovelaceContainerPath(this._params!.path);
+ const isSection = sectionIndex !== undefined;
+
+ // If we are in a section, we want to keep the section options for the preview
+ if (isSection) {
+ const containerConfig = findLovelaceContainer(
+ this._params!.lovelaceConfig!,
+ this._params!.path!
+ ) as LovelaceSectionConfig;
+ if (!isStrategySection(containerConfig)) {
+ const { cards, title, ...rest } = containerConfig;
+ sectionOptions = rest;
+ }
+ }
+
+ const sectionConfig = computeSection(
+ this._selectedEntities,
+ sectionOptions
+ );
+
showSuggestCardDialog(this, {
lovelaceConfig: this._params!.lovelaceConfig,
saveConfig: this._params!.saveConfig,
path: this._params!.path as [number],
entities: this._selectedEntities,
cardConfig,
+ sectionConfig,
});
this.closeDialog();
diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts
index 98427c14f4..c27b7024a2 100644
--- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts
+++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts
@@ -1,12 +1,12 @@
import { mdiClose, mdiHelpCircle } from "@mdi/js";
import deepFreeze from "deep-freeze";
import {
- css,
CSSResultGroup,
- html,
LitElement,
- nothing,
PropertyValues,
+ css,
+ html,
+ nothing,
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
@@ -16,6 +16,14 @@ import "../../../../components/ha-circular-progress";
import "../../../../components/ha-dialog";
import "../../../../components/ha-dialog-header";
import "../../../../components/ha-icon-button";
+import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
+import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
+import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
+import {
+ getCustomCardEntry,
+ isCustomType,
+ stripCustomPrefix,
+} from "../../../../data/lovelace_custom_cards";
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
import { haStyleDialog } from "../../../../resources/styles";
@@ -24,18 +32,12 @@ import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
import { addCard, replaceCard } from "../config-util";
import { getCardDocumentationURL } from "../get-card-documentation-url";
import type { ConfigChangedEvent } from "../hui-element-editor";
+import { findLovelaceContainer } from "../lovelace-path";
import type { GUIModeChangedEvent } from "../types";
import "./hui-card-element-editor";
import type { HuiCardElementEditor } from "./hui-card-element-editor";
import "./hui-card-preview";
import type { EditCardDialogParams } from "./show-edit-card-dialog";
-import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
-import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
-import {
- getCustomCardEntry,
- isCustomType,
- stripCustomPrefix,
-} from "../../../../data/lovelace_custom_cards";
declare global {
// for fire event
@@ -61,7 +63,9 @@ export class HuiDialogEditCard
@state() private _cardConfig?: LovelaceCardConfig;
- @state() private _viewConfig!: LovelaceViewConfig;
+ @state() private _containerConfig!:
+ | LovelaceViewConfig
+ | LovelaceSectionConfig;
@state() private _saving = false;
@@ -84,17 +88,29 @@ export class HuiDialogEditCard
this._params = params;
this._GUImode = true;
this._guiModeAvailable = true;
- const [view, card] = params.path;
- this._viewConfig = params.lovelaceConfig.views[view];
- this._cardConfig =
- card !== undefined ? this._viewConfig.cards![card] : params.cardConfig;
+
+ const containerConfig = findLovelaceContainer(
+ params.lovelaceConfig,
+ params.path
+ );
+
+ if ("strategy" in containerConfig) {
+ throw new Error("Can't edit strategy");
+ }
+
+ this._containerConfig = containerConfig;
+
+ if ("cardConfig" in params) {
+ this._cardConfig = params.cardConfig;
+ this._dirty = true;
+ } else {
+ this._cardConfig = this._containerConfig.cards?.[params.cardIndex];
+ }
+
this.large = false;
if (this._cardConfig && !Object.isFrozen(this._cardConfig)) {
this._cardConfig = deepFreeze(this._cardConfig);
}
- if (params.cardConfig) {
- this._dirty = true;
- }
}
public closeDialog(): boolean {
@@ -170,10 +186,10 @@ export class HuiDialogEditCard
{ type: cardName }
);
} else if (!this._cardConfig) {
- heading = this._viewConfig.title
+ heading = this._containerConfig.title
? this.hass!.localize(
"ui.panel.lovelace.editor.edit_card.pick_card_view_title",
- { name: this._viewConfig.title }
+ { name: this._containerConfig.title }
)
: this.hass!.localize("ui.panel.lovelace.editor.edit_card.pick_card");
} else {
@@ -368,16 +384,13 @@ export class HuiDialogEditCard
return;
}
this._saving = true;
+ const path = this._params!.path;
await this._params!.saveConfig(
- this._params!.path.length === 1
- ? addCard(
- this._params!.lovelaceConfig,
- this._params!.path as [number],
- this._cardConfig!
- )
+ "cardConfig" in this._params!
+ ? addCard(this._params!.lovelaceConfig, path, this._cardConfig!)
: replaceCard(
this._params!.lovelaceConfig,
- this._params!.path as [number, number],
+ [...path, this._params!.cardIndex],
this._cardConfig!
)
);
diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts
index 8cf248ac01..80e517d5ce 100644
--- a/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts
+++ b/src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts
@@ -5,13 +5,20 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-yaml-editor";
import type { HaYamlEditor } from "../../../../components/ha-yaml-editor";
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
+import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
+import { isStrategyView } from "../../../../data/lovelace/config/view";
import { haStyleDialog } from "../../../../resources/styles";
import { HomeAssistant } from "../../../../types";
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
-import { addCards } from "../config-util";
+import { addCards, addSection } from "../config-util";
+import {
+ LovelaceContainerPath,
+ parseLovelaceContainerPath,
+} from "../lovelace-path";
import "./hui-card-preview";
import { showCreateCardDialog } from "./show-create-card-dialog";
import { SuggestCardDialogParams } from "./show-suggest-card-dialog";
+import { LovelaceConfig } from "../../../../data/lovelace/config/types";
@customElement("hui-dialog-suggest-card")
export class HuiDialogSuggestCard extends LitElement {
@@ -21,6 +28,8 @@ export class HuiDialogSuggestCard extends LitElement {
@state() private _cardConfig?: LovelaceCardConfig[];
+ @state() private _sectionConfig?: LovelaceSectionConfig;
+
@state() private _saving = false;
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
@@ -28,9 +37,13 @@ export class HuiDialogSuggestCard extends LitElement {
public showDialog(params: SuggestCardDialogParams): void {
this._params = params;
this._cardConfig = params.cardConfig;
+ this._sectionConfig = params.sectionConfig;
if (!Object.isFrozen(this._cardConfig)) {
this._cardConfig = deepFreeze(this._cardConfig);
}
+ if (!Object.isFrozen(this._sectionConfig)) {
+ this._sectionConfig = deepFreeze(this._sectionConfig);
+ }
if (this._yamlEditor) {
this._yamlEditor.setValue(this._cardConfig);
}
@@ -42,6 +55,45 @@ export class HuiDialogSuggestCard extends LitElement {
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
+ private get _viewSupportsSection(): boolean {
+ if (!this._params?.lovelaceConfig || !this._params?.path) {
+ return false;
+ }
+
+ const { viewIndex } = parseLovelaceContainerPath(this._params.path);
+ const viewConfig = this._params!.lovelaceConfig.views[viewIndex];
+
+ return !isStrategyView(viewConfig) && viewConfig.type === "sections";
+ }
+
+ private _renderPreview() {
+ if (this._sectionConfig && this._viewSupportsSection) {
+ return html`
+
+
+
+ `;
+ }
+ if (this._cardConfig) {
+ return html`
+
+ ${this._cardConfig.map(
+ (cardConfig) => html`
+
+ `
+ )}
+
+ `;
+ }
+ return nothing;
+ }
+
protected render() {
if (!this._params) {
return nothing;
@@ -56,20 +108,7 @@ export class HuiDialogSuggestCard extends LitElement {
)}
>
- ${this._cardConfig
- ? html`
-
- ${this._cardConfig.map(
- (cardConfig) => html`
-
- `
- )}
-
- `
- : ""}
+ ${this._renderPreview()}
${this._params.yaml && this._cardConfig
? html`
@@ -79,7 +118,7 @@ export class HuiDialogSuggestCard extends LitElement {
>
`
- : ""}
+ : nothing}
{
if (
!this._params?.lovelaceConfig ||
@@ -188,13 +254,12 @@ export class HuiDialogSuggestCard extends LitElement {
return;
}
this._saving = true;
- await this._params!.saveConfig(
- addCards(
- this._params!.lovelaceConfig,
- this._params!.path as [number],
- this._cardConfig
- )
+
+ const newConfig = this._computeNewConfig(
+ this._params.lovelaceConfig,
+ this._params.path
);
+ await this._params!.saveConfig(newConfig);
this._saving = false;
showSaveSuccessToast(this, this.hass);
this.closeDialog();
diff --git a/src/panels/lovelace/editor/card-editor/hui-section-preview.ts b/src/panels/lovelace/editor/card-editor/hui-section-preview.ts
new file mode 100644
index 0000000000..c569fcf4c1
--- /dev/null
+++ b/src/panels/lovelace/editor/card-editor/hui-section-preview.ts
@@ -0,0 +1,104 @@
+import { PropertyValues, ReactiveElement } from "lit";
+import { customElement, property } from "lit/decorators";
+import { LovelaceSectionElement } from "../../../../data/lovelace";
+import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
+import { HomeAssistant } from "../../../../types";
+import { createSectionElement } from "../../create-element/create-section-element";
+import { createErrorSectionConfig } from "../../sections/hui-error-section";
+import { LovelaceConfig } from "../../../../data/lovelace/config/types";
+
+@customElement("hui-section-preview")
+export class HuiSectionPreview extends ReactiveElement {
+ @property({ attribute: false }) public hass?: HomeAssistant;
+
+ @property({ attribute: false }) public lovelace?: LovelaceConfig;
+
+ @property({ attribute: false }) public config?: LovelaceSectionConfig;
+
+ private _element?: LovelaceSectionElement;
+
+ private get _error() {
+ return this._element?.tagName === "HUI-ERROR-SECTION";
+ }
+
+ constructor() {
+ super();
+ this.addEventListener("ll-rebuild", () => {
+ this._cleanup();
+ if (this.config) {
+ this._createSection(this.config);
+ }
+ });
+ }
+
+ protected createRenderRoot() {
+ return this;
+ }
+
+ protected update(changedProperties: PropertyValues) {
+ super.update(changedProperties);
+
+ if (changedProperties.has("config")) {
+ const oldConfig = changedProperties.get("config") as
+ | undefined
+ | LovelaceSectionConfig;
+
+ if (!this.config) {
+ this._cleanup();
+ return;
+ }
+
+ if (!this.config.type) {
+ this._createSection(createErrorSectionConfig("No section type found"));
+ return;
+ }
+
+ if (!this._element) {
+ this._createSection(this.config);
+ return;
+ }
+
+ // in case the element was an error element we always want to recreate it
+ if (!this._error && oldConfig && this.config.type === oldConfig.type) {
+ try {
+ this._element.setConfig(this.config);
+ } catch (err: any) {
+ this._createSection(createErrorSectionConfig(err.message));
+ }
+ } else {
+ this._createSection(this.config);
+ }
+ }
+
+ if (changedProperties.has("hass")) {
+ if (this._element) {
+ this._element.hass = this.hass;
+ }
+ }
+ }
+
+ private _createSection(configValue: LovelaceSectionConfig): void {
+ this._cleanup();
+ this._element = createSectionElement(configValue) as LovelaceSectionElement;
+
+ if (this.hass) {
+ this._element!.hass = this.hass;
+ }
+
+ this.appendChild(this._element!);
+ }
+
+ private _cleanup() {
+ if (!this._element) {
+ return;
+ }
+ this.removeChild(this._element);
+ this._element = undefined;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-section-preview": HuiSectionPreview;
+ }
+}
diff --git a/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts b/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts
index dedd6d1b6a..96c58879b2 100644
--- a/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts
+++ b/src/panels/lovelace/editor/card-editor/show-create-card-dialog.ts
@@ -1,10 +1,12 @@
import { fireEvent } from "../../../../common/dom/fire_event";
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
+import { LovelaceContainerPath } from "../lovelace-path";
export interface CreateCardDialogParams {
lovelaceConfig: LovelaceConfig;
saveConfig: (config: LovelaceConfig) => void;
- path: [number] | [number, number];
+ path: LovelaceContainerPath;
+ suggestedCards?: string[];
entities?: string[]; // We can pass entity id's that will be added to the config when a card is picked
}
diff --git a/src/panels/lovelace/editor/card-editor/show-edit-card-dialog.ts b/src/panels/lovelace/editor/card-editor/show-edit-card-dialog.ts
index f6b55e3b0e..40391f6a13 100644
--- a/src/panels/lovelace/editor/card-editor/show-edit-card-dialog.ts
+++ b/src/panels/lovelace/editor/card-editor/show-edit-card-dialog.ts
@@ -1,13 +1,20 @@
import { fireEvent } from "../../../../common/dom/fire_event";
import type { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
+import { LovelaceContainerPath } from "../lovelace-path";
-export interface EditCardDialogParams {
+export type EditCardDialogParams = {
lovelaceConfig: LovelaceConfig;
saveConfig: (config: LovelaceConfig) => void;
- path: [number] | [number, number];
- cardConfig?: LovelaceCardConfig;
-}
+ path: LovelaceContainerPath;
+} & (
+ | {
+ cardIndex: number;
+ }
+ | {
+ cardConfig: LovelaceCardConfig;
+ }
+);
export const importEditCardDialog = () => import("./hui-dialog-edit-card");
diff --git a/src/panels/lovelace/editor/card-editor/show-suggest-card-dialog.ts b/src/panels/lovelace/editor/card-editor/show-suggest-card-dialog.ts
index ea43443d06..c95fed399e 100644
--- a/src/panels/lovelace/editor/card-editor/show-suggest-card-dialog.ts
+++ b/src/panels/lovelace/editor/card-editor/show-suggest-card-dialog.ts
@@ -1,14 +1,17 @@
import { fireEvent } from "../../../../common/dom/fire_event";
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
+import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
import { LovelaceConfig } from "../../../../data/lovelace/config/types";
+import { LovelaceContainerPath } from "../lovelace-path";
export interface SuggestCardDialogParams {
lovelaceConfig?: LovelaceConfig;
yaml?: boolean;
saveConfig?: (config: LovelaceConfig) => void;
- path?: [number];
+ path?: LovelaceContainerPath;
entities?: string[]; // We pass this to create dialog when user chooses "Pick own"
- cardConfig: LovelaceCardConfig[]; // We can pass a suggested config
+ cardConfig: LovelaceCardConfig[]; // We can pass a suggested config,s
+ sectionConfig?: LovelaceSectionConfig;
}
const importSuggestCardDialog = () => import("./hui-dialog-suggest-card");
diff --git a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts
index d8fe23d0a7..ef1fcdfae0 100644
--- a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts
@@ -27,6 +27,7 @@ import { supportsCoverOpenCloseCardFeature } from "../../card-features/hui-cover
import { supportsCoverPositionCardFeature } from "../../card-features/hui-cover-position-card-feature";
import { supportsCoverTiltCardFeature } from "../../card-features/hui-cover-tilt-card-feature";
import { supportsCoverTiltPositionCardFeature } from "../../card-features/hui-cover-tilt-position-card-feature";
+import { supportsFanPresetModesCardFeature } from "../../card-features/hui-fan-preset-modes-card-feature";
import { supportsFanSpeedCardFeature } from "../../card-features/hui-fan-speed-card-feature";
import { supportsHumidifierModesCardFeature } from "../../card-features/hui-humidifier-modes-card-feature";
import { supportsHumidifierToggleCardFeature } from "../../card-features/hui-humidifier-toggle-card-feature";
@@ -55,34 +56,36 @@ const UI_FEATURE_TYPES = [
"cover-position",
"cover-tilt-position",
"cover-tilt",
+ "fan-preset-modes",
"fan-speed",
"humidifier-modes",
"humidifier-toggle",
"lawn-mower-commands",
"light-brightness",
"light-color-temp",
+ "numeric-input",
"select-options",
"target-humidity",
"target-temperature",
- "vacuum-commands",
"update-actions",
+ "vacuum-commands",
"water-heater-operation-modes",
- "numeric-input",
] as const satisfies readonly FeatureType[];
type UiFeatureTypes = (typeof UI_FEATURE_TYPES)[number];
const EDITABLES_FEATURE_TYPES = new Set([
- "vacuum-commands",
"alarm-modes",
"climate-hvac-modes",
- "humidifier-modes",
- "water-heater-operation-modes",
- "lawn-mower-commands",
"climate-fan-modes",
"climate-preset-modes",
+ "fan-preset-modes",
+ "humidifier-modes",
+ "lawn-mower-commands",
"numeric-input",
"update-actions",
+ "vacuum-commands",
+ "water-heater-operation-modes",
]);
const SUPPORTS_FEATURE_TYPES: Record<
@@ -97,6 +100,7 @@ const SUPPORTS_FEATURE_TYPES: Record<
"cover-position": supportsCoverPositionCardFeature,
"cover-tilt-position": supportsCoverTiltPositionCardFeature,
"cover-tilt": supportsCoverTiltCardFeature,
+ "fan-preset-modes": supportsFanPresetModesCardFeature,
"fan-speed": supportsFanSpeedCardFeature,
"humidifier-modes": supportsHumidifierModesCardFeature,
"humidifier-toggle": supportsHumidifierToggleCardFeature,
@@ -104,12 +108,12 @@ const SUPPORTS_FEATURE_TYPES: Record<
"light-brightness": supportsLightBrightnessCardFeature,
"light-color-temp": supportsLightColorTempCardFeature,
"numeric-input": supportsNumericInputCardFeature,
+ "select-options": supportsSelectOptionsCardFeature,
"target-humidity": supportsTargetHumidityCardFeature,
"target-temperature": supportsTargetTemperatureCardFeature,
+ "update-actions": supportsUpdateActionsCardFeature,
"vacuum-commands": supportsVacuumCommandsCardFeature,
"water-heater-operation-modes": supportsWaterHeaterOperationModesCardFeature,
- "select-options": supportsSelectOptionsCardFeature,
- "update-actions": supportsUpdateActionsCardFeature,
};
const customCardFeatures = getCustomCardFeatures();
diff --git a/src/panels/lovelace/editor/config-elements/hui-fan-preset-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-fan-preset-modes-card-feature-editor.ts
new file mode 100644
index 0000000000..35cfd7b8a6
--- /dev/null
+++ b/src/panels/lovelace/editor/config-elements/hui-fan-preset-modes-card-feature-editor.ts
@@ -0,0 +1,133 @@
+import { HassEntity } from "home-assistant-js-websocket";
+import { html, LitElement, nothing } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import memoizeOne from "memoize-one";
+import { fireEvent } from "../../../../common/dom/fire_event";
+import { FormatEntityAttributeValueFunc } from "../../../../common/translations/entity-state";
+import { LocalizeFunc } from "../../../../common/translations/localize";
+import "../../../../components/ha-form/ha-form";
+import type {
+ HaFormSchema,
+ SchemaUnion,
+} from "../../../../components/ha-form/types";
+import type { HomeAssistant } from "../../../../types";
+import {
+ FanPresetModesCardFeatureConfig,
+ LovelaceCardFeatureContext,
+} from "../../card-features/types";
+import type { LovelaceCardFeatureEditor } from "../../types";
+
+@customElement("hui-fan-preset-modes-card-feature-editor")
+export class HuiFanPresetModesCardFeatureEditor
+ extends LitElement
+ implements LovelaceCardFeatureEditor
+{
+ @property({ attribute: false }) public hass?: HomeAssistant;
+
+ @property({ attribute: false }) public context?: LovelaceCardFeatureContext;
+
+ @state() private _config?: FanPresetModesCardFeatureConfig;
+
+ public setConfig(config: FanPresetModesCardFeatureConfig): void {
+ this._config = config;
+ }
+
+ private _schema = memoizeOne(
+ (
+ localize: LocalizeFunc,
+ formatEntityAttributeValue: FormatEntityAttributeValueFunc,
+ stateObj?: HassEntity
+ ) =>
+ [
+ {
+ name: "style",
+ selector: {
+ select: {
+ multiple: false,
+ mode: "list",
+ options: ["dropdown", "icons"].map((mode) => ({
+ value: mode,
+ label: localize(
+ `ui.panel.lovelace.editor.features.types.fan-preset-modes.style_list.${mode}`
+ ),
+ })),
+ },
+ },
+ },
+ {
+ name: "preset_modes",
+ selector: {
+ select: {
+ multiple: true,
+ mode: "list",
+ options:
+ stateObj?.attributes.preset_modes?.map((mode) => ({
+ value: mode,
+ label: formatEntityAttributeValue(
+ stateObj,
+ "preset_mode",
+ mode
+ ),
+ })) || [],
+ },
+ },
+ },
+ ] as const satisfies readonly HaFormSchema[]
+ );
+
+ protected render() {
+ if (!this.hass || !this._config) {
+ return nothing;
+ }
+
+ const stateObj = this.context?.entity_id
+ ? this.hass.states[this.context?.entity_id]
+ : undefined;
+
+ const data: FanPresetModesCardFeatureConfig = {
+ style: "dropdown",
+ preset_modes: [],
+ ...this._config,
+ };
+
+ const schema = this._schema(
+ this.hass.localize,
+ this.hass.formatEntityAttributeValue,
+ stateObj
+ );
+
+ return html`
+
+ `;
+ }
+
+ private _valueChanged(ev: CustomEvent): void {
+ fireEvent(this, "config-changed", { config: ev.detail.value });
+ }
+
+ private _computeLabelCallback = (
+ schema: SchemaUnion>
+ ) => {
+ switch (schema.name) {
+ case "style":
+ case "preset_modes":
+ return this.hass!.localize(
+ `ui.panel.lovelace.editor.features.types.fan-preset-modes.${schema.name}`
+ );
+ default:
+ return "";
+ }
+ };
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-fan-preset-modes-card-feature-editor": HuiFanPresetModesCardFeatureEditor;
+ }
+}
diff --git a/src/panels/lovelace/editor/config-util.ts b/src/panels/lovelace/editor/config-util.ts
index f494544fb6..09d2e611fa 100644
--- a/src/panels/lovelace/editor/config-util.ts
+++ b/src/panels/lovelace/editor/config-util.ts
@@ -1,296 +1,160 @@
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import { LovelaceSectionRawConfig } from "../../../data/lovelace/config/section";
import { LovelaceConfig } from "../../../data/lovelace/config/types";
import {
LovelaceViewConfig,
isStrategyView,
} from "../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../types";
+import {
+ LovelaceCardPath,
+ LovelaceContainerPath,
+ findLovelaceCards,
+ findLovelaceContainer,
+ getLovelaceContainerPath,
+ parseLovelaceCardPath,
+ parseLovelaceContainerPath,
+ updateLovelaceCards,
+ updateLovelaceContainer,
+} from "./lovelace-path";
export const addCard = (
config: LovelaceConfig,
- path: [number],
+ path: LovelaceContainerPath,
cardConfig: LovelaceCardConfig
): LovelaceConfig => {
- const [viewIndex] = path;
- const views: LovelaceViewConfig[] = [];
-
- config.views.forEach((viewConf, index) => {
- if (index !== viewIndex) {
- views.push(config.views[index]);
- return;
- }
-
- if (isStrategyView(viewConf)) {
- throw new Error("You cannot add a card in a strategy view.");
- }
-
- const cards = viewConf.cards
- ? [...viewConf.cards, cardConfig]
- : [cardConfig];
-
- views.push({
- ...viewConf,
- cards,
- });
- });
-
- return {
- ...config,
- views,
- };
+ const cards = findLovelaceCards(config, path);
+ const newCards = cards ? [...cards, cardConfig] : [cardConfig];
+ const newConfig = updateLovelaceCards(config, path, newCards);
+ return newConfig;
};
export const addCards = (
config: LovelaceConfig,
- path: [number],
+ path: LovelaceContainerPath,
cardConfigs: LovelaceCardConfig[]
): LovelaceConfig => {
- const [viewIndex] = path;
- const views: LovelaceViewConfig[] = [];
-
- config.views.forEach((viewConf, index) => {
- if (index !== viewIndex) {
- views.push(config.views[index]);
- return;
- }
-
- if (isStrategyView(viewConf)) {
- throw new Error("You cannot add cards in a strategy view.");
- }
-
- const cards = viewConf.cards
- ? [...viewConf.cards, ...cardConfigs]
- : [...cardConfigs];
-
- views.push({
- ...viewConf,
- cards,
- });
- });
-
- return {
- ...config,
- views,
- };
+ const cards = findLovelaceCards(config, path);
+ const newCards = cards ? [...cards, ...cardConfigs] : [...cardConfigs];
+ const newConfig = updateLovelaceCards(config, path, newCards);
+ return newConfig;
};
export const replaceCard = (
config: LovelaceConfig,
- path: [number, number],
+ path: LovelaceCardPath,
cardConfig: LovelaceCardConfig
): LovelaceConfig => {
- const [viewIndex, cardIndex] = path;
- const views: LovelaceViewConfig[] = [];
+ const { cardIndex } = parseLovelaceCardPath(path);
+ const containerPath = getLovelaceContainerPath(path);
- config.views.forEach((viewConf, index) => {
- if (index !== viewIndex) {
- views.push(config.views[index]);
- return;
- }
+ const cards = findLovelaceCards(config, containerPath);
- if (isStrategyView(viewConf)) {
- throw new Error("You cannot replace a card in a strategy view.");
- }
+ const newCards = (cards ?? []).map((origConf, ind) =>
+ ind === cardIndex ? cardConfig : origConf
+ );
- views.push({
- ...viewConf,
- cards: (viewConf.cards || []).map((origConf, ind) =>
- ind === cardIndex ? cardConfig : origConf
- ),
- });
- });
-
- return {
- ...config,
- views,
- };
+ const newConfig = updateLovelaceCards(config, containerPath, newCards);
+ return newConfig;
};
export const deleteCard = (
config: LovelaceConfig,
- path: [number, number]
+ path: LovelaceCardPath
): LovelaceConfig => {
- const [viewIndex, cardIndex] = path;
- const views: LovelaceViewConfig[] = [];
+ const { cardIndex } = parseLovelaceCardPath(path);
+ const containerPath = getLovelaceContainerPath(path);
- config.views.forEach((viewConf, index) => {
- if (index !== viewIndex) {
- views.push(config.views[index]);
- return;
- }
+ const cards = findLovelaceCards(config, containerPath);
- if (isStrategyView(viewConf)) {
- throw new Error("You cannot delete a card in a strategy view.");
- }
+ const newCards = (cards ?? []).filter((_origConf, ind) => ind !== cardIndex);
- views.push({
- ...viewConf,
- cards: (viewConf.cards || []).filter(
- (_origConf, ind) => ind !== cardIndex
- ),
- });
- });
-
- return {
- ...config,
- views,
- };
+ const newConfig = updateLovelaceCards(config, containerPath, newCards);
+ return newConfig;
};
export const insertCard = (
config: LovelaceConfig,
- path: [number, number],
+ path: LovelaceCardPath,
cardConfig: LovelaceCardConfig
) => {
- const [viewIndex, cardIndex] = path;
- const views: LovelaceViewConfig[] = [];
+ const { cardIndex } = parseLovelaceCardPath(path);
+ const containerPath = getLovelaceContainerPath(path);
- config.views.forEach((viewConf, index) => {
- if (index !== viewIndex) {
- views.push(config.views[index]);
- return;
- }
+ const cards = findLovelaceCards(config, containerPath);
- if (isStrategyView(viewConf)) {
- throw new Error("You cannot insert a card in a strategy view.");
- }
+ const newCards = cards
+ ? [...cards.slice(0, cardIndex), cardConfig, ...cards.slice(cardIndex)]
+ : [cardConfig];
- const cards = viewConf.cards
- ? [
- ...viewConf.cards.slice(0, cardIndex),
- cardConfig,
- ...viewConf.cards.slice(cardIndex),
- ]
- : [cardConfig];
-
- views.push({
- ...viewConf,
- cards,
- });
- });
-
- return {
- ...config,
- views,
- };
+ const newConfig = updateLovelaceCards(config, containerPath, newCards);
+ return newConfig;
};
-export const swapCard = (
+export const moveCardToIndex = (
config: LovelaceConfig,
- path1: [number, number],
- path2: [number, number]
+ path: LovelaceCardPath,
+ index: number
): LovelaceConfig => {
- const origView1 = config.views[path1[0]];
- const origView2 = config.views[path2[0]];
+ const { cardIndex } = parseLovelaceCardPath(path);
+ const containerPath = getLovelaceContainerPath(path);
- if (isStrategyView(origView1) || isStrategyView(origView2)) {
- throw new Error("You cannot move swap cards in a strategy view.");
- }
+ const cards = findLovelaceCards(config, containerPath);
- const card1 = origView1.cards![path1[1]];
- const card2 = origView2.cards![path2[1]];
+ const newCards = cards ? [...cards] : [];
- const newView1 = {
- ...origView1,
- cards: origView1.cards!.map((origCard, index) =>
- index === path1[1] ? card2 : origCard
- ),
- };
-
- const updatedOrigView2 = path1[0] === path2[0] ? newView1 : origView2;
- const newView2 = {
- ...updatedOrigView2,
- cards: updatedOrigView2.cards!.map((origCard, index) =>
- index === path2[1] ? card1 : origCard
- ),
- };
-
- return {
- ...config,
- views: config.views.map((origView, index) =>
- index === path2[0] ? newView2 : index === path1[0] ? newView1 : origView
- ),
- };
-};
-
-export const moveCardToPosition = (
- config: LovelaceConfig,
- path: [number, number],
- position: number
-): LovelaceConfig => {
- const view = config.views[path[0]];
-
- if (isStrategyView(view)) {
- throw new Error("You cannot move a card in a strategy view.");
- }
-
- const oldIndex = path[1];
- const newIndex = Math.max(Math.min(position - 1, view.cards!.length - 1), 0);
-
- const newCards = [...view.cards!];
+ const oldIndex = cardIndex;
+ const newIndex = Math.max(Math.min(index, newCards.length - 1), 0);
const card = newCards[oldIndex];
newCards.splice(oldIndex, 1);
newCards.splice(newIndex, 0, card);
- const newView = {
- ...view,
- cards: newCards,
- };
+ const newConfig = updateLovelaceCards(config, containerPath, newCards);
+ return newConfig;
+};
- return {
- ...config,
- views: config.views.map((origView, index) =>
- index === path[0] ? newView : origView
- ),
- };
+export const moveCardToContainer = (
+ config: LovelaceConfig,
+ fromPath: LovelaceCardPath,
+ toPath: LovelaceContainerPath
+): LovelaceConfig => {
+ const {
+ cardIndex: fromCardIndex,
+ viewIndex: fromViewIndex,
+ sectionIndex: fromSectionIndex,
+ } = parseLovelaceCardPath(fromPath);
+ const { viewIndex: toViewIndex, sectionIndex: toSectionIndex } =
+ parseLovelaceContainerPath(toPath);
+
+ if (fromViewIndex === toViewIndex && fromSectionIndex === toSectionIndex) {
+ throw new Error("You cannot move a card to the view or section it is in.");
+ }
+
+ const fromContainerPath = getLovelaceContainerPath(fromPath);
+ const cards = findLovelaceCards(config, fromContainerPath);
+ const card = cards![fromCardIndex];
+
+ let newConfig = addCard(config, toPath, card);
+ newConfig = deleteCard(newConfig, fromPath);
+
+ return newConfig;
};
export const moveCard = (
config: LovelaceConfig,
- fromPath: [number, number],
- toPath: [number]
+ fromPath: LovelaceCardPath,
+ toPath: LovelaceCardPath
): LovelaceConfig => {
- if (fromPath[0] === toPath[0]) {
- throw new Error("You cannot move a card to the view it is in.");
- }
- const fromView = config.views[fromPath[0]];
- const toView = config.views[toPath[0]];
+ const { cardIndex: fromCardIndex } = parseLovelaceCardPath(fromPath);
+ const fromContainerPath = getLovelaceContainerPath(fromPath);
+ const cards = findLovelaceCards(config, fromContainerPath);
+ const card = cards![fromCardIndex];
- if (isStrategyView(fromView)) {
- throw new Error("You cannot move a card from a strategy view.");
- }
+ let newConfig = deleteCard(config, fromPath);
+ newConfig = insertCard(newConfig, toPath, card);
- if (isStrategyView(toView)) {
- throw new Error("You cannot move a card to a strategy view.");
- }
-
- const card = fromView.cards![fromPath[1]];
-
- const newView1 = {
- ...fromView,
- cards: (fromView.cards || []).filter(
- (_origConf, ind) => ind !== fromPath[1]
- ),
- };
-
- const cards = toView.cards ? [...toView.cards, card] : [card];
-
- const newView2 = {
- ...toView,
- cards,
- };
-
- return {
- ...config,
- views: config.views.map((origView, index) =>
- index === toPath[0]
- ? newView2
- : index === fromPath[0]
- ? newView1
- : origView
- ),
- };
+ return newConfig;
};
export const addView = (
@@ -356,3 +220,84 @@ export const deleteView = (
...config,
views: config.views.filter((_origView, index) => index !== viewIndex),
});
+
+export const addSection = (
+ config: LovelaceConfig,
+ viewIndex: number,
+ sectionConfig: LovelaceSectionRawConfig
+): LovelaceConfig => {
+ const view = findLovelaceContainer(config, [viewIndex]) as LovelaceViewConfig;
+ if (isStrategyView(view)) {
+ throw new Error("Deleting sections in a strategy is not supported.");
+ }
+ const sections = view.sections
+ ? [...view.sections, sectionConfig]
+ : [sectionConfig];
+
+ const newConfig = updateLovelaceContainer(config, [viewIndex], {
+ ...view,
+ sections,
+ });
+ return newConfig;
+};
+
+export const deleteSection = (
+ config: LovelaceConfig,
+ viewIndex: number,
+ sectionIndex: number
+): LovelaceConfig => {
+ const view = findLovelaceContainer(config, [viewIndex]) as LovelaceViewConfig;
+ if (isStrategyView(view)) {
+ throw new Error("Deleting sections in a strategy is not supported.");
+ }
+ const sections = view.sections?.filter(
+ (_origSection, index) => index !== sectionIndex
+ );
+
+ const newConfig = updateLovelaceContainer(config, [viewIndex], {
+ ...view,
+ sections,
+ });
+ return newConfig;
+};
+
+export const insertSection = (
+ config: LovelaceConfig,
+ viewIndex: number,
+ sectionIndex: number,
+ sectionConfig: LovelaceSectionRawConfig
+): LovelaceConfig => {
+ const view = findLovelaceContainer(config, [viewIndex]) as LovelaceViewConfig;
+ if (isStrategyView(view)) {
+ throw new Error("Inserting sections in a strategy is not supported.");
+ }
+ const sections = view.sections
+ ? [
+ ...view.sections.slice(0, sectionIndex),
+ sectionConfig,
+ ...view.sections.slice(sectionIndex),
+ ]
+ : [sectionConfig];
+
+ const newConfig = updateLovelaceContainer(config, [viewIndex], {
+ ...view,
+ sections,
+ });
+ return newConfig;
+};
+
+export const moveSection = (
+ config: LovelaceConfig,
+ fromPath: [number, number],
+ toPath: [number, number]
+): LovelaceConfig => {
+ const section = findLovelaceContainer(
+ config,
+ fromPath
+ ) as LovelaceSectionRawConfig;
+
+ let newConfig = deleteSection(config, fromPath[0], fromPath[1]);
+ newConfig = insertSection(newConfig, toPath[0], toPath[1], section);
+
+ return newConfig;
+};
diff --git a/src/panels/lovelace/editor/delete-card.ts b/src/panels/lovelace/editor/delete-card.ts
index f4b2c08b09..f3264bc023 100644
--- a/src/panels/lovelace/editor/delete-card.ts
+++ b/src/panels/lovelace/editor/delete-card.ts
@@ -1,22 +1,29 @@
-import { isStrategyView } from "../../../data/lovelace/config/view";
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
import { HomeAssistant } from "../../../types";
import { showDeleteSuccessToast } from "../../../util/toast-deleted-success";
import { Lovelace } from "../types";
import { showDeleteCardDialog } from "./card-editor/show-delete-card-dialog";
import { deleteCard, insertCard } from "./config-util";
+import {
+ LovelaceCardPath,
+ findLovelaceContainer,
+ getLovelaceContainerPath,
+ parseLovelaceCardPath,
+} from "./lovelace-path";
export async function confDeleteCard(
element: HTMLElement,
hass: HomeAssistant,
lovelace: Lovelace,
- path: [number, number]
+ path: LovelaceCardPath
): Promise {
- const view = lovelace.config.views[path[0]];
- if (isStrategyView(view)) {
- throw new Error("Deleting cards in a strategy view is not supported.");
+ const containerPath = getLovelaceContainerPath(path);
+ const { cardIndex } = parseLovelaceCardPath(path);
+ const containerConfig = findLovelaceContainer(lovelace.config, containerPath);
+ if ("strategy" in containerConfig) {
+ throw new Error("Deleting cards in a strategy is not supported.");
}
- const cardConfig = view.cards![path[1]];
+ const cardConfig = containerConfig.cards![cardIndex];
showDeleteCardDialog(element, {
cardConfig,
deleteCard: async () => {
diff --git a/src/panels/lovelace/editor/lovelace-path.ts b/src/panels/lovelace/editor/lovelace-path.ts
new file mode 100644
index 0000000000..2eaf9dadc6
--- /dev/null
+++ b/src/panels/lovelace/editor/lovelace-path.ts
@@ -0,0 +1,197 @@
+import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import {
+ LovelaceSectionRawConfig,
+ isStrategySection,
+} from "../../../data/lovelace/config/section";
+import { LovelaceConfig } from "../../../data/lovelace/config/types";
+import {
+ LovelaceViewRawConfig,
+ isStrategyView,
+} from "../../../data/lovelace/config/view";
+
+export type LovelaceCardPath = [number, number] | [number, number, number];
+export type LovelaceContainerPath = [number] | [number, number];
+
+export const parseLovelaceCardPath = (
+ path: LovelaceCardPath
+): { viewIndex: number; sectionIndex?: number; cardIndex: number } => {
+ if (path.length === 2) {
+ return {
+ viewIndex: path[0],
+ cardIndex: path[1],
+ };
+ }
+ return {
+ viewIndex: path[0],
+ sectionIndex: path[1],
+ cardIndex: path[2],
+ };
+};
+
+export const parseLovelaceContainerPath = (
+ path: LovelaceContainerPath
+): { viewIndex: number; sectionIndex?: number } => {
+ if (path.length === 1) {
+ return {
+ viewIndex: path[0],
+ };
+ }
+ return {
+ viewIndex: path[0],
+ sectionIndex: path[1],
+ };
+};
+
+export const getLovelaceContainerPath = (
+ path: LovelaceCardPath
+): LovelaceContainerPath => path.slice(0, -1) as LovelaceContainerPath;
+
+export const findLovelaceContainer = (
+ config: LovelaceConfig,
+ path: LovelaceContainerPath
+): LovelaceViewRawConfig | LovelaceSectionRawConfig => {
+ const { viewIndex, sectionIndex } = parseLovelaceContainerPath(path);
+
+ const view = config.views[viewIndex];
+
+ if (!view) {
+ throw new Error("View does not exist");
+ }
+ if (sectionIndex === undefined) {
+ return view;
+ }
+ if (isStrategyView(view)) {
+ throw new Error("Can not find section in a strategy view");
+ }
+
+ const section = view.sections?.[sectionIndex];
+
+ if (!section) {
+ throw new Error("Section does not exist");
+ }
+ return section;
+};
+
+export const findLovelaceCards = (
+ config: LovelaceConfig,
+ path: LovelaceContainerPath
+): LovelaceCardConfig[] | undefined => {
+ const { viewIndex, sectionIndex } = parseLovelaceContainerPath(path);
+
+ const view = config.views[viewIndex];
+
+ if (!view) {
+ throw new Error("View does not exist");
+ }
+ if (isStrategyView(view)) {
+ throw new Error("Can not find cards in a strategy view");
+ }
+ if (sectionIndex === undefined) {
+ return view.cards;
+ }
+
+ const section = view.sections?.[sectionIndex];
+
+ if (!section) {
+ throw new Error("Section does not exist");
+ }
+ if (isStrategySection(section)) {
+ throw new Error("Can not find cards in a strategy section");
+ }
+ return section.cards;
+};
+
+export const updateLovelaceContainer = (
+ config: LovelaceConfig,
+ path: LovelaceContainerPath,
+ containerConfig: LovelaceViewRawConfig | LovelaceSectionRawConfig
+): LovelaceConfig => {
+ const { viewIndex, sectionIndex } = parseLovelaceContainerPath(path);
+
+ let updated = false;
+ const newViews = config.views.map((view, vIndex) => {
+ if (vIndex !== viewIndex) return view;
+
+ if (sectionIndex === undefined) {
+ updated = true;
+ return containerConfig;
+ }
+
+ if (isStrategyView(view)) {
+ throw new Error("Can not update section in a strategy view");
+ }
+
+ if (view.sections === undefined) {
+ throw new Error("Section does not exist");
+ }
+
+ const newSections = view.sections.map((section, sIndex) => {
+ if (sIndex !== sectionIndex) return section;
+ updated = true;
+ return containerConfig;
+ });
+ return {
+ ...view,
+ sections: newSections,
+ };
+ });
+
+ if (!updated) {
+ throw new Error("Can not update cards in a non-existing view/section");
+ }
+ return {
+ ...config,
+ views: newViews,
+ };
+};
+
+export const updateLovelaceCards = (
+ config: LovelaceConfig,
+ path: LovelaceContainerPath,
+ cards: LovelaceCardConfig[]
+): LovelaceConfig => {
+ const { viewIndex, sectionIndex } = parseLovelaceContainerPath(path);
+
+ let updated = false;
+ const newViews = config.views.map((view, vIndex) => {
+ if (vIndex !== viewIndex) return view;
+ if (isStrategyView(view)) {
+ throw new Error("Can not update cards in a strategy view");
+ }
+ if (sectionIndex === undefined) {
+ updated = true;
+ return {
+ ...view,
+ cards,
+ };
+ }
+
+ if (view.sections === undefined) {
+ throw new Error("Section does not exist");
+ }
+
+ const newSections = view.sections.map((section, sIndex) => {
+ if (sIndex !== sectionIndex) return section;
+ if (isStrategySection(section)) {
+ throw new Error("Can not update cards in a strategy section");
+ }
+ updated = true;
+ return {
+ ...section,
+ cards,
+ };
+ });
+ return {
+ ...view,
+ sections: newSections,
+ };
+ });
+
+ if (!updated) {
+ throw new Error("Can not update cards in a non-existing view/section");
+ }
+ return {
+ ...config,
+ views: newViews,
+ };
+};
diff --git a/src/panels/lovelace/editor/types.ts b/src/panels/lovelace/editor/types.ts
index 1edab843d1..44c42beac8 100644
--- a/src/panels/lovelace/editor/types.ts
+++ b/src/panels/lovelace/editor/types.ts
@@ -62,6 +62,7 @@ export interface Card {
description?: string;
showElement?: boolean;
isCustom?: boolean;
+ isSuggested?: boolean;
}
export interface HeaderFooter {
diff --git a/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts b/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts
index 98cd3f3163..dadd34449e 100644
--- a/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts
+++ b/src/panels/lovelace/editor/unused-entities/hui-unused-entities.ts
@@ -21,7 +21,10 @@ import "../card-editor/hui-entity-picker-table";
import { showSuggestCardDialog } from "../card-editor/show-suggest-card-dialog";
import { showSelectViewDialog } from "../select-view/show-select-view-dialog";
import { LovelaceConfig } from "../../../../data/lovelace/config/types";
-import { computeCards } from "../../common/generate-lovelace-config";
+import {
+ computeCards,
+ computeSection,
+} from "../../common/generate-lovelace-config";
@customElement("hui-unused-entities")
export class HuiUnusedEntities extends LitElement {
@@ -132,6 +135,8 @@ export class HuiUnusedEntities extends LitElement {
this._selectedEntities,
{}
);
+ const sectionConfig = computeSection(this._selectedEntities, {});
+
if (this.lovelace.config.views.length === 1) {
showSuggestCardDialog(this, {
lovelaceConfig: this.lovelace.config!,
@@ -139,6 +144,7 @@ export class HuiUnusedEntities extends LitElement {
path: [0],
entities: this._selectedEntities,
cardConfig,
+ sectionConfig,
});
return;
}
@@ -152,6 +158,7 @@ export class HuiUnusedEntities extends LitElement {
path: [viewIndex],
entities: this._selectedEntities,
cardConfig,
+ sectionConfig,
});
},
});
diff --git a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts
index a16f8237f4..038680b049 100644
--- a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts
+++ b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts
@@ -4,16 +4,16 @@ import { mdiCheck, mdiClose, mdiDotsVertical } from "@mdi/js";
import "@polymer/paper-tabs/paper-tab";
import "@polymer/paper-tabs/paper-tabs";
import {
- css,
CSSResultGroup,
- html,
LitElement,
- nothing,
PropertyValues,
+ css,
+ html,
+ nothing,
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
-import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
+import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event";
import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { navigate } from "../../../../common/navigate";
import { deepEqual } from "../../../../common/util/deep-equal";
@@ -23,6 +23,11 @@ import "../../../../components/ha-dialog";
import "../../../../components/ha-dialog-header";
import "../../../../components/ha-yaml-editor";
import type { HaYamlEditor } from "../../../../components/ha-yaml-editor";
+import { LovelaceBadgeConfig } from "../../../../data/lovelace/config/badge";
+import {
+ LovelaceViewConfig,
+ isStrategyView,
+} from "../../../../data/lovelace/config/view";
import {
showAlertDialog,
showConfirmationDialog,
@@ -33,6 +38,7 @@ import "../../components/hui-entity-editor";
import {
DEFAULT_VIEW_LAYOUT,
PANEL_VIEW_LAYOUT,
+ SECTION_VIEW_LAYOUT,
VIEWS_NO_BADGE_SUPPORT,
} from "../../views/const";
import { addView, deleteView, replaceView } from "../config-util";
@@ -46,12 +52,6 @@ import {
import "./hui-view-editor";
import "./hui-view-visibility-editor";
import { EditViewDialogParams } from "./show-edit-view-dialog";
-import {
- LovelaceViewConfig,
- isStrategyView,
-} from "../../../../data/lovelace/config/view";
-import { LovelaceBadgeConfig } from "../../../../data/lovelace/config/badge";
-import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
@customElement("hui-dialog-edit-view")
export class HuiDialogEditView extends LitElement {
@@ -63,8 +63,6 @@ export class HuiDialogEditView extends LitElement {
@state() private _badges?: LovelaceBadgeConfig[];
- @state() private _cards?: LovelaceCardConfig[];
-
@state() private _saving = false;
@state() private _curTab?: string;
@@ -102,7 +100,6 @@ export class HuiDialogEditView extends LitElement {
if (this._params.viewIndex === undefined) {
this._config = {};
this._badges = [];
- this._cards = [];
this._dirty = false;
return;
}
@@ -112,13 +109,11 @@ export class HuiDialogEditView extends LitElement {
const { strategy, ...viewConfig } = view;
this._config = viewConfig;
this._badges = [];
- this._cards = [];
return;
}
- const { cards, badges, ...viewConfig } = view;
+ const { badges, ...viewConfig } = view;
this._config = viewConfig;
this._badges = badges ? processEditorEntities(badges) : [];
- this._cards = cards;
}
public closeDialog(): void {
@@ -181,7 +176,7 @@ export class HuiDialogEditView extends LitElement {
)}
`
- : ""}
+ : nothing}
${this._badges.map(
(badgeConfig) => html`
@@ -193,7 +188,7 @@ export class HuiDialogEditView extends LitElement {
)}
`
- : ""}
+ : nothing}
`
- : ""}
+ : nothing}
${content}
${this._params.viewIndex !== undefined
@@ -312,10 +307,7 @@ export class HuiDialogEditView extends LitElement {
)}
`
- : ""}
- ${this.hass!.localize("ui.common.cancel")}
+ : nothing}
`
- : ""}
+ : nothing}
${this.hass!.localize("ui.common.save")}
@@ -364,24 +356,28 @@ export class HuiDialogEditView extends LitElement {
}
}
- private _deleteConfirm(): void {
- showConfirmationDialog(this, {
- title: this.hass!.localize(
- `ui.panel.lovelace.views.confirm_delete${
- this._cards?.length ? `_existing_cards` : ""
- }`
- ),
+ private async _deleteConfirm() {
+ const type = this._config?.sections?.length
+ ? "sections"
+ : this._config?.cards?.length
+ ? "cards"
+ : "only";
+
+ const named = this._config?.title ? "named" : "unnamed";
+
+ const confirm = await showConfirmationDialog(this, {
+ title: this.hass!.localize("ui.panel.lovelace.views.delete_title"),
text: this.hass!.localize(
- `ui.panel.lovelace.views.confirm_delete${
- this._cards?.length ? "_existing_cards" : ""
- }_text`,
- {
- name: this._config?.title || "Unnamed view",
- number: this._cards?.length || 0,
- }
+ `ui.panel.lovelace.views.delete_${named}_view_${type}`,
+ { name: this._config?.title }
),
- confirm: () => this._delete(),
+ confirmText: this.hass!.localize("ui.common.delete"),
+ destructive: true,
});
+
+ if (!confirm) return;
+
+ this._delete();
}
private _handleTabSelected(ev: CustomEvent): void {
@@ -405,9 +401,18 @@ export class HuiDialogEditView extends LitElement {
const viewConf: LovelaceViewConfig = {
...this._config,
badges: this._badges,
- cards: this._cards,
};
+ if (viewConf.type === SECTION_VIEW_LAYOUT && !viewConf.sections?.length) {
+ viewConf.sections = [{ cards: [] }];
+ } else if (!viewConf.cards?.length) {
+ viewConf.cards = [];
+ }
+
+ if (!viewConf.badges?.length) {
+ delete viewConf.badges;
+ }
+
const lovelace = this._params.lovelace!;
try {
@@ -472,7 +477,7 @@ export class HuiDialogEditView extends LitElement {
if (!ev.detail.isValid) {
return;
}
- const { badges = [], ...config } = ev.detail.value;
+ const { badges, ...config } = ev.detail.value;
this._config = config;
this._badges = badges;
this._dirty = true;
diff --git a/src/panels/lovelace/editor/view-editor/hui-view-editor.ts b/src/panels/lovelace/editor/view-editor/hui-view-editor.ts
index b693848a8d..d0c4f24d53 100644
--- a/src/panels/lovelace/editor/view-editor/hui-view-editor.ts
+++ b/src/panels/lovelace/editor/view-editor/hui-view-editor.ts
@@ -5,14 +5,18 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import { slugify } from "../../../../common/string/slugify";
import type { LocalizeFunc } from "../../../../common/translations/localize";
import "../../../../components/ha-form/ha-form";
-import type { SchemaUnion } from "../../../../components/ha-form/types";
+import type {
+ HaFormSchema,
+ SchemaUnion,
+} from "../../../../components/ha-form/types";
+import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../../types";
import {
DEFAULT_VIEW_LAYOUT,
+ SECTION_VIEW_LAYOUT,
PANEL_VIEW_LAYOUT,
SIDEBAR_VIEW_LAYOUT,
} from "../../views/const";
-import { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
declare global {
interface HASSDomEvents {
@@ -33,7 +37,7 @@ export class HuiViewEditor extends LitElement {
private _suggestedPath = false;
private _schema = memoizeOne(
- (localize: LocalizeFunc) =>
+ (localize: LocalizeFunc, currentType: string, isNew: boolean) =>
[
{ name: "title", selector: { text: {} } },
{
@@ -53,12 +57,18 @@ export class HuiViewEditor extends LitElement {
DEFAULT_VIEW_LAYOUT,
SIDEBAR_VIEW_LAYOUT,
PANEL_VIEW_LAYOUT,
+ SECTION_VIEW_LAYOUT,
] as const
).map((type) => ({
value: type,
label: localize(
`ui.panel.lovelace.editor.edit_view.types.${type}`
),
+ disabled:
+ !isNew &&
+ (currentType === SECTION_VIEW_LAYOUT
+ ? type !== SECTION_VIEW_LAYOUT
+ : type === SECTION_VIEW_LAYOUT),
})),
},
},
@@ -69,7 +79,7 @@ export class HuiViewEditor extends LitElement {
boolean: {},
},
},
- ] as const
+ ] as const satisfies HaFormSchema[]
);
set config(config: LovelaceViewConfig) {
@@ -90,7 +100,7 @@ export class HuiViewEditor extends LitElement {
return nothing;
}
- const schema = this._schema(this.hass.localize);
+ const schema = this._schema(this.hass.localize, this._type, this.isNew);
const data = {
...this._config,
@@ -154,6 +164,15 @@ export class HuiViewEditor extends LitElement {
return this.hass.localize(
"ui.panel.lovelace.editor.edit_view.subview_helper"
);
+ case "type":
+ if (this.isNew) return undefined;
+ return this._type === "sections"
+ ? this.hass.localize(
+ "ui.panel.lovelace.editor.edit_view.type_helper_others"
+ )
+ : this.hass.localize(
+ "ui.panel.lovelace.editor.edit_view.type_helper_sections"
+ );
default:
return undefined;
}
diff --git a/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts b/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts
index 6c757e22d7..128a80808a 100644
--- a/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts
+++ b/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts
@@ -14,6 +14,7 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { EntityConfig, LovelaceRow } from "./types";
+import { callProtectedLockService } from "../../../data/lock";
@customElement("hui-lock-entity-row")
class HuiLockEntityRow extends LitElement implements LovelaceRow {
@@ -75,10 +76,11 @@ class HuiLockEntityRow extends LitElement implements LovelaceRow {
private _callService(ev): void {
ev.stopPropagation();
const stateObj = this.hass!.states[this._config!.entity];
- this.hass!.callService(
- "lock",
- stateObj.state === "locked" ? "unlock" : "lock",
- { entity_id: stateObj.entity_id }
+ callProtectedLockService(
+ this,
+ this.hass!,
+ stateObj,
+ stateObj.state === "locked" ? "unlock" : "lock"
);
}
}
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 13afe9d3c5..1b57c6ee41 100644
--- a/src/panels/lovelace/entity-rows/hui-number-entity-row.ts
+++ b/src/panels/lovelace/entity-rows/hui-number-entity-row.ts
@@ -139,6 +139,7 @@ class HuiNumberEntityRow extends LitElement implements LovelaceRow {
}
ha-textfield {
text-align: end;
+ direction: ltr !important;
}
ha-slider {
width: 100%;
diff --git a/src/panels/lovelace/entity-rows/hui-script-entity-row.ts b/src/panels/lovelace/entity-rows/hui-script-entity-row.ts
index 6fa20512ea..1147d405b4 100644
--- a/src/panels/lovelace/entity-rows/hui-script-entity-row.ts
+++ b/src/panels/lovelace/entity-rows/hui-script-entity-row.ts
@@ -15,6 +15,8 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { ActionRowConfig, LovelaceRow } from "./types";
+import { computeObjectId } from "../../../common/entity/compute_object_id";
+import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog";
@customElement("hui-script-entity-row")
class HuiScriptEntityRow extends LitElement implements LovelaceRow {
@@ -92,7 +94,15 @@ class HuiScriptEntityRow extends LitElement implements LovelaceRow {
private _runScript(ev): void {
ev.stopPropagation();
- this._callService("turn_on");
+
+ const fields =
+ this.hass!.services.script[computeObjectId(this._config!.entity)]?.fields;
+
+ if (fields && Object.keys(fields).length > 0) {
+ showMoreInfoDialog(this, { entityId: this._config!.entity });
+ } else {
+ this._callService("turn_on");
+ }
}
private _callService(service: string): void {
diff --git a/src/panels/lovelace/sections/const.ts b/src/panels/lovelace/sections/const.ts
new file mode 100644
index 0000000000..8551f0fe92
--- /dev/null
+++ b/src/panels/lovelace/sections/const.ts
@@ -0,0 +1,2 @@
+export const GRID_SECTION_LAYOUT = "grid";
+export const DEFAULT_SECTION_LAYOUT = GRID_SECTION_LAYOUT;
diff --git a/src/panels/lovelace/sections/hui-error-section.ts b/src/panels/lovelace/sections/hui-error-section.ts
new file mode 100644
index 0000000000..801f6f0379
--- /dev/null
+++ b/src/panels/lovelace/sections/hui-error-section.ts
@@ -0,0 +1,60 @@
+import { html, LitElement, nothing } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import "../../../components/ha-label-badge";
+import "../../../components/ha-svg-icon";
+import { LovelaceSectionElement } from "../../../data/lovelace";
+import { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
+import { HomeAssistant } from "../../../types";
+
+export interface ErrorSectionConfig extends LovelaceSectionConfig {
+ error: string;
+}
+
+export const createErrorSectionElement = (config: ErrorSectionConfig) => {
+ const el = document.createElement(
+ "hui-error-section"
+ ) as LovelaceSectionElement;
+ el.setConfig(config);
+ return el;
+};
+
+export const createErrorSectionConfig = (
+ error: string
+): ErrorSectionConfig => ({
+ type: "error",
+ error,
+});
+
+@customElement("hui-error-section")
+export class HuiErrorSection
+ extends LitElement
+ implements LovelaceSectionElement
+{
+ public hass?: HomeAssistant;
+
+ @property({ type: Boolean }) public isStrategy = false;
+
+ @state() private _config?: ErrorSectionConfig;
+
+ public setConfig(config: ErrorSectionConfig): void {
+ this._config = config;
+ }
+
+ protected render() {
+ if (!this._config) {
+ return nothing;
+ }
+
+ // Todo improve
+ return html`
+ Error
+ ${this._config.error}
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-error-section": HuiErrorSection;
+ }
+}
diff --git a/src/panels/lovelace/sections/hui-grid-section.ts b/src/panels/lovelace/sections/hui-grid-section.ts
new file mode 100644
index 0000000000..b63e9fac8f
--- /dev/null
+++ b/src/panels/lovelace/sections/hui-grid-section.ts
@@ -0,0 +1,246 @@
+import { mdiPlus } from "@mdi/js";
+import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
+import { property, state } from "lit/decorators";
+import { classMap } from "lit/directives/class-map";
+import { repeat } from "lit/directives/repeat";
+import { styleMap } from "lit/directives/style-map";
+import { fireEvent } from "../../../common/dom/fire_event";
+import type { HaSortableOptions } from "../../../components/ha-sortable";
+import { LovelaceSectionElement } from "../../../data/lovelace";
+import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
+import { haStyle } from "../../../resources/styles";
+import type { HomeAssistant } from "../../../types";
+import { HuiErrorCard } from "../cards/hui-error-card";
+import "../components/hui-card-edit-mode";
+import { moveCard } from "../editor/config-util";
+import type { Lovelace, LovelaceCard } from "../types";
+
+const CARD_SORTABLE_OPTIONS: HaSortableOptions = {
+ delay: 100,
+ delayOnTouchOnly: true,
+ direction: "vertical",
+ invertedSwapThreshold: 0.7,
+} as HaSortableOptions;
+
+export class GridSection extends LitElement implements LovelaceSectionElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false }) public lovelace?: Lovelace;
+
+ @property({ type: Number }) public index?: number;
+
+ @property({ type: Number }) public viewIndex?: number;
+
+ @property({ type: Boolean }) public isStrategy = false;
+
+ @property({ attribute: false }) public cards: Array<
+ LovelaceCard | HuiErrorCard
+ > = [];
+
+ @state() _config?: LovelaceSectionConfig;
+
+ @state() _dragging = false;
+
+ public setConfig(config: LovelaceSectionConfig): void {
+ this._config = config;
+ }
+
+ private _cardConfigKeys = new WeakMap();
+
+ private _getKey(cardConfig: LovelaceCardConfig) {
+ if (!this._cardConfigKeys.has(cardConfig)) {
+ this._cardConfigKeys.set(cardConfig, Math.random().toString());
+ }
+ return this._cardConfigKeys.get(cardConfig)!;
+ }
+
+ render() {
+ if (!this.cards || !this._config) return nothing;
+
+ const cardsConfig = this._config?.cards ?? [];
+
+ const editMode = Boolean(this.lovelace?.editMode && !this.isStrategy);
+
+ return html`
+ ${this._config.title || this.lovelace?.editMode
+ ? html`
+
+ ${this._config.title ||
+ this.hass.localize(
+ "ui.panel.lovelace.editor.section.unnamed_section"
+ )}
+
+ `
+ : nothing}
+
+
+ ${repeat(
+ cardsConfig,
+ (cardConfig) => this._getKey(cardConfig),
+ (_cardConfig, idx) => {
+ const card = this.cards![idx];
+ (card as any).editMode = editMode;
+ const size = card && (card as any).getGridSize?.();
+ return html`
+
+ ${editMode
+ ? html`
+
+ ${card}
+
+ `
+ : card}
+
+ `;
+ }
+ )}
+ ${editMode
+ ? html`
+
+
+
+ `
+ : nothing}
+
+
+ `;
+ }
+
+ private _cardMoved(ev) {
+ ev.stopPropagation();
+ const { oldIndex, newIndex, oldPath, newPath } = ev.detail;
+ const newConfig = moveCard(
+ this.lovelace!.config,
+ [...oldPath, oldIndex] as [number, number, number],
+ [...newPath, newIndex] as [number, number, number]
+ );
+ this.lovelace!.saveConfig(newConfig);
+ }
+
+ private _dragStart() {
+ this._dragging = true;
+ }
+
+ private _dragEnd() {
+ this._dragging = false;
+ }
+
+ private _addCard() {
+ fireEvent(this, "ll-create-card", { suggested: ["tile"] });
+ }
+
+ static get styles(): CSSResultGroup {
+ return [
+ haStyle,
+ css`
+ :host {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ }
+ .container {
+ --column-count: 4;
+ display: grid;
+ grid-template-columns: repeat(var(--column-count), minmax(0, 1fr));
+ grid-auto-rows: minmax(66px, auto);
+ gap: 8px;
+ padding: 0;
+ margin: 0 auto;
+ }
+
+ .container.edit-mode {
+ padding: 8px;
+ border-radius: var(--ha-card-border-radius, 12px);
+ border: 2px dashed var(--divider-color);
+ min-height: 66px;
+ }
+
+ .title {
+ color: var(--primary-text-color);
+ font-size: 20px;
+ font-weight: normal;
+ margin: 0px;
+ letter-spacing: 0.1px;
+ line-height: 32px;
+ min-height: 32px;
+ display: block;
+ padding: 24px 10px 10px;
+ }
+
+ .title.placeholder {
+ color: var(--secondary-text-color);
+ font-style: italic;
+ }
+
+ .card {
+ border-radius: var(--ha-card-border-radius, 12px);
+ position: relative;
+ grid-row: span var(--row-size, 1);
+ grid-column: span var(--column-size, 4);
+ }
+
+ .add {
+ outline: none;
+ grid-row: span var(--row-size, 1);
+ grid-column: span var(--column-size, 2);
+ background: none;
+ cursor: pointer;
+ border-radius: var(--ha-card-border-radius, 12px);
+ border: 2px dashed var(--primary-color);
+ height: 66px;
+ order: 1;
+ }
+ .add:focus {
+ border-style: solid;
+ }
+ .sortable-ghost {
+ border-radius: var(--ha-card-border-radius, 12px);
+ }
+ `,
+ ];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-grid-section": GridSection;
+ }
+}
+
+customElements.define("hui-grid-section", GridSection);
diff --git a/src/panels/lovelace/sections/hui-section.ts b/src/panels/lovelace/sections/hui-section.ts
new file mode 100644
index 0000000000..b50b1df18a
--- /dev/null
+++ b/src/panels/lovelace/sections/hui-section.ts
@@ -0,0 +1,247 @@
+import { PropertyValues, ReactiveElement } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import "../../../components/ha-svg-icon";
+import type { LovelaceSectionElement } from "../../../data/lovelace";
+import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import {
+ LovelaceSectionConfig,
+ LovelaceSectionRawConfig,
+ isStrategySection,
+} from "../../../data/lovelace/config/section";
+import type { HomeAssistant } from "../../../types";
+import type { HuiErrorCard } from "../cards/hui-error-card";
+import { createCardElement } from "../create-element/create-card-element";
+import {
+ createErrorCardConfig,
+ createErrorCardElement,
+} from "../create-element/create-element-base";
+import { createSectionElement } from "../create-element/create-section-element";
+import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
+import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
+import { deleteCard } from "../editor/config-util";
+import { confDeleteCard } from "../editor/delete-card";
+import { parseLovelaceCardPath } from "../editor/lovelace-path";
+import { generateLovelaceSectionStrategy } from "../strategies/get-strategy";
+import type { Lovelace, LovelaceCard } from "../types";
+import { DEFAULT_SECTION_LAYOUT } from "./const";
+
+@customElement("hui-section")
+export class HuiSection extends ReactiveElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false }) public lovelace!: Lovelace;
+
+ @property({ attribute: false }) public config!: LovelaceSectionRawConfig;
+
+ @property({ type: Number }) public index!: number;
+
+ @property({ type: Number }) public viewIndex!: number;
+
+ @state() private _cards: Array = [];
+
+ private _layoutElementType?: string;
+
+ private _layoutElement?: LovelaceSectionElement;
+
+ // Public to make demo happy
+ public createCardElement(cardConfig: LovelaceCardConfig) {
+ const element = createCardElement(cardConfig) as LovelaceCard;
+ try {
+ element.hass = this.hass;
+ } catch (e: any) {
+ return createErrorCardElement(
+ createErrorCardConfig(e.message, cardConfig)
+ );
+ }
+ element.addEventListener(
+ "ll-rebuild",
+ (ev: Event) => {
+ // In edit mode let it go to hui-root and rebuild whole section.
+ if (!this.lovelace!.editMode) {
+ ev.stopPropagation();
+ this._rebuildCard(element, cardConfig);
+ }
+ },
+ { once: true }
+ );
+ return element;
+ }
+
+ protected createRenderRoot() {
+ return this;
+ }
+
+ public willUpdate(changedProperties: PropertyValues): void {
+ super.willUpdate(changedProperties);
+
+ /*
+ We need to handle the following use cases:
+ - initialization: create layout element, populate
+ - config changed to section with same layout element
+ - config changed to section with different layout element
+ - forwarded properties hass/narrow/lovelace/cards change
+ - cards change if one is rebuild when it was loaded later
+ - lovelace changes if edit mode is enabled or config has changed
+ */
+
+ const oldConfig = changedProperties.get("config");
+
+ // If config has changed, create element if necessary and set all values.
+ if (
+ changedProperties.has("config") &&
+ (!oldConfig || this.config !== oldConfig)
+ ) {
+ this._initializeConfig();
+ }
+ }
+
+ protected update(changedProperties) {
+ super.update(changedProperties);
+
+ // If no layout element, we're still creating one
+ if (this._layoutElement) {
+ // Config has not changed. Just props
+ if (changedProperties.has("hass")) {
+ this._cards.forEach((element) => {
+ try {
+ element.hass = this.hass;
+ } catch (e: any) {
+ this._rebuildCard(element, createErrorCardConfig(e.message, null));
+ }
+ });
+
+ this._layoutElement.hass = this.hass;
+ }
+ if (changedProperties.has("lovelace")) {
+ this._layoutElement.lovelace = this.lovelace;
+ }
+ if (changedProperties.has("_cards")) {
+ this._layoutElement.cards = this._cards;
+ }
+ }
+ }
+
+ private async _initializeConfig() {
+ let sectionConfig = { ...this.config };
+ let isStrategy = false;
+
+ if (isStrategySection(sectionConfig)) {
+ isStrategy = true;
+ sectionConfig = await generateLovelaceSectionStrategy(
+ sectionConfig.strategy,
+ this.hass!
+ );
+ }
+
+ sectionConfig = {
+ ...sectionConfig,
+ type: sectionConfig.type || DEFAULT_SECTION_LAYOUT,
+ };
+
+ // Create a new layout element if necessary.
+ let addLayoutElement = false;
+
+ if (
+ !this._layoutElement ||
+ this._layoutElementType !== sectionConfig.type
+ ) {
+ addLayoutElement = true;
+ this._createLayoutElement(sectionConfig);
+ }
+
+ this._createCards(sectionConfig);
+ this._layoutElement!.isStrategy = isStrategy;
+ this._layoutElement!.hass = this.hass;
+ this._layoutElement!.lovelace = this.lovelace;
+ this._layoutElement!.index = this.index;
+ this._layoutElement!.viewIndex = this.viewIndex;
+ this._layoutElement!.cards = this._cards;
+
+ if (addLayoutElement) {
+ while (this.lastChild) {
+ this.removeChild(this.lastChild);
+ }
+ this.appendChild(this._layoutElement!);
+ }
+ }
+
+ private _createLayoutElement(config: LovelaceSectionConfig): void {
+ this._layoutElement = createSectionElement(
+ config
+ ) as LovelaceSectionElement;
+ this._layoutElementType = config.type;
+ this._layoutElement.addEventListener("ll-create-card", (ev) => {
+ ev.stopPropagation();
+ showCreateCardDialog(this, {
+ lovelaceConfig: this.lovelace.config,
+ saveConfig: this.lovelace.saveConfig,
+ path: [this.viewIndex, this.index],
+ suggestedCards: ev.detail?.suggested,
+ });
+ });
+ this._layoutElement.addEventListener("ll-edit-card", (ev) => {
+ ev.stopPropagation();
+ const { cardIndex } = parseLovelaceCardPath(ev.detail.path);
+ showEditCardDialog(this, {
+ lovelaceConfig: this.lovelace.config,
+ saveConfig: this.lovelace.saveConfig,
+ path: [this.viewIndex, this.index],
+ cardIndex,
+ });
+ });
+ this._layoutElement.addEventListener("ll-delete-card", (ev) => {
+ ev.stopPropagation();
+ if (ev.detail.confirm) {
+ confDeleteCard(this, this.hass!, this.lovelace!, ev.detail.path);
+ } else {
+ const newLovelace = deleteCard(this.lovelace!.config, ev.detail.path);
+ this.lovelace.saveConfig(newLovelace);
+ }
+ });
+ }
+
+ private _createCards(config: LovelaceSectionConfig): void {
+ if (!config || !config.cards || !Array.isArray(config.cards)) {
+ this._cards = [];
+ return;
+ }
+
+ this._cards = config.cards.map((cardConfig) => {
+ const element = this.createCardElement(cardConfig);
+ try {
+ element.hass = this.hass;
+ } catch (e: any) {
+ return createErrorCardElement(
+ createErrorCardConfig(e.message, cardConfig)
+ );
+ }
+ return element;
+ });
+ }
+
+ private _rebuildCard(
+ cardElToReplace: LovelaceCard,
+ config: LovelaceCardConfig
+ ): void {
+ let newCardEl = this.createCardElement(config);
+ try {
+ newCardEl.hass = this.hass;
+ } catch (e: any) {
+ newCardEl = createErrorCardElement(
+ createErrorCardConfig(e.message, config)
+ );
+ }
+ if (cardElToReplace.parentElement) {
+ cardElToReplace.parentElement!.replaceChild(newCardEl, cardElToReplace);
+ }
+ this._cards = this._cards!.map((curCardEl) =>
+ curCardEl === cardElToReplace ? newCardEl : curCardEl
+ );
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-section": HuiSection;
+ }
+}
diff --git a/src/panels/lovelace/strategies/get-strategy.ts b/src/panels/lovelace/strategies/get-strategy.ts
index ee62115275..927089dedd 100644
--- a/src/panels/lovelace/strategies/get-strategy.ts
+++ b/src/panels/lovelace/strategies/get-strategy.ts
@@ -12,6 +12,7 @@ import { AsyncReturnType, HomeAssistant } from "../../../types";
import { cleanLegacyStrategyConfig, isLegacyStrategy } from "./legacy-strategy";
import {
LovelaceDashboardStrategy,
+ LovelaceSectionStrategy,
LovelaceStrategy,
LovelaceViewStrategy,
} from "./types";
@@ -27,13 +28,15 @@ const STRATEGIES: Record> = {
"original-states": () => import("./original-states-view-strategy"),
energy: () => import("../../energy/strategies/energy-view-strategy"),
},
+ section: {},
};
-export type LovelaceStrategyConfigType = "dashboard" | "view";
+export type LovelaceStrategyConfigType = "dashboard" | "view" | "section";
type Strategies = {
dashboard: LovelaceDashboardStrategy;
view: LovelaceViewStrategy;
+ section: LovelaceSectionStrategy;
};
type StrategyConfig = AsyncReturnType<
@@ -163,6 +166,24 @@ export const generateLovelaceViewStrategy = async (
hass
);
+export const generateLovelaceSectionStrategy = async (
+ strategyConfig: LovelaceStrategyConfig,
+ hass: HomeAssistant
+): Promise =>
+ generateStrategy(
+ "section",
+ (err) => ({
+ cards: [
+ {
+ type: "markdown",
+ content: `Error loading the section strategy:\n> ${err}`,
+ },
+ ],
+ }),
+ strategyConfig,
+ hass
+ );
+
/**
* Find all references to strategies and replaces them with the generated output
*/
@@ -175,11 +196,24 @@ export const expandLovelaceConfigStrategies = async (
: { ...config };
newConfig.views = await Promise.all(
- newConfig.views.map((view) =>
- isStrategyView(view)
- ? generateLovelaceViewStrategy(view.strategy, hass)
- : view
- )
+ newConfig.views.map(async (view) => {
+ const newView = isStrategyView(view)
+ ? await generateLovelaceViewStrategy(view.strategy, hass)
+ : { ...view };
+
+ if (newView.sections) {
+ newView.sections = await Promise.all(
+ newView.sections.map(async (section) => {
+ const newSection = isStrategyView(section)
+ ? await generateLovelaceSectionStrategy(section.strategy, hass)
+ : { ...section };
+ return newSection;
+ })
+ );
+ }
+
+ return newView;
+ })
);
return newConfig;
diff --git a/src/panels/lovelace/strategies/types.ts b/src/panels/lovelace/strategies/types.ts
index da2ab8ee3c..ae1be1bbca 100644
--- a/src/panels/lovelace/strategies/types.ts
+++ b/src/panels/lovelace/strategies/types.ts
@@ -1,5 +1,6 @@
-import { LovelaceConfig } from "../../../data/lovelace/config/types";
+import { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
+import { LovelaceConfig } from "../../../data/lovelace/config/types";
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import { HomeAssistant } from "../../../types";
import { LovelaceGenericElementEditor } from "../types";
@@ -15,6 +16,9 @@ export interface LovelaceDashboardStrategy
export interface LovelaceViewStrategy
extends LovelaceStrategy {}
+export interface LovelaceSectionStrategy
+ extends LovelaceStrategy {}
+
export interface LovelaceStrategyEditor extends LovelaceGenericElementEditor {
setConfig(config: LovelaceStrategyConfig): void;
}
diff --git a/src/panels/lovelace/types.ts b/src/panels/lovelace/types.ts
index b1d42984b8..31a87961f2 100644
--- a/src/panels/lovelace/types.ts
+++ b/src/panels/lovelace/types.ts
@@ -44,6 +44,7 @@ export interface LovelaceCard extends HTMLElement {
isPanel?: boolean;
editMode?: boolean;
getCardSize(): number | Promise;
+ getGridSize?(): [number, number];
setConfig(config: LovelaceCardConfig): void;
}
diff --git a/src/panels/lovelace/views/const.ts b/src/panels/lovelace/views/const.ts
index 5cc4709bbb..5633f05bbc 100644
--- a/src/panels/lovelace/views/const.ts
+++ b/src/panels/lovelace/views/const.ts
@@ -1,4 +1,9 @@
export const DEFAULT_VIEW_LAYOUT = "masonry";
export const PANEL_VIEW_LAYOUT = "panel";
export const SIDEBAR_VIEW_LAYOUT = "sidebar";
-export const VIEWS_NO_BADGE_SUPPORT = [PANEL_VIEW_LAYOUT, SIDEBAR_VIEW_LAYOUT];
+export const SECTION_VIEW_LAYOUT = "sections";
+export const VIEWS_NO_BADGE_SUPPORT = [
+ PANEL_VIEW_LAYOUT,
+ SIDEBAR_VIEW_LAYOUT,
+ SECTION_VIEW_LAYOUT,
+];
diff --git a/src/panels/lovelace/views/hui-sections-view.ts b/src/panels/lovelace/views/hui-sections-view.ts
new file mode 100644
index 0000000000..cbf5af8570
--- /dev/null
+++ b/src/panels/lovelace/views/hui-sections-view.ts
@@ -0,0 +1,321 @@
+import { mdiArrowAll, mdiDelete, mdiPencil, mdiViewGridPlus } from "@mdi/js";
+import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import { repeat } from "lit/directives/repeat";
+import { styleMap } from "lit/directives/style-map";
+import "../../../components/ha-icon-button";
+import "../../../components/ha-sortable";
+import "../../../components/ha-svg-icon";
+import type { LovelaceViewElement } from "../../../data/lovelace";
+import { LovelaceSectionConfig as LovelaceRawSectionConfig } from "../../../data/lovelace/config/section";
+import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
+import {
+ showConfirmationDialog,
+ showPromptDialog,
+} from "../../../dialogs/generic/show-dialog-box";
+import type { HomeAssistant } from "../../../types";
+import { addSection, deleteSection, moveSection } from "../editor/config-util";
+import {
+ findLovelaceContainer,
+ updateLovelaceContainer,
+} from "../editor/lovelace-path";
+import { HuiSection } from "../sections/hui-section";
+import type { Lovelace } from "../types";
+
+@customElement("hui-sections-view")
+export class SectionsView extends LitElement implements LovelaceViewElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false }) public lovelace?: Lovelace;
+
+ @property({ type: Number }) public index?: number;
+
+ @property({ type: Boolean }) public isStrategy = false;
+
+ @property({ attribute: false }) public sections: HuiSection[] = [];
+
+ @state() private _config?: LovelaceViewConfig;
+
+ public setConfig(config: LovelaceViewConfig): void {
+ this._config = config;
+ }
+
+ private _sectionConfigKeys = new WeakMap();
+
+ private _getKey(sectionConfig: LovelaceRawSectionConfig) {
+ if (!this._sectionConfigKeys.has(sectionConfig)) {
+ this._sectionConfigKeys.set(sectionConfig, Math.random().toString());
+ }
+ return this._sectionConfigKeys.get(sectionConfig)!;
+ }
+
+ protected render() {
+ if (!this.lovelace) return nothing;
+
+ const sectionsConfig = this._config?.sections ?? [];
+
+ const editMode = this.lovelace.editMode;
+
+ return html`
+
+
+ ${repeat(
+ sectionsConfig,
+ (sectionConfig) => this._getKey(sectionConfig),
+ (_sectionConfig, idx) => {
+ const section = this.sections[idx];
+ (section as any).itemPath = [idx];
+ return html`
+
+ ${editMode
+ ? html`
+
+ `
+ : nothing}
+
${section}
+
+ `;
+ }
+ )}
+ ${editMode
+ ? html`
+
+
+
+ `
+ : nothing}
+
+
+ `;
+ }
+
+ private _addSection(): void {
+ const newConfig = addSection(this.lovelace!.config, this.index!, {
+ type: "grid",
+ cards: [],
+ });
+ this.lovelace!.saveConfig(newConfig);
+ }
+
+ private async _editSection(ev) {
+ const index = ev.currentTarget.index;
+
+ const path = [this.index!, index] as [number, number];
+
+ const section = findLovelaceContainer(
+ this.lovelace!.config,
+ path
+ ) as LovelaceRawSectionConfig;
+
+ const newTitle = !section.title;
+
+ const title = await showPromptDialog(this, {
+ title: this.hass.localize(
+ `ui.panel.lovelace.editor.edit_section_title.${newTitle ? "title_new" : "title"}`
+ ),
+ inputLabel: this.hass.localize(
+ "ui.panel.lovelace.editor.edit_section_title.input_label"
+ ),
+ inputType: "string",
+ defaultValue: section.title,
+ confirmText: newTitle
+ ? this.hass.localize("ui.common.add")
+ : this.hass.localize("ui.common.save"),
+ });
+
+ if (title === null) {
+ return;
+ }
+
+ const newConfig = updateLovelaceContainer(this.lovelace!.config, path, {
+ ...section,
+ title: title || undefined,
+ });
+
+ this.lovelace!.saveConfig(newConfig);
+ }
+
+ private async _deleteSection(ev) {
+ const index = ev.currentTarget.index;
+
+ const path = [this.index!, index] as [number, number];
+
+ const section = findLovelaceContainer(
+ this.lovelace!.config,
+ path
+ ) as LovelaceRawSectionConfig;
+
+ const title = section.title?.trim();
+ const cardCount = section.cards?.length;
+
+ if (title || cardCount) {
+ const named = title ? "named" : "unnamed";
+ const type = cardCount ? "cards" : "only";
+
+ const confirm = await showConfirmationDialog(this, {
+ title: this.hass.localize(
+ "ui.panel.lovelace.editor.delete_section.title"
+ ),
+ text: this.hass.localize(
+ `ui.panel.lovelace.editor.delete_section.text_${named}_section_${type}`,
+ { name: title }
+ ),
+ confirmText: this.hass.localize("ui.common.delete"),
+ destructive: true,
+ });
+
+ if (!confirm) return;
+ }
+
+ const newConfig = deleteSection(this.lovelace!.config, this.index!, index);
+ this.lovelace!.saveConfig(newConfig);
+ }
+
+ private _sectionMoved(ev: CustomEvent) {
+ ev.stopPropagation();
+ const { oldIndex, newIndex } = ev.detail;
+
+ const newConfig = moveSection(
+ this.lovelace!.config,
+ [this.index!, oldIndex],
+ [this.index!, newIndex]
+ );
+ this.lovelace!.saveConfig(newConfig);
+ }
+
+ static get styles(): CSSResultGroup {
+ return css`
+ :host {
+ display: block;
+ }
+
+ .section {
+ position: relative;
+ border-radius: var(--ha-card-border-radius, 12px);
+ }
+
+ .container {
+ --grid-gap: 20px;
+ --grid-max-width: 1400px;
+ --grid-cell-max-width: 500px;
+ --grid-cell-min-width: 320px;
+ display: grid;
+ grid-template-columns: repeat(
+ auto-fit,
+ minmax(var(--grid-cell-min-width), 1fr)
+ );
+ justify-content: center;
+ gap: 8px var(--grid-gap);
+ padding: var(--grid-gap);
+ box-sizing: border-box;
+ max-width: min(
+ calc(
+ var(--cell-count) * (var(--grid-cell-max-width) + var(--grid-gap)) +
+ var(--grid-gap)
+ ),
+ var(--grid-max-width)
+ );
+ margin: 0 auto;
+ }
+
+ @media (max-width: 600px) {
+ .container {
+ grid-template-columns: 1fr;
+ --grid-gap: 8px;
+ }
+ }
+
+ .section-actions {
+ position: absolute;
+ top: 0;
+ right: 0;
+ opacity: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: opacity 0.2s ease-in-out;
+ background-color: rgba(var(--rgb-card-background-color), 0.3);
+ border-radius: 18px;
+ background: var(--secondary-background-color);
+ --mdc-icon-button-size: 36px;
+ --mdc-icon-size: 20px;
+ color: var(--primary-text-color);
+ }
+
+ .handle {
+ cursor: grab;
+ padding: 8px;
+ }
+
+ .add {
+ margin-top: calc(66px + 8px);
+ outline: none;
+ background: none;
+ cursor: pointer;
+ border-radius: var(--ha-card-border-radius, 12px);
+ border: 2px dashed var(--primary-color);
+ order: 1;
+ height: 66px;
+ padding: 8px;
+ box-sizing: content-box;
+ }
+
+ .add:focus {
+ border: 2px solid var(--primary-color);
+ }
+
+ .sortable-ghost {
+ border-radius: var(--ha-card-border-radius, 12px);
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-sections-view": SectionsView;
+ }
+}
diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts
index 1d78c5e7a8..6d35d6a715 100644
--- a/src/panels/lovelace/views/hui-view.ts
+++ b/src/panels/lovelace/views/hui-view.ts
@@ -1,9 +1,17 @@
import { PropertyValues, ReactiveElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
+import { HASSDomEvent } from "../../../common/dom/fire_event";
import "../../../components/entity/ha-state-label-badge";
import "../../../components/ha-svg-icon";
import type { LovelaceViewElement } from "../../../data/lovelace";
+import { LovelaceBadgeConfig } from "../../../data/lovelace/config/badge";
+import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
+import { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
+import {
+ LovelaceViewConfig,
+ isStrategyView,
+} from "../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../types";
import {
createErrorBadgeConfig,
@@ -20,24 +28,30 @@ import {
import { createViewElement } from "../create-element/create-view-element";
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
-import { confDeleteCard } from "../editor/delete-card";
import { deleteCard } from "../editor/config-util";
+import { confDeleteCard } from "../editor/delete-card";
+import {
+ LovelaceCardPath,
+ parseLovelaceCardPath,
+} from "../editor/lovelace-path";
+import { createErrorSectionConfig } from "../sections/hui-error-section";
+import "../sections/hui-section";
+import type { HuiSection } from "../sections/hui-section";
import { generateLovelaceViewStrategy } from "../strategies/get-strategy";
import type { Lovelace, LovelaceBadge, LovelaceCard } from "../types";
-import { PANEL_VIEW_LAYOUT, DEFAULT_VIEW_LAYOUT } from "./const";
-import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
-import { LovelaceBadgeConfig } from "../../../data/lovelace/config/badge";
-import {
- LovelaceViewConfig,
- isStrategyView,
-} from "../../../data/lovelace/config/view";
+import { DEFAULT_VIEW_LAYOUT, PANEL_VIEW_LAYOUT } from "./const";
declare global {
// for fire event
interface HASSDomEvents {
- "ll-create-card": undefined;
- "ll-edit-card": { path: [number] | [number, number] };
- "ll-delete-card": { path: [number] | [number, number]; confirm: boolean };
+ "ll-create-card": { suggested?: string[] } | undefined;
+ "ll-edit-card": { path: LovelaceCardPath };
+ "ll-delete-card": { path: LovelaceCardPath; confirm: boolean };
+ }
+ interface HTMLElementEventMap {
+ "ll-create-card": HASSDomEvent;
+ "ll-edit-card": HASSDomEvent;
+ "ll-delete-card": HASSDomEvent;
}
}
@@ -55,6 +69,8 @@ export class HUIView extends ReactiveElement {
@state() private _badges: LovelaceBadge[] = [];
+ @state() private _sections: HuiSection[] = [];
+
private _layoutElementType?: string;
private _layoutElement?: LovelaceViewElement;
@@ -102,6 +118,27 @@ export class HUIView extends ReactiveElement {
return element;
}
+ // Public to make demo happy
+ public createSectionElement(sectionConfig: LovelaceSectionConfig) {
+ const element = document.createElement("hui-section");
+ element.hass = this.hass;
+ element.lovelace = this.lovelace;
+ element.config = sectionConfig;
+ element.viewIndex = this.index;
+ element.addEventListener(
+ "ll-rebuild",
+ (ev: Event) => {
+ // In edit mode let it go to hui-root and rebuild whole view.
+ if (!this.lovelace!.editMode) {
+ ev.stopPropagation();
+ this._rebuildSection(element, sectionConfig);
+ }
+ },
+ { once: true }
+ );
+ return element;
+ }
+
protected createRenderRoot() {
return this;
}
@@ -133,7 +170,7 @@ export class HUIView extends ReactiveElement {
}
}
- protected update(changedProperties) {
+ protected update(changedProperties: PropertyValues) {
super.update(changedProperties);
// If no layout element, we're still creating one
@@ -156,6 +193,14 @@ export class HUIView extends ReactiveElement {
}
});
+ this._sections.forEach((element) => {
+ try {
+ element.hass = this.hass;
+ } catch (e: any) {
+ this._rebuildSection(element, createErrorSectionConfig(e.message));
+ }
+ });
+
this._layoutElement.hass = this.hass;
const oldHass = changedProperties.get("hass") as
@@ -175,6 +220,14 @@ export class HUIView extends ReactiveElement {
}
if (changedProperties.has("lovelace")) {
this._layoutElement.lovelace = this.lovelace;
+ this._sections.forEach((element) => {
+ try {
+ element.hass = this.hass;
+ element.lovelace = this.lovelace;
+ } catch (e: any) {
+ this._rebuildSection(element, createErrorSectionConfig(e.message));
+ }
+ });
}
if (changedProperties.has("_cards")) {
this._layoutElement.cards = this._cards;
@@ -214,6 +267,7 @@ export class HUIView extends ReactiveElement {
this._createBadges(viewConfig);
this._createCards(viewConfig);
+ this._createSections(viewConfig);
this._layoutElement!.isStrategy = isStrategy;
this._layoutElement!.hass = this.hass;
this._layoutElement!.narrow = this.narrow;
@@ -221,6 +275,7 @@ export class HUIView extends ReactiveElement {
this._layoutElement!.index = this.index;
this._layoutElement!.cards = this._cards;
this._layoutElement!.badges = this._badges;
+ this._layoutElement!.sections = this._sections;
applyThemesOnElement(this, this.hass.themes, viewConfig.theme);
this._viewConfigTheme = viewConfig.theme;
@@ -236,18 +291,21 @@ export class HUIView extends ReactiveElement {
private _createLayoutElement(config: LovelaceViewConfig): void {
this._layoutElement = createViewElement(config) as LovelaceViewElement;
this._layoutElementType = config.type;
- this._layoutElement.addEventListener("ll-create-card", () => {
+ this._layoutElement.addEventListener("ll-create-card", (ev) => {
showCreateCardDialog(this, {
lovelaceConfig: this.lovelace.config,
saveConfig: this.lovelace.saveConfig,
path: [this.index],
+ suggestedCards: ev.detail?.suggested,
});
});
this._layoutElement.addEventListener("ll-edit-card", (ev) => {
+ const { cardIndex } = parseLovelaceCardPath(ev.detail.path);
showEditCardDialog(this, {
lovelaceConfig: this.lovelace.config,
saveConfig: this.lovelace.saveConfig,
- path: ev.detail.path,
+ path: [this.index],
+ cardIndex,
});
});
this._layoutElement.addEventListener("ll-delete-card", (ev) => {
@@ -297,6 +355,19 @@ export class HUIView extends ReactiveElement {
});
}
+ private _createSections(config: LovelaceViewConfig): void {
+ if (!config || !config.sections || !Array.isArray(config.sections)) {
+ this._sections = [];
+ return;
+ }
+
+ this._sections = config.sections.map((sectionConfig, index) => {
+ const element = this.createSectionElement(sectionConfig);
+ element.index = index;
+ return element;
+ });
+ }
+
private _rebuildCard(
cardElToReplace: LovelaceCard,
config: LovelaceCardConfig
@@ -337,6 +408,23 @@ export class HUIView extends ReactiveElement {
curBadgeEl === badgeElToReplace ? newBadgeEl : curBadgeEl
);
}
+
+ private _rebuildSection(
+ sectionElToReplace: HuiSection,
+ config: LovelaceSectionConfig
+ ): void {
+ const newSectionEl = this.createSectionElement(config);
+ newSectionEl.index = sectionElToReplace.index;
+ if (sectionElToReplace.parentElement) {
+ sectionElToReplace.parentElement!.replaceChild(
+ newSectionEl,
+ sectionElToReplace
+ );
+ }
+ this._sections = this._sections!.map((curSectionEl) =>
+ curSectionEl === sectionElToReplace ? newSectionEl : curSectionEl
+ );
+ }
}
declare global {
diff --git a/src/panels/mailbox/ha-panel-mailbox.ts b/src/panels/mailbox/ha-panel-mailbox.ts
index 643112c7bd..250af9a83a 100644
--- a/src/panels/mailbox/ha-panel-mailbox.ts
+++ b/src/panels/mailbox/ha-panel-mailbox.ts
@@ -12,8 +12,6 @@ import { formatDateTime } from "../../common/datetime/format_date_time";
import "../../components/ha-card";
import "../../components/ha-menu-button";
import "../../components/ha-tabs";
-import "@polymer/paper-item/paper-item";
-import "@polymer/paper-item/paper-item-body";
import "@polymer/paper-tabs/paper-tab";
import { HomeAssistant } from "../../types";
import { fireEvent } from "../../common/dom/fire_event";
@@ -82,25 +80,24 @@ class HaPanelMailbox extends LitElement {
: nothing}
${this._messages?.map(
(message) =>
- html`
-
-
-
${message.caller}
-
- ${formatDuration(this.hass.locale, {
- seconds: message.duration,
- })}
-
-
-
- ${message.timestamp} -
- ${message.message}
-
-
- `
+
+ ${message.caller}
+
+ ${formatDuration(this.hass.locale, {
+ seconds: message.duration,
+ })}
+
+
+
+ ${message.timestamp} -
+ ${message.message}
+
+ `
)}
@@ -219,10 +216,6 @@ class HaPanelMailbox extends LitElement {
overflow: hidden;
}
- paper-item {
- cursor: pointer;
- }
-
ha-tabs {
margin-left: max(env(safe-area-inset-left), 24px);
margin-right: max(env(safe-area-inset-right), 24px);
diff --git a/src/panels/map/ha-panel-map.ts b/src/panels/map/ha-panel-map.ts
index b7698ca186..d6c1cbd1fb 100644
--- a/src/panels/map/ha-panel-map.ts
+++ b/src/panels/map/ha-panel-map.ts
@@ -46,7 +46,7 @@ class HaPanelMap extends LitElement {
}
private _openZonesEditor() {
- navigate("/config/zone");
+ navigate("/config/zone?historyBack=1");
}
public willUpdate(changedProps: PropertyValues) {
diff --git a/src/panels/media-browser/ha-panel-media-browser.ts b/src/panels/media-browser/ha-panel-media-browser.ts
index 8713bed2a4..c5bc566f07 100644
--- a/src/panels/media-browser/ha-panel-media-browser.ts
+++ b/src/panels/media-browser/ha-panel-media-browser.ts
@@ -343,7 +343,6 @@ class PanelMediaBrowser extends LitElement {
ha-media-player-browse {
height: calc(100vh - (100px + var(--header-height)));
- direction: ltr;
}
:host([narrow]) ha-media-player-browse {
diff --git a/src/panels/my/ha-panel-my.ts b/src/panels/my/ha-panel-my.ts
index bac84192a2..100eeddf59 100644
--- a/src/panels/my/ha-panel-my.ts
+++ b/src/panels/my/ha-panel-my.ts
@@ -258,7 +258,7 @@ export const getMyRedirects = (hasSupervisor: boolean): Redirects => ({
},
supervisor_logs: {
// Moved from Supervisor panel in 2022.5
- redirect: "/config/logs",
+ redirect: "/config/logs?provider=supervisor",
},
supervisor_info: {
// Moved from Supervisor panel in 2022.5
diff --git a/src/panels/profile/dialog-ha-mfa-module-setup-flow.ts b/src/panels/profile/dialog-ha-mfa-module-setup-flow.ts
index 0ca1b026e6..c7bad0fa14 100644
--- a/src/panels/profile/dialog-ha-mfa-module-setup-flow.ts
+++ b/src/panels/profile/dialog-ha-mfa-module-setup-flow.ts
@@ -97,7 +97,7 @@ class HaMfaModuleSetupFlow extends LitElement {
? html`
${this.hass.localize(
"ui.panel.profile.mfa_setup.step_done",
- { step: this._step.title }
+ { step: this._step.title || this._step.handler }
)}
`
: this._step.type === "form"
diff --git a/src/panels/profile/ha-long-lived-access-token-dialog.ts b/src/panels/profile/ha-long-lived-access-token-dialog.ts
index 4dd9fe1298..904680a2d1 100644
--- a/src/panels/profile/ha-long-lived-access-token-dialog.ts
+++ b/src/panels/profile/ha-long-lived-access-token-dialog.ts
@@ -74,7 +74,9 @@ export class HaLongLivedAccessTokenDialog extends LitElement {
? this._qrCode
: html`
- Generate QR code
+ ${this.hass.localize(
+ "ui.panel.profile.long_lived_access_tokens.generate_qr_code"
+ )}
`}
diff --git a/src/state-summary/state-card-lock.ts b/src/state-summary/state-card-lock.ts
index c35c4e3007..117a7c992b 100644
--- a/src/state-summary/state-card-lock.ts
+++ b/src/state-summary/state-card-lock.ts
@@ -11,7 +11,7 @@ import {
import { customElement, property } from "lit/decorators";
import { supportsFeature } from "../common/entity/supports-feature";
import "../components/entity/state-info";
-import { LockEntityFeature } from "../data/lock";
+import { callProtectedLockService, LockEntityFeature } from "../data/lock";
import { HomeAssistant } from "../types";
import { haStyle } from "../resources/styles";
@@ -56,10 +56,10 @@ class StateCardLock extends LitElement {
private async _callService(ev) {
ev.stopPropagation();
const service = ev.target.dataset.service;
- const data = {
- entity_id: this.stateObj.entity_id,
- };
- await this.hass.callService("lock", service, data);
+ if (!this.hass || !this.stateObj) {
+ return;
+ }
+ await callProtectedLockService(this, this.hass, this.stateObj, service);
}
static get styles(): CSSResultGroup {
diff --git a/src/state-summary/state-card-script.ts b/src/state-summary/state-card-script.ts
index f8014684e7..fc375d8d25 100644
--- a/src/state-summary/state-card-script.ts
+++ b/src/state-summary/state-card-script.ts
@@ -8,6 +8,8 @@ import { isUnavailableState } from "../data/entity";
import { canRun, ScriptEntity } from "../data/script";
import { haStyle } from "../resources/styles";
import { HomeAssistant } from "../types";
+import { computeObjectId } from "../common/entity/compute_object_id";
+import { showMoreInfoDialog } from "../dialogs/more-info/show-ha-more-info-dialog";
@customElement("state-card-script")
class StateCardScript extends LitElement {
@@ -56,7 +58,16 @@ class StateCardScript extends LitElement {
private _runScript(ev: Event) {
ev.stopPropagation();
- this._callService("turn_on");
+
+ const fields =
+ this.hass!.services.script[computeObjectId(this.stateObj.entity_id)]
+ ?.fields;
+
+ if (fields && Object.keys(fields).length > 0) {
+ showMoreInfoDialog(this, { entityId: this.stateObj.entity_id });
+ } else {
+ this._callService("turn_on");
+ }
}
private _callService(service: string): void {
diff --git a/src/translations/en.json b/src/translations/en.json
index cbeaab0b43..24f63e86a3 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -218,8 +218,14 @@
},
"script": {
"run": "[%key:ui::card::service::run%]",
+ "running_single": "Running…",
+ "running_queued": "{queued} queued",
+ "running_parallel": "{active} Running…",
"cancel": "Cancel",
- "cancel_multiple": "Cancel {number}"
+ "cancel_multiple": "Cancel {number}",
+ "cancel_all": "Cancel all",
+ "idle": "Idle",
+ "run_script": "Run script"
},
"service": {
"run": "Run"
@@ -317,6 +323,7 @@
"refresh": "Refresh",
"cancel": "Cancel",
"delete": "Delete",
+ "download": "[%key:supervisor::backup::download%]",
"duplicate": "Duplicate",
"remove": "Remove",
"enable": "Enable",
@@ -1370,7 +1377,11 @@
"add_option": "[%key:ui::panel::config::automation::editor::actions::type::choose::add_option%]",
"remove_option": "[%key:ui::panel::config::automation::editor::actions::type::choose::remove_option%]",
"no_options": "There are no options yet.",
- "add": "Add"
+ "add": "Add",
+ "confirm_delete": {
+ "delete": "[%key:ui::components::todo::item::confirm_delete::delete%]",
+ "prompt": "[%key:ui::components::todo::item::confirm_delete::prompt%]"
+ }
},
"counter": {
"minimum": "Minimum value",
@@ -2168,7 +2179,17 @@
"show_full_logs": "Show full logs",
"download_full_log": "Download full log",
"provider_not_found": "Log provider not found",
- "provider_not_available": "Logs for ''{provider}'' are not available on your system."
+ "provider_not_available": "Logs for ''{provider}'' are not available on your system.",
+ "detail": {
+ "logger": "Logger",
+ "source": "Source",
+ "integration": "[%key:ui::panel::config::integrations::integration%]",
+ "documentation": "documentation",
+ "issues": "issues",
+ "first_occurred": "First occurred",
+ "occurrences": "occurrences",
+ "last_logged": "Last logged"
+ }
},
"lovelace": {
"caption": "Dashboards",
@@ -2347,7 +2368,21 @@
"no_runs_found": "No runs found",
"older_run": "Older run",
"newer_run": "Newer run",
- "start_debug_run": "Start debug run"
+ "start_debug_run": "Start debug run",
+ "pipeline": {
+ "header": "Assist Pipeline",
+ "run_text_pipeline": "Run text pipeline",
+ "run_audio_pipeline": "Run audio pipeline",
+ "run_audio_with_wake": "Run audio pipeline with wake word detection",
+ "response": "[%key:ui::panel::developer-tools::tabs::services::response%]",
+ "send": "Send",
+ "continue_listening": "Continue listening for wake word",
+ "continue_talking": "Continue talking",
+ "continue_conversation": "Continue conversation",
+ "input_text": "Input text",
+ "run": "[%key:ui::card::service::run%]",
+ "error_starting": "Error starting pipeline"
+ }
},
"expose": {
"caption": "Expose",
@@ -2478,7 +2513,7 @@
"triggers": {
"name": "Triggers",
"header": "When",
- "description": "This list of triggers is what starts your automation. A trigger is a specific event happening in or around your home, for example: ''When the sun sets''.",
+ "description": "A trigger is a specific event happening in or around your home, for example: ''When the sun sets''. Any trigger listed here will start your automation.",
"learn_more": "Learn more about triggers",
"triggered": "Triggered",
"add": "Add trigger",
@@ -3479,7 +3514,12 @@
"instance_will_be_available": "Your instance will be available at your",
"link_learn_how_it_works": "Learn how it works",
"nabu_casa_url": "Nabu Casa URL",
- "certificate_info": "Certificate info"
+ "advanced_options": "Advanced options",
+ "external_activation": "Allow external activation of remote control",
+ "external_activation_secondary": "Allows you to turn on remote control from your Nabu Casa account page, even if you're outside your local network",
+ "certificate_info": "Certificate info",
+ "certificate_expire": "Will be renewed at {date}",
+ "more_info": "More info"
},
"alexa": {
"title": "Alexa",
@@ -4098,6 +4138,7 @@
"other_networks": "Other networks",
"my_network": "Preferred network",
"no_preferred_network": "You don't have a preferred network yet.",
+ "more_info": "More Info",
"add_open_thread_border_router": "Add an OpenThread border router",
"reset_border_router": "Reset border router",
"add_to_my_network": "Add to preferred network",
@@ -4997,10 +5038,13 @@
"saving_failed": "Saving dashboard configuration failed."
},
"views": {
- "confirm_delete": "Delete view?",
- "confirm_delete_text": "Are you sure you want to delete your ''{name}'' view?",
- "confirm_delete_existing_cards": "Deleting this view will also remove the cards",
- "confirm_delete_existing_cards_text": "Are you sure you want to delete your ''{name}'' view? The view contains {number} cards that will be deleted. This action cannot be undone."
+ "delete_title": "Delete view",
+ "delete_named_view_only": "''{name}'' view will be deleted.",
+ "delete_unnamed_view_only": "This view will be deleted.",
+ "delete_named_view_cards": "''{name}'' view and all its cards will be deleted.",
+ "delete_unnamed_view_cards": "This view and all its cards will be deleted.",
+ "delete_named_view_sections": "''{name}'' view and all its sections will be deleted.",
+ "delete_unnamed_view_sections": "This view and all its sections will be deleted."
},
"menu": {
"configure_ui": "Edit dashboard",
@@ -5068,10 +5112,14 @@
"select_users": "Select which users should see this view in the navigation"
},
"type": "View type",
+ "type_helper_sections": "You can not change your view to use the 'sections' view type, because migration is not supported yet. Start from scratch with a new view if you want to experiment with the 'sections' view.",
+ "type_helper_others": "You can not change your view to an other type because migration is not supported yet. Start from scratch with a new view if you want to use another view type.",
+
"types": {
"masonry": "Masonry (default)",
"sidebar": "Sidebar",
- "panel": "Panel (1 card)"
+ "panel": "Panel (1 card)",
+ "sections": "Sections (experimental)"
},
"subview": "Subview",
"subview_helper": "Subviews don't appear in tabs and have a back button.",
@@ -5087,7 +5135,7 @@
"header": "Card configuration",
"typed_header": "{type} Card configuration",
"pick_card": "Which card would you like to add?",
- "pick_card_view_title": "Which card would you like to add to your {name} view?",
+ "pick_card_title": "Which card would you like to add to {name}",
"toggle_editor": "Toggle editor",
"unsaved_changes": "You have unsaved changes",
"confirm_cancel": "Are you sure you want to cancel?",
@@ -5125,6 +5173,23 @@
"no_config": "No config found.",
"no_views": "No views in this dashboard."
},
+ "section": {
+ "unnamed_section": "Unnamed section",
+ "add_card": "[%key:ui::panel::lovelace::editor::edit_card::add%]",
+ "add_section": "Add section"
+ },
+ "delete_section": {
+ "title": "Delete section",
+ "text_named_section_only": "''{name}'' section will be deleted.",
+ "text_unnamed_section_only": "This section will be deleted.",
+ "text_named_section_cards": "''{name}'' section and all its cards will be deleted.",
+ "text_unnamed_section_cards": "This section and all its cards will be deleted."
+ },
+ "edit_section_title": {
+ "title": "Edit name",
+ "title_new": "Add name",
+ "input_label": "Name"
+ },
"suggest_card": {
"header": "We created a suggestion for you",
"create_own": "Pick different card",
@@ -5430,7 +5495,10 @@
"state": "State",
"secondary_info_attribute": "Secondary info attribute",
"search": "Search",
- "state_color": "Color icons based on state?"
+ "state_color": "Color icons based on state?",
+ "suggested_cards": "Suggested cards",
+ "other_cards": "Other cards",
+ "custom_cards": "Custom cards"
},
"map": {
"name": "Map",
@@ -5600,6 +5668,15 @@
},
"preset_modes": "Preset modes"
},
+ "fan-preset-modes": {
+ "label": "Fan preset modes",
+ "style": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style%]",
+ "style_list": {
+ "dropdown": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style_list::dropdown%]",
+ "icons": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style_list::icons%]"
+ },
+ "preset_modes": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::preset_modes%]"
+ },
"humidifier-toggle": {
"label": "Humidifier toggle"
},
@@ -5951,7 +6028,8 @@
"prompt_name": "Give the token a name",
"prompt_copy_token": "Copy your access token. It will not be shown again.",
"empty_state": "You have no long-lived access tokens yet.",
- "qr_code_image": "QR code for token {name}"
+ "qr_code_image": "QR code for token {name}",
+ "generate_qr_code": "Generate QR Code"
}
},
"todo": {
@@ -6288,6 +6366,7 @@
"end": "End",
"new_value": "New value",
"adjust": "Adjust",
+ "outliers": "Outliers",
"sum_adjusted": "Statistic sum adjusted",
"error_sum_adjusted": "Error adjusting sum: {message}"
}
@@ -6478,6 +6557,7 @@
}
},
"energy": {
+ "download_data": "[%key:ui::panel::history::download_data%]",
"configure": "[%key:ui::dialogs::quick-bar::commands::navigation::energy%]",
"compare": {
"info": "You are comparing the period {start} with the period {end}"
@@ -6500,7 +6580,8 @@
"energy_water_graph_title": "Water consumption",
"energy_distribution_title": "Energy distribution",
"energy_sources_table_title": "Sources",
- "energy_devices_graph_title": "Monitor individual devices"
+ "energy_devices_graph_title": "Individual devices total usage",
+ "energy_devices_detail_graph_title": "Individual devices detail usage"
}
},
"history": {
diff --git a/test/panels/lovelace/editor/config-util.spec.ts b/test/panels/lovelace/editor/config-util.spec.ts
index a437b28cfa..b625636736 100644
--- a/test/panels/lovelace/editor/config-util.spec.ts
+++ b/test/panels/lovelace/editor/config-util.spec.ts
@@ -1,63 +1,12 @@
import { assert } from "chai";
+import { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
import {
- swapCard,
- moveCard,
+ moveCardToContainer,
swapView,
} from "../../../../src/panels/lovelace/editor/config-util";
-import { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
-describe("swapCard", () => {
- it("swaps 2 cards in same view", () => {
- const config: LovelaceConfig = {
- views: [
- {},
- {
- cards: [{ type: "card1" }, { type: "card2" }],
- },
- ],
- };
-
- const result = swapCard(config, [1, 0], [1, 1]);
- const expected = {
- views: [
- {},
- {
- cards: [{ type: "card2" }, { type: "card1" }],
- },
- ],
- };
- assert.deepEqual(expected, result);
- });
-
- it("swaps 2 cards in different views", () => {
- const config: LovelaceConfig = {
- views: [
- {
- cards: [{ type: "v1-c1" }, { type: "v1-c2" }],
- },
- {
- cards: [{ type: "v2-c1" }, { type: "v2-c2" }],
- },
- ],
- };
-
- const result = swapCard(config, [0, 0], [1, 1]);
- const expected: LovelaceConfig = {
- views: [
- {
- cards: [{ type: "v2-c2" }, { type: "v1-c2" }],
- },
- {
- cards: [{ type: "v2-c1" }, { type: "v1-c1" }],
- },
- ],
- };
- assert.deepEqual(expected, result);
- });
-});
-
-describe("moveCard", () => {
+describe("moveCardToContainer", () => {
it("move a card to an empty view", () => {
const config: LovelaceConfig = {
views: [
@@ -68,7 +17,7 @@ describe("moveCard", () => {
],
};
- const result = moveCard(config, [1, 0], [0]);
+ const result = moveCardToContainer(config, [1, 0], [0]);
const expected: LovelaceConfig = {
views: [
{
@@ -94,7 +43,7 @@ describe("moveCard", () => {
],
};
- const result = moveCard(config, [1, 0], [0]);
+ const result = moveCardToContainer(config, [1, 0], [0]);
const expected: LovelaceConfig = {
views: [
{
@@ -121,12 +70,12 @@ describe("moveCard", () => {
};
const result = () => {
- moveCard(config, [1, 0], [1]);
+ moveCardToContainer(config, [1, 0], [1]);
};
assert.throws(
result,
Error,
- "You cannot move a card to the view it is in."
+ "You cannot move a card to the view or section it is in."
);
});
});
diff --git a/tsconfig.json b/tsconfig.json
index 72918ea5ad..83c5f840ac 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -42,13 +42,13 @@
// LitElement
"no-property-visibility-mismatch": "error",
// CSS
- "no-invalid-css": "off", // warning does not work
+ "no-invalid-css": "off" // warning does not work
},
"globalTags": ["google-cast-launcher"],
"customHtmlData": [
- "./node_modules/@lrnwebcomponents/simple-tooltip/custom-elements.json",
- ],
- },
- ],
- },
+ "./node_modules/@lrnwebcomponents/simple-tooltip/custom-elements.json"
+ ]
+ }
+ ]
+ }
}
diff --git a/yarn.lock b/yarn.lock
index a42f4f1a04..874b6ffc71 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -129,8 +129,8 @@ __metadata:
linkType: hard
"@babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.6, @babel/helper-create-class-features-plugin@npm:^7.23.9":
- version: 7.23.9
- resolution: "@babel/helper-create-class-features-plugin@npm:7.23.9"
+ version: 7.23.10
+ resolution: "@babel/helper-create-class-features-plugin@npm:7.23.10"
dependencies:
"@babel/helper-annotate-as-pure": "npm:^7.22.5"
"@babel/helper-environment-visitor": "npm:^7.22.20"
@@ -143,7 +143,7 @@ __metadata:
semver: "npm:^6.3.1"
peerDependencies:
"@babel/core": ^7.0.0
- checksum: 10/91c8aa8888780bd90aa50f511917cb0953ccd61b2ea4abf61915c1d68d99bb14b472969a8ae5b391d7890759dfc22be79104297be07919c38351714a4ce2fe74
+ checksum: 10/8b9f02526eeb03ef1d2bc89e3554377ae966b33a74078ab1f88168dfa725dc206ea5ecf4cf417c3651d8a6b3c70204f6939a9aa0401be3d0d32ddbf6024ea3c7
languageName: node
linkType: hard
@@ -1447,12 +1447,12 @@ __metadata:
languageName: node
linkType: hard
-"@bundle-stats/plugin-webpack-filter@npm:4.9.2":
- version: 4.9.2
- resolution: "@bundle-stats/plugin-webpack-filter@npm:4.9.2"
+"@bundle-stats/plugin-webpack-filter@npm:4.10.1":
+ version: 4.10.1
+ resolution: "@bundle-stats/plugin-webpack-filter@npm:4.10.1"
peerDependencies:
core-js: ^3.0.0
- checksum: 10/d57aeff530a1af099929f67d12402f5a563e018333d86de159af2c1714274b040de9e1a9f6dad1b3bbee6b7af0cde6f9668a368138f27ac13d34642beba8e2f0
+ checksum: 10/f389188a27a01b8c353bb8b90a3c9fe1eabf4c24ed9f28c52e4063204780490dfd73df109d55ac0b0331a82b61705c0f3dac68b04fe50fcbd0e4e2efff2eda89
languageName: node
linkType: hard
@@ -1508,32 +1508,32 @@ __metadata:
languageName: node
linkType: hard
-"@codemirror/search@npm:6.5.5":
- version: 6.5.5
- resolution: "@codemirror/search@npm:6.5.5"
+"@codemirror/search@npm:6.5.6":
+ version: 6.5.6
+ resolution: "@codemirror/search@npm:6.5.6"
dependencies:
"@codemirror/state": "npm:^6.0.0"
"@codemirror/view": "npm:^6.0.0"
crelt: "npm:^1.0.5"
- checksum: 10/61707efa563edaea1d83f0680db63a953f3f1c125e50bd912d84d07129aa5ba1f3a775f62339f7931c01f5afd69db777c0571215bd0aaef51964c37ee932f6df
+ checksum: 10/6668a34b4617e909617d3d831627d74b7a7985e8cd86d396bfcb3e86262f2310fc029fd6c846f1b8f1e6768e75985c9f1b0b18b31e05341f06b5b75c1ffde38d
languageName: node
linkType: hard
-"@codemirror/state@npm:6.4.0, @codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.4.0":
- version: 6.4.0
- resolution: "@codemirror/state@npm:6.4.0"
- checksum: 10/d9129c456d1589ca376594620bad10c51d3dcdb57950f34637cea0e2ea073a695d426dc1cfc9b909b07365c236a6312da1eaf740c384c853009742493b8c9935
+"@codemirror/state@npm:6.4.1, @codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.4.0":
+ version: 6.4.1
+ resolution: "@codemirror/state@npm:6.4.1"
+ checksum: 10/a9ec56c7d7d52034ce8ebea3a9a4d216b9e972d701b32b5000e56c97790d0d46af129aeba0b80bed36648b4024b3ba3e4910cf5bfed11de4a9e89252e0707a70
languageName: node
linkType: hard
-"@codemirror/view@npm:6.23.1, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0":
- version: 6.23.1
- resolution: "@codemirror/view@npm:6.23.1"
+"@codemirror/view@npm:6.24.1, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0":
+ version: 6.24.1
+ resolution: "@codemirror/view@npm:6.24.1"
dependencies:
"@codemirror/state": "npm:^6.4.0"
style-mod: "npm:^4.1.0"
w3c-keyname: "npm:^2.2.4"
- checksum: 10/42e6b73bcad6bf5d2e9578c54d166c63c4b1c7c7c7806b6f6b4bead8683dc7fcca52201a02a1f9b8ccf120a4ad87e7dcd68f09d9d3e416304dad41a75e20da82
+ checksum: 10/66428da341241a865f75c88c4e2984234919ae46a76bba24822867166ba3d15a9df0235b120c491a5ffacdfed7f5d748cae083e19c48656ee9b93c40a5f3c7e1
languageName: node
linkType: hard
@@ -1597,10 +1597,10 @@ __metadata:
languageName: node
linkType: hard
-"@eslint/js@npm:8.56.0":
- version: 8.56.0
- resolution: "@eslint/js@npm:8.56.0"
- checksum: 10/97a4b5ccf7e24f4d205a1fb0f21cdcd610348ecf685f6798a48dd41ba443f2c1eedd3050ff5a0b8f30b8cf6501ab512aa9b76e531db15e59c9ebaa41f3162e37
+"@eslint/js@npm:8.57.0":
+ version: 8.57.0
+ resolution: "@eslint/js@npm:8.57.0"
+ checksum: 10/3c501ce8a997cf6cbbaf4ed358af5492875e3550c19b9621413b82caa9ae5382c584b0efa79835639e6e0ddaa568caf3499318e5bdab68643ef4199dce5eb0a0
languageName: node
linkType: hard
@@ -1749,60 +1749,60 @@ __metadata:
languageName: node
linkType: hard
-"@fullcalendar/core@npm:6.1.10":
- version: 6.1.10
- resolution: "@fullcalendar/core@npm:6.1.10"
+"@fullcalendar/core@npm:6.1.11":
+ version: 6.1.11
+ resolution: "@fullcalendar/core@npm:6.1.11"
dependencies:
preact: "npm:~10.12.1"
- checksum: 10/0ca26aefd3e553dac9019838e46ab0e73f7df4954f4d2cbbda4ad73f4e8b9889e4a016cdcc7ae5f548d08d147d6315dffede51f8e213eff5ef63f2dcca2d759f
+ checksum: 10/7624841879d34fdf769c7610e95cef820ea52eb45c74d51be426bb2acc05cb57806785fc1b1a1282b156470c1f04c976314327fbff63e1b115b7108649aeb1c8
languageName: node
linkType: hard
-"@fullcalendar/daygrid@npm:6.1.10, @fullcalendar/daygrid@npm:~6.1.10":
- version: 6.1.10
- resolution: "@fullcalendar/daygrid@npm:6.1.10"
+"@fullcalendar/daygrid@npm:6.1.11, @fullcalendar/daygrid@npm:~6.1.11":
+ version: 6.1.11
+ resolution: "@fullcalendar/daygrid@npm:6.1.11"
peerDependencies:
- "@fullcalendar/core": ~6.1.10
- checksum: 10/6c58038c1a5b6ba439f0b5d3fb9d53e7fabbf23039d18d6d60036acceee399cd1cbf6038d4b8973ee4c54544029fb940d29ff7d26472a332248e24a6e5969bf6
+ "@fullcalendar/core": ~6.1.11
+ checksum: 10/c6165c22405d0fee19b2e4ac54b35115c8bc7e176e3ef60f06b1d7af93d4da1fa571acbd169faa3ea4743c55f6374c6e7f7cc774026a1ae0b83d80db33c4b391
languageName: node
linkType: hard
-"@fullcalendar/interaction@npm:6.1.10":
- version: 6.1.10
- resolution: "@fullcalendar/interaction@npm:6.1.10"
+"@fullcalendar/interaction@npm:6.1.11":
+ version: 6.1.11
+ resolution: "@fullcalendar/interaction@npm:6.1.11"
peerDependencies:
- "@fullcalendar/core": ~6.1.10
- checksum: 10/890f7809e4587dc8aa37292d29806a932214848ce1de42092e7290d62206ee785957dc77468bf6b741ca2948cc0e8563bb4bc2397d83d52c440bb2b054da06f2
+ "@fullcalendar/core": ~6.1.11
+ checksum: 10/6d669d59f20615b71d42d0d053af39d512e824381d575554e016c9221f3f98e17b7770341711322f8455a9c4729450479e2cf4bf026ff123540bf671c6f59f33
languageName: node
linkType: hard
-"@fullcalendar/list@npm:6.1.10":
- version: 6.1.10
- resolution: "@fullcalendar/list@npm:6.1.10"
+"@fullcalendar/list@npm:6.1.11":
+ version: 6.1.11
+ resolution: "@fullcalendar/list@npm:6.1.11"
peerDependencies:
- "@fullcalendar/core": ~6.1.10
- checksum: 10/773830aa2b67c7e10e38b64b9ecd9819901067dd6fd7c78c1ec840830c07166ca1280edd57b746a635ed93cbdbb732a8a5f2cf1725e9ba4d668e30765f61f337
+ "@fullcalendar/core": ~6.1.11
+ checksum: 10/13bb92c7ca4c7808ec57c1ada55a724ff7e8928bb118e1d9bbaf20fab8c6fb2486101e37b9422dc88ef50342354d35c436bbfa161b5ff09379a11c317f26c725
languageName: node
linkType: hard
-"@fullcalendar/luxon3@npm:6.1.10":
- version: 6.1.10
- resolution: "@fullcalendar/luxon3@npm:6.1.10"
+"@fullcalendar/luxon3@npm:6.1.11":
+ version: 6.1.11
+ resolution: "@fullcalendar/luxon3@npm:6.1.11"
peerDependencies:
- "@fullcalendar/core": ~6.1.10
+ "@fullcalendar/core": ~6.1.11
luxon: ^3.0.0
- checksum: 10/575c225cddff677f30d835d84c6957f47ac81b8f2a395f3e0d1d11ea4da75b2479b42431b2a3e16284a1caf5589796633289970eb63143fe9aa3ef818b78213f
+ checksum: 10/fc302aad0d1b080aac800956921358f10682d8b62d49ff78db85fbc6ea15c8799729679d164d70ac71cee77e0744da55cdfc9b295dcb35e0d6bf673649fd805d
languageName: node
linkType: hard
-"@fullcalendar/timegrid@npm:6.1.10":
- version: 6.1.10
- resolution: "@fullcalendar/timegrid@npm:6.1.10"
+"@fullcalendar/timegrid@npm:6.1.11":
+ version: 6.1.11
+ resolution: "@fullcalendar/timegrid@npm:6.1.11"
dependencies:
- "@fullcalendar/daygrid": "npm:~6.1.10"
+ "@fullcalendar/daygrid": "npm:~6.1.11"
peerDependencies:
- "@fullcalendar/core": ~6.1.10
- checksum: 10/0351679754f110610a87e1a08b60df3833837f828ede0bb804c07632d765d5061bd03913a06384078e567092ae3071826aa82620b79b7e92fb55b4c878000bcb
+ "@fullcalendar/core": ~6.1.11
+ checksum: 10/b2794502a0aa35c33405e35b05d367abab983d15af568a285123a673414bf545c298f7227b661290f99a2ef37e90013513cab3e9d4d0c15840212cd3b429c99d
languageName: node
linkType: hard
@@ -1815,7 +1815,7 @@ __metadata:
languageName: node
linkType: hard
-"@humanwhocodes/config-array@npm:^0.11.13":
+"@humanwhocodes/config-array@npm:^0.11.14":
version: 0.11.14
resolution: "@humanwhocodes/config-array@npm:0.11.14"
dependencies:
@@ -1999,9 +1999,9 @@ __metadata:
linkType: hard
"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0":
- version: 3.1.1
- resolution: "@jridgewell/resolve-uri@npm:3.1.1"
- checksum: 10/64d59df8ae1a4e74315eb1b61e012f1c7bc8aac47a3a1e683f6fe7008eab07bc512a742b7aa7c0405685d1421206de58c9c2e6adbfe23832f8bd69408ffc183e
+ version: 3.1.2
+ resolution: "@jridgewell/resolve-uri@npm:3.1.2"
+ checksum: 10/97106439d750a409c22c8bff822d648f6a71f3aa9bc8e5129efdc36343cd3096ddc4eeb1c62d2fe48e9bdd4db37b05d4646a17114ecebd3bbcacfa2de51c3c1d
languageName: node
linkType: hard
@@ -2040,12 +2040,12 @@ __metadata:
linkType: hard
"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.9":
- version: 0.3.21
- resolution: "@jridgewell/trace-mapping@npm:0.3.21"
+ version: 0.3.22
+ resolution: "@jridgewell/trace-mapping@npm:0.3.22"
dependencies:
"@jridgewell/resolve-uri": "npm:^3.1.0"
"@jridgewell/sourcemap-codec": "npm:^1.4.14"
- checksum: 10/925dda0620887e5a24f11b5a3a106f4e8b1a66155b49be6ceee61432174df33a17c243d8a89b2cd79ccebd281d817878759236a2fc42c47325ae9f73dfbfb90d
+ checksum: 10/48d3e3db00dbecb211613649a1849876ba5544a3f41cf5e6b99ea1130272d6cf18591b5b67389bce20f1c871b4ede5900c3b6446a7aab6d0a3b2fe806a834db7
languageName: node
linkType: hard
@@ -2089,11 +2089,11 @@ __metadata:
linkType: hard
"@lezer/lr@npm:^1.0.0":
- version: 1.3.14
- resolution: "@lezer/lr@npm:1.3.14"
+ version: 1.4.0
+ resolution: "@lezer/lr@npm:1.4.0"
dependencies:
"@lezer/common": "npm:^1.0.0"
- checksum: 10/9d32701f91fdf7d570073f5e83cda028c80bea7633f928c809eb6977d4f0b5e32424f95fb78cafea98789c4c0dadc9694636903290f0c1c418d2a47ed7f18f46
+ checksum: 10/7391d0d08e54cd9e4f4d46e6ee6aa81fbaf079b22ed9c13d01fc9928e0ffd16d0c2d21b2cedd55675ad6c687277db28349ea8db81c9c69222cd7e7c40edd026e
languageName: node
linkType: hard
@@ -2126,9 +2126,9 @@ __metadata:
linkType: hard
"@lit-labs/ssr-dom-shim@npm:^1.0.0, @lit-labs/ssr-dom-shim@npm:^1.1.0":
- version: 1.1.2
- resolution: "@lit-labs/ssr-dom-shim@npm:1.1.2"
- checksum: 10/a930f7de57b952dc21317a5754aa0411e000bb4991053cde771c111b7792c4a4cdc896922f0353c832215bed71400431c5ab5a6252c8f4f70bb9ce0b37fe4752
+ version: 1.2.0
+ resolution: "@lit-labs/ssr-dom-shim@npm:1.2.0"
+ checksum: 10/33679defe08538ac6fb612854e7d32b4ea1e787cceba2c3373d26fd56baa9833881887da7bade3930a176ba518dc00bb42ce95d82ddb6af6b05b8fbe1fc3169f
languageName: node
linkType: hard
@@ -2167,6 +2167,15 @@ __metadata:
languageName: node
linkType: hard
+"@lrnwebcomponents/simple-tooltip@patch:@lrnwebcomponents/simple-tooltip@npm%3A8.0.0#~/.yarn/patches/@lrnwebcomponents-simple-tooltip-npm-8.0.0-77591f2e0c.patch":
+ version: 8.0.0
+ resolution: "@lrnwebcomponents/simple-tooltip@patch:@lrnwebcomponents/simple-tooltip@npm%3A8.0.0#~/.yarn/patches/@lrnwebcomponents-simple-tooltip-npm-8.0.0-77591f2e0c.patch::version=8.0.0&hash=91f01a"
+ dependencies:
+ lit: "npm:^3.1.0"
+ checksum: 10/25e2ec2e7379004784ede67419da99a57c2aeb5f7c5747069682b0ca4f28a4e4aaec03a6946d17b33b85407b625d9747af7d0e576f2f1172f8b57090f425fbf9
+ languageName: node
+ linkType: hard
+
"@material/animation@npm:14.0.0-canary.53b3cad2f.0":
version: 14.0.0-canary.53b3cad2f.0
resolution: "@material/animation@npm:14.0.0-canary.53b3cad2f.0"
@@ -3132,13 +3141,13 @@ __metadata:
languageName: node
linkType: hard
-"@material/web@npm:=1.2.0":
- version: 1.2.0
- resolution: "@material/web@npm:1.2.0"
+"@material/web@npm:=1.3.0":
+ version: 1.3.0
+ resolution: "@material/web@npm:1.3.0"
dependencies:
lit: "npm:^2.7.4 || ^3.0.0"
tslib: "npm:^2.4.0"
- checksum: 10/abf79ee6e247b21f046bf099accdb3439d43586f3be948b5f3fc09ab2b47a3a2b37fcaff01dde4205a9e40a3d22312cf314887f87fe930af755c4dc440a32529
+ checksum: 10/7c3427747eccb69628807bed115dca96bb4a8e360e5cb97170a42ab7d469d17f0c925defa417a212ef3237c252f0b06dac9499b56c42945214f9bdeb7f7e5a0b
languageName: node
linkType: hard
@@ -3184,15 +3193,15 @@ __metadata:
linkType: hard
"@npmcli/agent@npm:^2.0.0":
- version: 2.2.0
- resolution: "@npmcli/agent@npm:2.2.0"
+ version: 2.2.1
+ resolution: "@npmcli/agent@npm:2.2.1"
dependencies:
agent-base: "npm:^7.1.0"
http-proxy-agent: "npm:^7.0.0"
https-proxy-agent: "npm:^7.0.1"
lru-cache: "npm:^10.0.1"
socks-proxy-agent: "npm:^8.0.1"
- checksum: 10/822ea077553cd9cfc5cbd6d92380b0950fcb054a7027cd1b63a33bd0cbb16b0c6626ea75d95ec0e804643c8904472d3361d2da8c2444b1fb02a9b525d9c07c41
+ checksum: 10/d4a48128f61e47f2f5c89315a5350e265dc619987e635bd62b52b29c7ed93536e724e721418c0ce352ceece86c13043c67aba1b70c3f5cc72fce6bb746706162
languageName: node
linkType: hard
@@ -3225,8 +3234,8 @@ __metadata:
linkType: hard
"@octokit/core@npm:^5.0.0":
- version: 5.0.2
- resolution: "@octokit/core@npm:5.0.2"
+ version: 5.1.0
+ resolution: "@octokit/core@npm:5.1.0"
dependencies:
"@octokit/auth-token": "npm:^4.0.0"
"@octokit/graphql": "npm:^7.0.0"
@@ -3235,7 +3244,7 @@ __metadata:
"@octokit/types": "npm:^12.0.0"
before-after-hook: "npm:^2.2.0"
universal-user-agent: "npm:^6.0.0"
- checksum: 10/bb991f88793fab043c4c09f9441432596fe0e6448caf42cd2209f52c1f26807418be488ad2cea7a8293e58e79e5c0019f38dda46e8cf96af5e89e43cca37ec3e
+ checksum: 10/8062e86a3088f24a691b36d2c3e9f33e864cefcb5f544b0633650358bce280708b111551cbe855ecf6a5190d6fc4fec1220117c329a2c27525940dd97b868614
languageName: node
linkType: hard
@@ -3308,13 +3317,13 @@ __metadata:
linkType: hard
"@octokit/plugin-rest-endpoint-methods@npm:^10.0.0":
- version: 10.2.0
- resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.2.0"
+ version: 10.3.0
+ resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.3.0"
dependencies:
- "@octokit/types": "npm:^12.3.0"
+ "@octokit/types": "npm:^12.4.0"
peerDependencies:
"@octokit/core": ">=5"
- checksum: 10/0f8ca73b3e582b366b400278f19df6309f263efa3809a9d6ba613063e7a26f16d6f8d69c413bf9b23c2431ad4c795e4e06a43717b6acc1367186fb55347cfb69
+ checksum: 10/be202aca31a513e9e06eda680ae761d05a944a2900523c2041a8ac6bc43e7a5bab0f76bcba09ef96ed48e3b1fabe4104a174b2f839dfb7a2a6f3d632023b4c6a
languageName: node
linkType: hard
@@ -3343,14 +3352,14 @@ __metadata:
linkType: hard
"@octokit/request@npm:^8.0.0, @octokit/request@npm:^8.0.1, @octokit/request@npm:^8.0.2":
- version: 8.1.6
- resolution: "@octokit/request@npm:8.1.6"
+ version: 8.2.0
+ resolution: "@octokit/request@npm:8.2.0"
dependencies:
"@octokit/endpoint": "npm:^9.0.0"
"@octokit/request-error": "npm:^5.0.0"
"@octokit/types": "npm:^12.0.0"
universal-user-agent: "npm:^6.0.0"
- checksum: 10/aebea1c33d607d23c70f663cd5f8279a8bd932ab77b4ca5cca3b33968a347b4adb47476c886086f3a9aa1acefab3b79adac78ee7aa2dacd67eb1f2a05e272618
+ checksum: 10/553ba8b99ea6fe2d3b66b2be6df06f7fe62a0b81e441d334ef25388cf0fcdab4a888fcfe2c1fb1ada262c233bcf7169da3ad5e03f024060ea5723f7753b0de3e
languageName: node
linkType: hard
@@ -3366,12 +3375,12 @@ __metadata:
languageName: node
linkType: hard
-"@octokit/types@npm:^12.0.0, @octokit/types@npm:^12.3.0, @octokit/types@npm:^12.4.0":
- version: 12.4.0
- resolution: "@octokit/types@npm:12.4.0"
+"@octokit/types@npm:^12.0.0, @octokit/types@npm:^12.4.0":
+ version: 12.5.0
+ resolution: "@octokit/types@npm:12.5.0"
dependencies:
"@octokit/openapi-types": "npm:^19.1.0"
- checksum: 10/b0a893e31fed59a919c2072ae67b671aa5f21e00ee3dee689af325f09f12ddd9175ce07c590b835d183bcb1cd2a2da908e02391b2fc33071881561366b2a35e7
+ checksum: 10/a2c8e736e368c781b9389a41fe4ec2cf81563674cf8d74bcc28bf1901dfc4b0c092101c7b333309933b8c14a5a3d1de9ca7eaec93451c41b708b4936e0960894
languageName: node
linkType: hard
@@ -3869,11 +3878,11 @@ __metadata:
linkType: hard
"@sinonjs/commons@npm:^3.0.0":
- version: 3.0.0
- resolution: "@sinonjs/commons@npm:3.0.0"
+ version: 3.0.1
+ resolution: "@sinonjs/commons@npm:3.0.1"
dependencies:
type-detect: "npm:4.0.8"
- checksum: 10/086720ae0bc370829322df32612205141cdd44e592a8a9ca97197571f8f970352ea39d3bda75b347c43789013ddab36b34b59e40380a49bdae1c2df3aa85fe4f
+ checksum: 10/a0af217ba7044426c78df52c23cedede6daf377586f3ac58857c565769358ab1f44ebf95ba04bbe38814fba6e316ca6f02870a009328294fc2c555d0f85a7117
languageName: node
linkType: hard
@@ -3959,7 +3968,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/bonjour@npm:^3.5.9":
+"@types/bonjour@npm:^3.5.13":
version: 3.5.13
resolution: "@types/bonjour@npm:3.5.13"
dependencies:
@@ -3969,12 +3978,12 @@ __metadata:
linkType: hard
"@types/chrome@npm:*":
- version: 0.0.258
- resolution: "@types/chrome@npm:0.0.258"
+ version: 0.0.260
+ resolution: "@types/chrome@npm:0.0.260"
dependencies:
"@types/filesystem": "npm:*"
"@types/har-format": "npm:*"
- checksum: 10/301f60ba009832f8eff232159234a4b73db2d7925eae1b67a1a4687da80d56022430bc722e8c4effc0a12c1868c0bb380e981ef8b6ba744bbe52bf47591a8198
+ checksum: 10/4e7d6e5e3bd67bc481c6524aacce902568ba8f78b7da3fe1f2999f8f01863240847f1b05a358d38dbd2afdbe112dfd9ff84912a664c40595e9e4266eef3891cc
languageName: node
linkType: hard
@@ -3994,6 +4003,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/color-name@npm:1.1.3":
+ version: 1.1.3
+ resolution: "@types/color-name@npm:1.1.3"
+ checksum: 10/9060d16d0bce2cdf562d6da54e18c5f23e80308ccb58b725b9173a028818f27d8e01c8a5cd96952e76f11145a7388ed7d2f450fb4652f4760383834f2e698263
+ languageName: node
+ linkType: hard
+
"@types/command-line-args@npm:^5.0.0":
version: 5.2.3
resolution: "@types/command-line-args@npm:5.2.3"
@@ -4001,7 +4017,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/connect-history-api-fallback@npm:^1.3.5":
+"@types/connect-history-api-fallback@npm:^1.5.4":
version: 1.5.4
resolution: "@types/connect-history-api-fallback@npm:1.5.4"
dependencies:
@@ -4028,14 +4044,14 @@ __metadata:
linkType: hard
"@types/cookies@npm:*":
- version: 0.7.10
- resolution: "@types/cookies@npm:0.7.10"
+ version: 0.9.0
+ resolution: "@types/cookies@npm:0.9.0"
dependencies:
"@types/connect": "npm:*"
"@types/express": "npm:*"
"@types/keygrip": "npm:*"
"@types/node": "npm:*"
- checksum: 10/85d4b434bac9a971d8a4122d5a7c947dcaaca98fee26e90e0b792b1046da1de414dc37ea164b1693653b9b59f72c501927de90412a3a1dff2c7bdb6abadc3608
+ checksum: 10/88d2106834fca85cf9dfef984e99bf4969e77d48538d8e8408a29679b4d1f675fe4725d35f2e38d252a336b76d14a2bc84bcb34edc72238a7a8261c0808c7c56
languageName: node
linkType: hard
@@ -4074,18 +4090,18 @@ __metadata:
linkType: hard
"@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33":
- version: 4.17.41
- resolution: "@types/express-serve-static-core@npm:4.17.41"
+ version: 4.17.43
+ resolution: "@types/express-serve-static-core@npm:4.17.43"
dependencies:
"@types/node": "npm:*"
"@types/qs": "npm:*"
"@types/range-parser": "npm:*"
"@types/send": "npm:*"
- checksum: 10/7647e19d9c3d57ddd18947d2b161b90ef0aedd15875140e5b824209be41c1084ae942d4fb43cd5f2051a6a5f8c044519ef6c9ac1b2ad86b9aa546b4f1f023303
+ checksum: 10/9079e137470e0456bb8e77ae66df9505ee12591e94860bde574cfe52c5c60bbc5bf7dd44f5689c3cbb1baf0aa84442d9a21f53dcd921d18745727293cd5a5fd6
languageName: node
linkType: hard
-"@types/express@npm:*, @types/express@npm:^4.17.13":
+"@types/express@npm:*, @types/express@npm:^4.17.21":
version: 4.17.21
resolution: "@types/express@npm:4.17.21"
dependencies:
@@ -4107,16 +4123,16 @@ __metadata:
linkType: hard
"@types/filewriter@npm:*":
- version: 0.0.32
- resolution: "@types/filewriter@npm:0.0.32"
- checksum: 10/fe2f19239c23c63c009c6d422227d692bc2a0cd1113f8ce31b0fb7048f32ec018003172199949843fdbb1c5988551c29e1e9e2238b9c160969b5e5edbfb76424
+ version: 0.0.33
+ resolution: "@types/filewriter@npm:0.0.33"
+ checksum: 10/495a4bb424c27eda967fe9ac3b8f7b781e6b3f9ce59403a991590cb1073022f9c5383d3c7d808ef6956b785550c36664c4fcd502dc0baf69e340bd481171e0ca
languageName: node
linkType: hard
"@types/geojson@npm:*":
- version: 7946.0.13
- resolution: "@types/geojson@npm:7946.0.13"
- checksum: 10/b3b68457c89bc3f0445dc9eb54d07e6f89658672867c54989bc7f71f87d54e562195b291d43e1b84476493351271d7ccb9f5c6ab2012b29fbafbb0e8e43c4bca
+ version: 7946.0.14
+ resolution: "@types/geojson@npm:7946.0.14"
+ checksum: 10/ae511bee6488ae3bd5a3a3347aedb0371e997b14225b8983679284e22fa4ebd88627c6e3ff8b08bf4cc35068cb29310c89427311ffc9322c255615821a922e71
languageName: node
linkType: hard
@@ -4306,11 +4322,11 @@ __metadata:
linkType: hard
"@types/node@npm:*":
- version: 20.11.5
- resolution: "@types/node@npm:20.11.5"
+ version: 20.11.19
+ resolution: "@types/node@npm:20.11.19"
dependencies:
undici-types: "npm:~5.26.4"
- checksum: 10/9f31c471047d7b3e240ce7b77ff29b0d15e83be7e3feafb3d0b0d0931122b438b1eefa302a5a2e1e9849914ff3fd76aafbd8ccb372efb1331ba048da63bce6f8
+ checksum: 10/c7f4705d6c84aa21679ad180c33c13ca9567f650e66e14bcee77c7c43d14619c7cd3b4d7b2458947143030b7b1930180efa6d12d999b45366abff9fed7a17472
languageName: node
linkType: hard
@@ -4397,17 +4413,17 @@ __metadata:
languageName: node
linkType: hard
-"@types/retry@npm:0.12.0":
- version: 0.12.0
- resolution: "@types/retry@npm:0.12.0"
- checksum: 10/bbd0b88f4b3eba7b7acfc55ed09c65ef6f2e1bcb4ec9b4dca82c66566934351534317d294a770a7cc6c0468d5573c5350abab6e37c65f8ef254443e1b028e44d
+"@types/retry@npm:0.12.2":
+ version: 0.12.2
+ resolution: "@types/retry@npm:0.12.2"
+ checksum: 10/e5675035717b39ce4f42f339657cae9637cf0c0051cf54314a6a2c44d38d91f6544be9ddc0280587789b6afd056be5d99dbe3e9f4df68c286c36321579b1bf4a
languageName: node
linkType: hard
"@types/semver@npm:^7.5.0":
- version: 7.5.6
- resolution: "@types/semver@npm:7.5.6"
- checksum: 10/e77282b17f74354e17e771c0035cccb54b94cc53d0433fa7e9ba9d23fd5d7edcd14b6c8b7327d58bbd89e83b1c5eda71dfe408e06b929007e2b89586e9b63459
+ version: 7.5.7
+ resolution: "@types/semver@npm:7.5.7"
+ checksum: 10/535d88ec577fe59e38211881f79a1e2ba391e9e1516f8fff74e7196a5ba54315bace9c67a4616c334c830c89027d70a9f473a4ceb634526086a9da39180f2f9a
languageName: node
linkType: hard
@@ -4430,7 +4446,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/serve-index@npm:^1.9.1":
+"@types/serve-index@npm:^1.9.4":
version: 1.9.4
resolution: "@types/serve-index@npm:1.9.4"
dependencies:
@@ -4439,7 +4455,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/serve-static@npm:*, @types/serve-static@npm:^1.13.10":
+"@types/serve-static@npm:*, @types/serve-static@npm:^1.15.5":
version: 1.15.5
resolution: "@types/serve-static@npm:1.15.5"
dependencies:
@@ -4450,7 +4466,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/sockjs@npm:^0.3.33":
+"@types/sockjs@npm:^0.3.36":
version: 0.3.36
resolution: "@types/sockjs@npm:0.3.36"
dependencies:
@@ -4459,10 +4475,10 @@ __metadata:
languageName: node
linkType: hard
-"@types/sortablejs@npm:1.15.7":
- version: 1.15.7
- resolution: "@types/sortablejs@npm:1.15.7"
- checksum: 10/422fb6a4862723567a0750339aff0ed8cfdbb4c5bc2601111481c1c2a23de5d6679c7f8dfd76daf2037e2d4df02e42fcd3203251aead64d5629968ead220cf10
+"@types/sortablejs@npm:1.15.8":
+ version: 1.15.8
+ resolution: "@types/sortablejs@npm:1.15.8"
+ checksum: 10/aea58b08cf45f5e9633707a8df0df1212595c731bbdfd29805487138fdd0d8c51fa5c741999738a645c1e801d43a92ba0d3fb5b45625b52e247c56588aef6c55
languageName: node
linkType: hard
@@ -4506,7 +4522,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/ws@npm:^8.5.5":
+"@types/ws@npm:^8.5.10":
version: 8.5.10
resolution: "@types/ws@npm:8.5.10"
dependencies:
@@ -4515,15 +4531,15 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/eslint-plugin@npm:6.20.0":
- version: 6.20.0
- resolution: "@typescript-eslint/eslint-plugin@npm:6.20.0"
+"@typescript-eslint/eslint-plugin@npm:7.0.2":
+ version: 7.0.2
+ resolution: "@typescript-eslint/eslint-plugin@npm:7.0.2"
dependencies:
"@eslint-community/regexpp": "npm:^4.5.1"
- "@typescript-eslint/scope-manager": "npm:6.20.0"
- "@typescript-eslint/type-utils": "npm:6.20.0"
- "@typescript-eslint/utils": "npm:6.20.0"
- "@typescript-eslint/visitor-keys": "npm:6.20.0"
+ "@typescript-eslint/scope-manager": "npm:7.0.2"
+ "@typescript-eslint/type-utils": "npm:7.0.2"
+ "@typescript-eslint/utils": "npm:7.0.2"
+ "@typescript-eslint/visitor-keys": "npm:7.0.2"
debug: "npm:^4.3.4"
graphemer: "npm:^1.4.0"
ignore: "npm:^5.2.4"
@@ -4531,73 +4547,73 @@ __metadata:
semver: "npm:^7.5.4"
ts-api-utils: "npm:^1.0.1"
peerDependencies:
- "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha
- eslint: ^7.0.0 || ^8.0.0
+ "@typescript-eslint/parser": ^7.0.0
+ eslint: ^8.56.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10/dee6a2392c831e6ae69611ecc4de06e66a7b16f6bf6d8e3bfd25091eb14d88c9d0bb9c9cd634efcfa318902341f7a459cf48f713d55cb1d610145ca1f52af4d3
+ checksum: 10/430b2f7ca36ee73dc75c1d677088709f3c9d5bbb4fffa3cfbe1b7d63979ee397f7a4a2a1386e05a04991500fa0ab0dd5272e8603a2b20f42e4bf590603500858
languageName: node
linkType: hard
-"@typescript-eslint/parser@npm:6.20.0":
- version: 6.20.0
- resolution: "@typescript-eslint/parser@npm:6.20.0"
+"@typescript-eslint/parser@npm:7.0.2":
+ version: 7.0.2
+ resolution: "@typescript-eslint/parser@npm:7.0.2"
dependencies:
- "@typescript-eslint/scope-manager": "npm:6.20.0"
- "@typescript-eslint/types": "npm:6.20.0"
- "@typescript-eslint/typescript-estree": "npm:6.20.0"
- "@typescript-eslint/visitor-keys": "npm:6.20.0"
+ "@typescript-eslint/scope-manager": "npm:7.0.2"
+ "@typescript-eslint/types": "npm:7.0.2"
+ "@typescript-eslint/typescript-estree": "npm:7.0.2"
+ "@typescript-eslint/visitor-keys": "npm:7.0.2"
debug: "npm:^4.3.4"
peerDependencies:
- eslint: ^7.0.0 || ^8.0.0
+ eslint: ^8.56.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10/691062d47cae7977604ede848ffff3689162428a53577f298989f585954aa3a3450e7fd5c2b363d024cd5f16022c163cecf0f1f1d138234bbd78048050b4b8bf
+ checksum: 10/18d6e1bda64013f7d66164164c57a10390f7979db55b265062ae9337e11e0921bffca10870e252cd0bd198f79ffa2e87a652e57110e5b1b4cc738453154c205c
languageName: node
linkType: hard
-"@typescript-eslint/scope-manager@npm:6.20.0":
- version: 6.20.0
- resolution: "@typescript-eslint/scope-manager@npm:6.20.0"
+"@typescript-eslint/scope-manager@npm:7.0.2":
+ version: 7.0.2
+ resolution: "@typescript-eslint/scope-manager@npm:7.0.2"
dependencies:
- "@typescript-eslint/types": "npm:6.20.0"
- "@typescript-eslint/visitor-keys": "npm:6.20.0"
- checksum: 10/2c1a644f2931454b34875f2e6dffad52a1fc7b6ac508d7d1ad3cd9da028a7dff9c6191feeea2c9ca691deba199ac9e83cbd0036914be4cd45b6954437f03c09a
+ "@typescript-eslint/types": "npm:7.0.2"
+ "@typescript-eslint/visitor-keys": "npm:7.0.2"
+ checksum: 10/773ea6e61f741777e69a469641f3db0d3c2301c0102667825fb235ed5a65c95f6d6b31b19e734b9a215acc0c7c576c65497635b8d5928eeddb58653ceb13d2d5
languageName: node
linkType: hard
-"@typescript-eslint/type-utils@npm:6.20.0":
- version: 6.20.0
- resolution: "@typescript-eslint/type-utils@npm:6.20.0"
+"@typescript-eslint/type-utils@npm:7.0.2":
+ version: 7.0.2
+ resolution: "@typescript-eslint/type-utils@npm:7.0.2"
dependencies:
- "@typescript-eslint/typescript-estree": "npm:6.20.0"
- "@typescript-eslint/utils": "npm:6.20.0"
+ "@typescript-eslint/typescript-estree": "npm:7.0.2"
+ "@typescript-eslint/utils": "npm:7.0.2"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.0.1"
peerDependencies:
- eslint: ^7.0.0 || ^8.0.0
+ eslint: ^8.56.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10/bc2f2793cfec3463164b5f5ded31b4e169e21c3a1990c1ce4effe70a359c486d92fbbc4cd92758bbf1c30a468ad0839e0fa890bd452c707d0c294cb3a7b14021
+ checksum: 10/63bf19c9f5bbcb0f3e127f509d85dc49be4e5e51781d78f58c96786089e7c909b25d35d0248a6a758e2f7d5b5223d2262c2d597ab71f226af6beb499ae950645
languageName: node
linkType: hard
-"@typescript-eslint/types@npm:6.20.0":
- version: 6.20.0
- resolution: "@typescript-eslint/types@npm:6.20.0"
- checksum: 10/74ed1761e27c3c1a29fd260fe51096f42cfb1472b20390d6df6ec41de0420208f379e809de416e81cd7c00fdc3d5550b2391872be56bf4a1b0c595f71db0b1ea
+"@typescript-eslint/types@npm:7.0.2":
+ version: 7.0.2
+ resolution: "@typescript-eslint/types@npm:7.0.2"
+ checksum: 10/2cba8a0355cc7357db142fa597d02cf39e1d1cb0ec87c80e91daaa2b87f2a794d2649def9d7b2aa435691c3810d2cbd4cdc21668b19b991863f0d54d4a22da82
languageName: node
linkType: hard
-"@typescript-eslint/typescript-estree@npm:6.20.0":
- version: 6.20.0
- resolution: "@typescript-eslint/typescript-estree@npm:6.20.0"
+"@typescript-eslint/typescript-estree@npm:7.0.2":
+ version: 7.0.2
+ resolution: "@typescript-eslint/typescript-estree@npm:7.0.2"
dependencies:
- "@typescript-eslint/types": "npm:6.20.0"
- "@typescript-eslint/visitor-keys": "npm:6.20.0"
+ "@typescript-eslint/types": "npm:7.0.2"
+ "@typescript-eslint/visitor-keys": "npm:7.0.2"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
@@ -4607,34 +4623,34 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10/55b280c6e71c79cb009ac80189a7f0e1aa9011bc7206c810bbb52d9703a894aa2817dfd44d947edf64d62f3aa0962e01f3423fcb21d2f39964a4840287d9e196
+ checksum: 10/307080e29c22fc69f0ce7ab7101e1629e05f45a9e541c250e03d06b61336ab0ccb5f0a7354ee3da4e38d5cade4dd2fb7bb396cd7cbe74c2c4b3e29706a70abcc
languageName: node
linkType: hard
-"@typescript-eslint/utils@npm:6.20.0":
- version: 6.20.0
- resolution: "@typescript-eslint/utils@npm:6.20.0"
+"@typescript-eslint/utils@npm:7.0.2":
+ version: 7.0.2
+ resolution: "@typescript-eslint/utils@npm:7.0.2"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0"
"@types/json-schema": "npm:^7.0.12"
"@types/semver": "npm:^7.5.0"
- "@typescript-eslint/scope-manager": "npm:6.20.0"
- "@typescript-eslint/types": "npm:6.20.0"
- "@typescript-eslint/typescript-estree": "npm:6.20.0"
+ "@typescript-eslint/scope-manager": "npm:7.0.2"
+ "@typescript-eslint/types": "npm:7.0.2"
+ "@typescript-eslint/typescript-estree": "npm:7.0.2"
semver: "npm:^7.5.4"
peerDependencies:
- eslint: ^7.0.0 || ^8.0.0
- checksum: 10/6d4604be6123e0073dd5e7dd357c95b370c678572d2e982478d0d6937d4d65f0cad0ac207b8b724f3bce239e64ba1ddd6bece11e1592734d8bf691177e6971e6
+ eslint: ^8.56.0
+ checksum: 10/e68bac777419cd529371f7f29f534efaeca130c90ed9723bfc7aac451d61ca3fc4ebd310e2c015e29e8dc7be4734ae46258ca8755897d7f5e3bb502660d5372f
languageName: node
linkType: hard
-"@typescript-eslint/visitor-keys@npm:6.20.0":
- version: 6.20.0
- resolution: "@typescript-eslint/visitor-keys@npm:6.20.0"
+"@typescript-eslint/visitor-keys@npm:7.0.2":
+ version: 7.0.2
+ resolution: "@typescript-eslint/visitor-keys@npm:7.0.2"
dependencies:
- "@typescript-eslint/types": "npm:6.20.0"
+ "@typescript-eslint/types": "npm:7.0.2"
eslint-visitor-keys: "npm:^3.4.1"
- checksum: 10/df066c73f3880ad78880c442f307e58f026e6047d9caab9d7c356d13276f4fe466fab3e8d19cdb1e6749e87639cb7c4babcfe118f554fcd2d3929ce9f4983216
+ checksum: 10/da6c1b0729af99216cde3a65d4e91584a81fc6c9dff7ba291089f01bf7262de375f58c4c4246e5fbc29f51258db7725d9c830f82ccbd1cda812fd13c51480cda
languageName: node
linkType: hard
@@ -4645,128 +4661,128 @@ __metadata:
languageName: node
linkType: hard
-"@vaadin/a11y-base@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/a11y-base@npm:24.3.5"
+"@vaadin/a11y-base@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/a11y-base@npm:24.3.6"
dependencies:
"@open-wc/dedupe-mixin": "npm:^1.3.0"
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/component-base": "npm:~24.3.5"
+ "@vaadin/component-base": "npm:~24.3.6"
lit: "npm:^3.0.0"
- checksum: 10/17120df44a410e9c0b449b51c0b3380e6a2a0f92b7ea37746c3b20070849df535fa81ca4513219863e15009a5b04427b294fd467c692330f37b89db333d550f2
+ checksum: 10/ba101554e829c569fe71cd05642e00437fc3bad7a4a106421843410459bb874eb6f484ca8ebb17f215577aa2e517dd64a84509d07dcd96bd0ab8eb0b62f30346
languageName: node
linkType: hard
-"@vaadin/combo-box@npm:24.3.5":
- version: 24.3.5
- resolution: "@vaadin/combo-box@npm:24.3.5"
+"@vaadin/combo-box@npm:24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/combo-box@npm:24.3.6"
dependencies:
"@open-wc/dedupe-mixin": "npm:^1.3.0"
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/a11y-base": "npm:~24.3.5"
- "@vaadin/component-base": "npm:~24.3.5"
- "@vaadin/field-base": "npm:~24.3.5"
- "@vaadin/input-container": "npm:~24.3.5"
- "@vaadin/item": "npm:~24.3.5"
- "@vaadin/lit-renderer": "npm:~24.3.5"
- "@vaadin/overlay": "npm:~24.3.5"
- "@vaadin/vaadin-lumo-styles": "npm:~24.3.5"
- "@vaadin/vaadin-material-styles": "npm:~24.3.5"
- "@vaadin/vaadin-themable-mixin": "npm:~24.3.5"
- checksum: 10/ca61dc04d997eb2c4ba0e6433f199b139ed8e310a29cad2962c6ed610bafd8103638876c1f01ebe97b284fca535e5f86f7d6c4d48931e5e99f488675df197660
+ "@vaadin/a11y-base": "npm:~24.3.6"
+ "@vaadin/component-base": "npm:~24.3.6"
+ "@vaadin/field-base": "npm:~24.3.6"
+ "@vaadin/input-container": "npm:~24.3.6"
+ "@vaadin/item": "npm:~24.3.6"
+ "@vaadin/lit-renderer": "npm:~24.3.6"
+ "@vaadin/overlay": "npm:~24.3.6"
+ "@vaadin/vaadin-lumo-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-material-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-themable-mixin": "npm:~24.3.6"
+ checksum: 10/f05cb153a666227163031726b353b81500265ed614c3705cd5e81e9a6ec0235a0e207109b17958e9c5164b2c4d79ca25583400d4286cb1114221a0046d7c3e05
languageName: node
linkType: hard
-"@vaadin/component-base@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/component-base@npm:24.3.5"
+"@vaadin/component-base@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/component-base@npm:24.3.6"
dependencies:
"@open-wc/dedupe-mixin": "npm:^1.3.0"
"@polymer/polymer": "npm:^3.0.0"
"@vaadin/vaadin-development-mode-detector": "npm:^2.0.0"
"@vaadin/vaadin-usage-statistics": "npm:^2.1.0"
lit: "npm:^3.0.0"
- checksum: 10/cc9ef67334b0f145952d68a5ccf24fcce6a86f6cd548d07356e540a8f84f08d4567182856a597e8ed3c2650ffc0acbde181fe72502a6eb9ecf024afc3a564dde
+ checksum: 10/2bf4571a35f1d07a8da1a77c59d280add5b25a67aaf4e54a731ee10424125a028b01c06c54aa861f4892a5ce69cc4b1c84a37a1058588d10cd05bb34514601b6
languageName: node
linkType: hard
-"@vaadin/field-base@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/field-base@npm:24.3.5"
+"@vaadin/field-base@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/field-base@npm:24.3.6"
dependencies:
"@open-wc/dedupe-mixin": "npm:^1.3.0"
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/a11y-base": "npm:~24.3.5"
- "@vaadin/component-base": "npm:~24.3.5"
+ "@vaadin/a11y-base": "npm:~24.3.6"
+ "@vaadin/component-base": "npm:~24.3.6"
lit: "npm:^3.0.0"
- checksum: 10/8ae5844791d1e4385780b254c149f5f320998c36eb932f7d04f08a8fcbb30f41d009e59738823c0b3836ce9214b047a17124721ca3fc622f137ef42030a68c1b
+ checksum: 10/71f407f8ca1801d7453a49f8d130e66c5a9999c8ddbfd1569a6e5141c372670b71cb195587a2a562a3965d2ac28e5fc022dcef4a98c96568ae78ad759ddb9d7c
languageName: node
linkType: hard
-"@vaadin/icon@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/icon@npm:24.3.5"
+"@vaadin/icon@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/icon@npm:24.3.6"
dependencies:
"@open-wc/dedupe-mixin": "npm:^1.3.0"
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/component-base": "npm:~24.3.5"
- "@vaadin/vaadin-lumo-styles": "npm:~24.3.5"
- "@vaadin/vaadin-themable-mixin": "npm:~24.3.5"
+ "@vaadin/component-base": "npm:~24.3.6"
+ "@vaadin/vaadin-lumo-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-themable-mixin": "npm:~24.3.6"
lit: "npm:^3.0.0"
- checksum: 10/f48d647e73e513c4d730faab4f4cd543918574ffdd3bcb6d1586d67b13e5428618b44b034ce49eda68fe2b806ae827f7625fc93eb2d94046128e779783cefe02
+ checksum: 10/cffe77e5b1f6feb44b1f839c462580d5162cc1782e1701c292323068584e2a7747794473e46c3aa22c8fe6f1410a98e3bbd5a220ae6805c6759fec511e14675f
languageName: node
linkType: hard
-"@vaadin/input-container@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/input-container@npm:24.3.5"
+"@vaadin/input-container@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/input-container@npm:24.3.6"
dependencies:
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/component-base": "npm:~24.3.5"
- "@vaadin/vaadin-lumo-styles": "npm:~24.3.5"
- "@vaadin/vaadin-material-styles": "npm:~24.3.5"
- "@vaadin/vaadin-themable-mixin": "npm:~24.3.5"
+ "@vaadin/component-base": "npm:~24.3.6"
+ "@vaadin/vaadin-lumo-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-material-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-themable-mixin": "npm:~24.3.6"
lit: "npm:^3.0.0"
- checksum: 10/b942c6657809e2a65cf317e0526786eb7206abff57dfe9fb0611245a5b5334307a589a78fa358b2d6f02bfe4534691295871db326db34bf4014c50fec5ed1f7f
+ checksum: 10/6fd86c09ba47ea2937896826f1646155d53d3e9d363031f2a6c81774f6224e8cff1038f400ebf75b9de3c0084c65952226e5309b4b5649b69a3e66ef8ad84e65
languageName: node
linkType: hard
-"@vaadin/item@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/item@npm:24.3.5"
+"@vaadin/item@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/item@npm:24.3.6"
dependencies:
"@open-wc/dedupe-mixin": "npm:^1.3.0"
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/a11y-base": "npm:~24.3.5"
- "@vaadin/component-base": "npm:~24.3.5"
- "@vaadin/vaadin-lumo-styles": "npm:~24.3.5"
- "@vaadin/vaadin-material-styles": "npm:~24.3.5"
- "@vaadin/vaadin-themable-mixin": "npm:~24.3.5"
- checksum: 10/1a428afd6f26f3f35465469d891a14198fb0bf46287e624139c585845a17352d9d013a54f96343b1790f8a9de2cb9796f2014ec58bc794d1215329038505313a
+ "@vaadin/a11y-base": "npm:~24.3.6"
+ "@vaadin/component-base": "npm:~24.3.6"
+ "@vaadin/vaadin-lumo-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-material-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-themable-mixin": "npm:~24.3.6"
+ checksum: 10/d38f8219c8e9ba6acb833444eca2894723e83c06ce7557d0796042969899323ca9c19331639f6c677b49be79cda705da7d0d4251cd8370003df39f448f668835
languageName: node
linkType: hard
-"@vaadin/lit-renderer@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/lit-renderer@npm:24.3.5"
+"@vaadin/lit-renderer@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/lit-renderer@npm:24.3.6"
dependencies:
lit: "npm:^3.0.0"
- checksum: 10/232437d961102cdf5dee1828f0bd1ec7e2791bbce648cc0ac8860fb4e9a8ccad0dd49daa3bf1cd2d30cd5f0ad9dea149b9963bd847fba0299a7ae6775bf5dfdf
+ checksum: 10/5e2c93f9ccbe037a9d20338954dd4cd01511c3f481b0091623892f31194483661781650cbee52c64ebb8c3be99e1500cac90e460b82d781d6bf4c436ca1f2039
languageName: node
linkType: hard
-"@vaadin/overlay@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/overlay@npm:24.3.5"
+"@vaadin/overlay@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/overlay@npm:24.3.6"
dependencies:
"@open-wc/dedupe-mixin": "npm:^1.3.0"
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/a11y-base": "npm:~24.3.5"
- "@vaadin/component-base": "npm:~24.3.5"
- "@vaadin/vaadin-lumo-styles": "npm:~24.3.5"
- "@vaadin/vaadin-material-styles": "npm:~24.3.5"
- "@vaadin/vaadin-themable-mixin": "npm:~24.3.5"
- checksum: 10/1e171da246fae2a8cde03ba020773c09bb67cf384fa683501d7e63ea97528dd025e65c7a4a6c7c98d9c743c06b496e6926f24d7b94aac251f68931b65ace2d91
+ "@vaadin/a11y-base": "npm:~24.3.6"
+ "@vaadin/component-base": "npm:~24.3.6"
+ "@vaadin/vaadin-lumo-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-material-styles": "npm:~24.3.6"
+ "@vaadin/vaadin-themable-mixin": "npm:~24.3.6"
+ checksum: 10/f2f8a8125a957999a8b184ab56516b29856f0ba3f6ab75f7e0bcde8a6d477d0342f2fd1dbc2ee0ac7b8bc6b320cf9c22227503cf9854a7000792da6644ce2078
languageName: node
linkType: hard
@@ -4777,36 +4793,36 @@ __metadata:
languageName: node
linkType: hard
-"@vaadin/vaadin-lumo-styles@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/vaadin-lumo-styles@npm:24.3.5"
+"@vaadin/vaadin-lumo-styles@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/vaadin-lumo-styles@npm:24.3.6"
dependencies:
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/component-base": "npm:~24.3.5"
- "@vaadin/icon": "npm:~24.3.5"
- "@vaadin/vaadin-themable-mixin": "npm:~24.3.5"
- checksum: 10/d19c0bd8ad03aafee5cf24ef49c1f351972581b70af491e9a6b46011a2c761ec46c0897883f5dd9f6a555c85985d747a97455ebe9ee588ca8e4875a452fc6f1e
+ "@vaadin/component-base": "npm:~24.3.6"
+ "@vaadin/icon": "npm:~24.3.6"
+ "@vaadin/vaadin-themable-mixin": "npm:~24.3.6"
+ checksum: 10/158bedb18919229dc743821bbac6510b50b825d901265b71512f980d478675f675491a129f65de955c74ca367a1d97d7fd5691283a255f507ed28522722a209e
languageName: node
linkType: hard
-"@vaadin/vaadin-material-styles@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/vaadin-material-styles@npm:24.3.5"
+"@vaadin/vaadin-material-styles@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/vaadin-material-styles@npm:24.3.6"
dependencies:
"@polymer/polymer": "npm:^3.0.0"
- "@vaadin/component-base": "npm:~24.3.5"
- "@vaadin/vaadin-themable-mixin": "npm:~24.3.5"
- checksum: 10/4685b035992389bf48745a7591380c8fa13dda32b6ff6df8685b16768e52fb35ab23e7e46805dd5eda419417660adf483ce600699fdd0476e9a74226ed3adc39
+ "@vaadin/component-base": "npm:~24.3.6"
+ "@vaadin/vaadin-themable-mixin": "npm:~24.3.6"
+ checksum: 10/76835be72e6d08727a38cdec11c54565c7319eb1010ee5404f78acc7b6d8e8f5c363f9c5e9c149507a42a7ee7b075e8e0aae78aeaa375f4db3b0a97ee0cabc15
languageName: node
linkType: hard
-"@vaadin/vaadin-themable-mixin@npm:24.3.5, @vaadin/vaadin-themable-mixin@npm:~24.3.5":
- version: 24.3.5
- resolution: "@vaadin/vaadin-themable-mixin@npm:24.3.5"
+"@vaadin/vaadin-themable-mixin@npm:24.3.6, @vaadin/vaadin-themable-mixin@npm:~24.3.6":
+ version: 24.3.6
+ resolution: "@vaadin/vaadin-themable-mixin@npm:24.3.6"
dependencies:
"@open-wc/dedupe-mixin": "npm:^1.3.0"
lit: "npm:^3.0.0"
- checksum: 10/faab5b044dfae77a5f558d006ca7debc4f6134e7eef47df538c35fd611ba02be0ae59d66d9574c5ce1aeea60a005fc4213f11259760352f370eefa60c47024b6
+ checksum: 10/93b2f78bf2ad8575caedb1a0f7742d6f7e3920c362d74da6addf2d00de152e9a6e588cfa0b47f1aea76322fd031ae65446d80c6015591c7e00e4124afe07ffbb
languageName: node
linkType: hard
@@ -4930,9 +4946,9 @@ __metadata:
linkType: hard
"@vscode/web-custom-data@npm:^0.4.2":
- version: 0.4.8
- resolution: "@vscode/web-custom-data@npm:0.4.8"
- checksum: 10/556106530e399321d1412d0074d1a4dcfc04c17fc334df8de4f10469a2ad6f83c7245caf92174817c5bf032ec5ffd894bc418889d76a2a7d163ad0e4c910adf0
+ version: 0.4.9
+ resolution: "@vscode/web-custom-data@npm:0.4.9"
+ checksum: 10/6ccc98c43b0ead4f320dab2e33df3570590d4d3e94edf54b722c3b376fc236abb5a6e9e7655942044cf7ebe4f305a58bc58c1d8d4b251b9434d1db1266797e2e
languageName: node
linkType: hard
@@ -5672,13 +5688,13 @@ __metadata:
languageName: node
linkType: hard
-"array-buffer-byte-length@npm:^1.0.0":
- version: 1.0.0
- resolution: "array-buffer-byte-length@npm:1.0.0"
+"array-buffer-byte-length@npm:^1.0.1":
+ version: 1.0.1
+ resolution: "array-buffer-byte-length@npm:1.0.1"
dependencies:
- call-bind: "npm:^1.0.2"
- is-array-buffer: "npm:^3.0.1"
- checksum: 10/044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3
+ call-bind: "npm:^1.0.5"
+ is-array-buffer: "npm:^3.0.4"
+ checksum: 10/53524e08f40867f6a9f35318fafe467c32e45e9c682ba67b11943e167344d2febc0f6977a17e699b05699e805c3e8f073d876f8bbf1b559ed494ad2cd0fae09e
languageName: node
linkType: hard
@@ -5767,6 +5783,19 @@ __metadata:
languageName: node
linkType: hard
+"array.prototype.filter@npm:^1.0.3":
+ version: 1.0.3
+ resolution: "array.prototype.filter@npm:1.0.3"
+ dependencies:
+ call-bind: "npm:^1.0.2"
+ define-properties: "npm:^1.2.0"
+ es-abstract: "npm:^1.22.1"
+ es-array-method-boxes-properly: "npm:^1.0.0"
+ is-string: "npm:^1.0.7"
+ checksum: 10/3da2189afb00f95559cc73fc3c50f17a071a65bb705c0b2f2e2a2b2142781215b622442368c8b4387389b6ab251adf09ad347f9a8a4cf29d24404cc5ea1e295c
+ languageName: node
+ linkType: hard
+
"array.prototype.find@npm:^2.2.2":
version: 2.2.2
resolution: "array.prototype.find@npm:2.2.2"
@@ -5780,15 +5809,15 @@ __metadata:
linkType: hard
"array.prototype.findlastindex@npm:^1.2.3":
- version: 1.2.3
- resolution: "array.prototype.findlastindex@npm:1.2.3"
+ version: 1.2.4
+ resolution: "array.prototype.findlastindex@npm:1.2.4"
dependencies:
- call-bind: "npm:^1.0.2"
- define-properties: "npm:^1.2.0"
- es-abstract: "npm:^1.22.1"
- es-shim-unscopables: "npm:^1.0.0"
- get-intrinsic: "npm:^1.2.1"
- checksum: 10/063cbab8eeac3aa01f3e980eecb9a8c5d87723032b49f7f814ecc6d75c33c03c17e3f43a458127a62e16303cab412f95d6ad9dc7e0ae6d9dc27a9bb76c24df7a
+ call-bind: "npm:^1.0.5"
+ define-properties: "npm:^1.2.1"
+ es-abstract: "npm:^1.22.3"
+ es-errors: "npm:^1.3.0"
+ es-shim-unscopables: "npm:^1.0.2"
+ checksum: 10/12d7de8da619065b9d4c40550d11c13f2fbbc863c4270ef01d022f49ef16fbe9022441ee9d60b1e952853c661dd4b3e05c21e4348d4631c6d93ddf802a252296
languageName: node
linkType: hard
@@ -5816,25 +5845,19 @@ __metadata:
languageName: node
linkType: hard
-"arraybuffer.prototype.slice@npm:^1.0.2":
- version: 1.0.2
- resolution: "arraybuffer.prototype.slice@npm:1.0.2"
+"arraybuffer.prototype.slice@npm:^1.0.3":
+ version: 1.0.3
+ resolution: "arraybuffer.prototype.slice@npm:1.0.3"
dependencies:
- array-buffer-byte-length: "npm:^1.0.0"
- call-bind: "npm:^1.0.2"
- define-properties: "npm:^1.2.0"
- es-abstract: "npm:^1.22.1"
- get-intrinsic: "npm:^1.2.1"
- is-array-buffer: "npm:^3.0.2"
+ array-buffer-byte-length: "npm:^1.0.1"
+ call-bind: "npm:^1.0.5"
+ define-properties: "npm:^1.2.1"
+ es-abstract: "npm:^1.22.3"
+ es-errors: "npm:^1.2.1"
+ get-intrinsic: "npm:^1.2.3"
+ is-array-buffer: "npm:^3.0.4"
is-shared-array-buffer: "npm:^1.0.2"
- checksum: 10/c200faf437786f5b2c80d4564ff5481c886a16dee642ef02abdc7306c7edd523d1f01d1dd12b769c7eb42ac9bc53874510db19a92a2c035c0f6696172aafa5d3
- languageName: node
- linkType: hard
-
-"asap@npm:~2.0.6":
- version: 2.0.6
- resolution: "asap@npm:2.0.6"
- checksum: 10/b244c0458c571945e4b3be0b14eb001bea5596f9868cc50cc711dc03d58a7e953517d3f0dad81ccde3ff37d1f074701fa76a6f07d41aaa992d7204a37b915dda
+ checksum: 10/0221f16c1e3ec7b67da870ee0e1f12b825b5f9189835392b59a22990f715827561a4f4cd5330dc7507de272d8df821be6cd4b0cb569babf5ea4be70e365a2f3d
languageName: node
linkType: hard
@@ -5912,17 +5935,17 @@ __metadata:
languageName: node
linkType: hard
-"available-typed-arrays@npm:^1.0.5":
- version: 1.0.5
- resolution: "available-typed-arrays@npm:1.0.5"
- checksum: 10/4d4d5e86ea0425696f40717882f66a570647b94ac8d273ddc7549a9b61e5da099e149bf431530ccbd776bd74e02039eb8b5edf426e3e2211ee61af16698a9064
+"available-typed-arrays@npm:^1.0.6":
+ version: 1.0.6
+ resolution: "available-typed-arrays@npm:1.0.6"
+ checksum: 10/c1e2e3d3a694f21bf60e0a048d8275fa7358131a0b8e6b57714318d618b59522416db67fb9f56973af0ce596f4333ef1336ca12c37a41d5a72ef79885373a7fd
languageName: node
linkType: hard
"axe-core@npm:^4.3.3":
- version: 4.8.3
- resolution: "axe-core@npm:4.8.3"
- checksum: 10/86d72bcdff867b8a4f223b910f90d1c963ddab1db3bdc5290e111453bae4e319ed14d667cd7a6ac97185ffa141261c88ac9a586aa007d007ffc19ed9ae81ee1d
+ version: 4.8.4
+ resolution: "axe-core@npm:4.8.4"
+ checksum: 10/c8b3972b17afac33b9e151556fa500b9218086ca763866942de30e7f51ac50582902ad03ec16381796c95afaacfa8c33efb2d02ab4f09b6c09d6be58b95da978
languageName: node
linkType: hard
@@ -6120,7 +6143,7 @@ __metadata:
languageName: node
linkType: hard
-"bonjour-service@npm:^1.0.11":
+"bonjour-service@npm:^1.2.1":
version: 1.2.1
resolution: "bonjour-service@npm:1.2.1"
dependencies:
@@ -6190,17 +6213,17 @@ __metadata:
languageName: node
linkType: hard
-"browserslist@npm:^4.21.10, browserslist@npm:^4.22.2":
- version: 4.22.3
- resolution: "browserslist@npm:4.22.3"
+"browserslist@npm:^4.21.10, browserslist@npm:^4.22.2, browserslist@npm:^4.22.3":
+ version: 4.23.0
+ resolution: "browserslist@npm:4.23.0"
dependencies:
- caniuse-lite: "npm:^1.0.30001580"
- electron-to-chromium: "npm:^1.4.648"
+ caniuse-lite: "npm:^1.0.30001587"
+ electron-to-chromium: "npm:^1.4.668"
node-releases: "npm:^2.0.14"
update-browserslist-db: "npm:^1.0.13"
bin:
browserslist: cli.js
- checksum: 10/d46a906c79dfe95d9702c020afbe5b7b4dbe2019b85432e7a020326adff27e63e3c0a52dc8d4e73247060bbe2c13f000714741903cf96a16baae9c216dc74c75
+ checksum: 10/496c3862df74565dd942b4ae65f502c575cbeba1fa4a3894dad7aa3b16130dc3033bc502d8848147f7b625154a284708253d9598bcdbef5a1e34cf11dc7bad8e
languageName: node
linkType: hard
@@ -6319,14 +6342,16 @@ __metadata:
languageName: node
linkType: hard
-"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5":
- version: 1.0.5
- resolution: "call-bind@npm:1.0.5"
+"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7":
+ version: 1.0.7
+ resolution: "call-bind@npm:1.0.7"
dependencies:
+ es-define-property: "npm:^1.0.0"
+ es-errors: "npm:^1.3.0"
function-bind: "npm:^1.1.2"
- get-intrinsic: "npm:^1.2.1"
- set-function-length: "npm:^1.1.1"
- checksum: 10/246d44db6ef9bbd418828dbd5337f80b46be4398d522eded015f31554cbb2ea33025b0203b75c7ab05a1a255b56ef218880cca1743e4121e306729f9e414da39
+ get-intrinsic: "npm:^1.2.4"
+ set-function-length: "npm:^1.2.1"
+ checksum: 10/cd6fe658e007af80985da5185bff7b55e12ef4c2b6f41829a26ed1eef254b1f1c12e3dfd5b2b068c6ba8b86aba62390842d81752e67dcbaec4f6f76e7113b6b7
languageName: node
linkType: hard
@@ -6368,23 +6393,23 @@ __metadata:
languageName: node
linkType: hard
-"caniuse-lite@npm:^1.0.30001580":
- version: 1.0.30001580
- resolution: "caniuse-lite@npm:1.0.30001580"
- checksum: 10/b626d25d792c766383a47c9efe1384f7d3c3b23e0ee70bf121e8b3a628806a96a21def16a44e58b75f4a5e23b5e008f51c2cc1e8be477b8c8d9493dcc170dd0e
+"caniuse-lite@npm:^1.0.30001587":
+ version: 1.0.30001588
+ resolution: "caniuse-lite@npm:1.0.30001588"
+ checksum: 10/09150ef2daa65c75cb2681832d5bc203760a02d9f71eb033dc0401fbfdbe026d3a84e54a8d2085f730a4f51eb074028b89013dd033841e1a0eb3c7323a50ed45
languageName: node
linkType: hard
-"chai@npm:5.0.3":
- version: 5.0.3
- resolution: "chai@npm:5.0.3"
+"chai@npm:5.1.0":
+ version: 5.1.0
+ resolution: "chai@npm:5.1.0"
dependencies:
assertion-error: "npm:^2.0.1"
check-error: "npm:^2.0.0"
deep-eql: "npm:^5.0.1"
loupe: "npm:^3.1.0"
pathval: "npm:^2.0.0"
- checksum: 10/d9b2bb0e4591b4a73ea98bb7a6423c4e50dd35f43ce4404be26126796af970d844269bb0b07b21866620c542f07957003b34c5cf60095e5a84878af6b120cc2d
+ checksum: 10/4d4eee5ec61eeff9e9dfe05ae49ef4b48f1cc8e14e4d4c72476482cea85d824aff0e76d5c4d357026fb276870d705341068eef98d240cd90f008b9bd250e7a69
languageName: node
linkType: hard
@@ -6441,7 +6466,7 @@ __metadata:
languageName: node
linkType: hard
-"chokidar@npm:3.5.3, chokidar@npm:^3.4.3, chokidar@npm:^3.5.3":
+"chokidar@npm:3.5.3":
version: 3.5.3
resolution: "chokidar@npm:3.5.3"
dependencies:
@@ -6483,6 +6508,25 @@ __metadata:
languageName: node
linkType: hard
+"chokidar@npm:^3.4.3, chokidar@npm:^3.6.0":
+ version: 3.6.0
+ resolution: "chokidar@npm:3.6.0"
+ dependencies:
+ anymatch: "npm:~3.1.2"
+ braces: "npm:~3.0.2"
+ fsevents: "npm:~2.3.2"
+ glob-parent: "npm:~5.1.2"
+ is-binary-path: "npm:~2.1.0"
+ is-glob: "npm:~4.0.1"
+ normalize-path: "npm:~3.0.0"
+ readdirp: "npm:~3.6.0"
+ dependenciesMeta:
+ fsevents:
+ optional: true
+ checksum: 10/c327fb07704443f8d15f7b4a7ce93b2f0bc0e6cea07ec28a7570aa22cd51fcf0379df589403976ea956c369f25aa82d84561947e227cd925902e1751371658df
+ languageName: node
+ linkType: hard
+
"chownr@npm:^2.0.0":
version: 2.0.0
resolution: "chownr@npm:2.0.0"
@@ -6707,6 +6751,13 @@ __metadata:
languageName: node
linkType: hard
+"color-name@npm:2.0.0":
+ version: 2.0.0
+ resolution: "color-name@npm:2.0.0"
+ checksum: 10/10a1addae41de2987d6b90dbd3cfade266c2e6f680ce21749911df4493b4fae07654862c6b5358bdd13e155461acb4eedaa5e0ba172bf13542cdcca10866cf2b
+ languageName: node
+ linkType: hard
+
"color-name@npm:~1.1.4":
version: 1.1.4
resolution: "color-name@npm:1.1.4"
@@ -6960,18 +7011,18 @@ __metadata:
linkType: hard
"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.34.0":
- version: 3.35.1
- resolution: "core-js-compat@npm:3.35.1"
+ version: 3.36.0
+ resolution: "core-js-compat@npm:3.36.0"
dependencies:
- browserslist: "npm:^4.22.2"
- checksum: 10/9a153c66591e23703e182b258ec6bdaff0a7c578dc5f9ac152fdfef2d09e8ec277f192e28d4634a8b576c8e1a6d3b1ac76ff6b8776e72b71b334e609e177a05e
+ browserslist: "npm:^4.22.3"
+ checksum: 10/633c49a254fe48981057e33651e5a74a0a14f14731aa5afed5d2e61fbe3c5cbc116ffd4feaa158c683c40d6dc4fd2e6aa0ebe12c45d157cfa571309d08400c98
languageName: node
linkType: hard
-"core-js@npm:3.35.1":
- version: 3.35.1
- resolution: "core-js@npm:3.35.1"
- checksum: 10/5d31f22eb05cf66bd1a2088a04b7106faa5d0b91c1ffa5d72c5203e4974c31bd7e11969297f540a806c00c74c23991eaad5639592df8b5dbe4412fff3c075cd5
+"core-js@npm:3.36.0":
+ version: 3.36.0
+ resolution: "core-js@npm:3.36.0"
+ checksum: 10/896326c6391c1607dc645293c214cd31c6c535d4a77a88b15fc29e787199f9b06dc15986ddfbc798335bf7a7afd1e92152c94aa5a974790a7f97a98121774302
languageName: node
linkType: hard
@@ -7207,14 +7258,14 @@ __metadata:
languageName: node
linkType: hard
-"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1":
- version: 1.1.1
- resolution: "define-data-property@npm:1.1.1"
+"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.2":
+ version: 1.1.4
+ resolution: "define-data-property@npm:1.1.4"
dependencies:
- get-intrinsic: "npm:^1.2.1"
+ es-define-property: "npm:^1.0.0"
+ es-errors: "npm:^1.3.0"
gopd: "npm:^1.0.1"
- has-property-descriptors: "npm:^1.0.0"
- checksum: 10/5573c8df96b5857408cad64d9b91b69152e305ce4b06218e5f49b59c6cafdbb90a8bd8a0bb83c7bc67a8d479c04aa697063c9bc28d849b7282f9327586d6bc7b
+ checksum: 10/abdcb2505d80a53524ba871273e5da75e77e52af9e15b3aa65d8aad82b8a3a424dad7aee2cc0b71470ac7acf501e08defac362e8b6a73cdb4309f028061df4ae
languageName: node
linkType: hard
@@ -7362,9 +7413,9 @@ __metadata:
linkType: hard
"diff@npm:^5.1.0":
- version: 5.1.0
- resolution: "diff@npm:5.1.0"
- checksum: 10/f4557032a98b2967fe27b1a91dfcf8ebb6b9a24b1afe616b5c2312465100b861e9b8d4da374be535f2d6b967ce2f53826d7f6edc2a0d32b2ab55abc96acc2f9d
+ version: 5.2.0
+ resolution: "diff@npm:5.2.0"
+ checksum: 10/01b7b440f83a997350a988e9d2f558366c0f90f15be19f4aa7f1bb3109a4e153dfc3b9fbf78e14ea725717017407eeaa2271e3896374a0181e8f52445740846d
languageName: node
linkType: hard
@@ -7486,10 +7537,10 @@ __metadata:
languageName: node
linkType: hard
-"electron-to-chromium@npm:^1.4.648":
- version: 1.4.648
- resolution: "electron-to-chromium@npm:1.4.648"
- checksum: 10/a18f06bafce9017ac7b587f76dac77063a0beb7dfcdf9d5971f72b322f56af6315e4fc3c59154a260a9188c168ac7632538797d57a8c53ab57025ace0c9441f2
+"electron-to-chromium@npm:^1.4.668":
+ version: 1.4.673
+ resolution: "electron-to-chromium@npm:1.4.673"
+ checksum: 10/e9e82bec564f4398040a3ce5a8e344dfebac624e458545c7d9317bb54d65f7000648e552acebc1951cda4562e5d9cebcb7d9e76a376c8ad1e04f7860230935fa
languageName: node
linkType: hard
@@ -7589,11 +7640,11 @@ __metadata:
linkType: hard
"envinfo@npm:^7.7.3":
- version: 7.11.0
- resolution: "envinfo@npm:7.11.0"
+ version: 7.11.1
+ resolution: "envinfo@npm:7.11.1"
bin:
envinfo: dist/cli.js
- checksum: 10/8cba09db181329b243fe02b3384ec275ebf93d5d3663c31e2064697aa96576c7de9b7e1c878a250f8eaec0db8026bace747709dcdc8d8a4ecd9a653cdbc08926
+ checksum: 10/5a18ead05954ac1643350170fefce2436a9cb758dc402e36fe4616553ee46469f766fcb6df72379d1741a2e5b55918949b343ff6174502c31c524a5cf75f05cd
languageName: node
linkType: hard
@@ -7622,50 +7673,75 @@ __metadata:
languageName: node
linkType: hard
-"es-abstract@npm:^1.22.1":
- version: 1.22.3
- resolution: "es-abstract@npm:1.22.3"
+"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3":
+ version: 1.22.4
+ resolution: "es-abstract@npm:1.22.4"
dependencies:
- array-buffer-byte-length: "npm:^1.0.0"
- arraybuffer.prototype.slice: "npm:^1.0.2"
- available-typed-arrays: "npm:^1.0.5"
- call-bind: "npm:^1.0.5"
- es-set-tostringtag: "npm:^2.0.1"
+ array-buffer-byte-length: "npm:^1.0.1"
+ arraybuffer.prototype.slice: "npm:^1.0.3"
+ available-typed-arrays: "npm:^1.0.6"
+ call-bind: "npm:^1.0.7"
+ es-define-property: "npm:^1.0.0"
+ es-errors: "npm:^1.3.0"
+ es-set-tostringtag: "npm:^2.0.2"
es-to-primitive: "npm:^1.2.1"
function.prototype.name: "npm:^1.1.6"
- get-intrinsic: "npm:^1.2.2"
- get-symbol-description: "npm:^1.0.0"
+ get-intrinsic: "npm:^1.2.4"
+ get-symbol-description: "npm:^1.0.2"
globalthis: "npm:^1.0.3"
gopd: "npm:^1.0.1"
- has-property-descriptors: "npm:^1.0.0"
+ has-property-descriptors: "npm:^1.0.2"
has-proto: "npm:^1.0.1"
has-symbols: "npm:^1.0.3"
- hasown: "npm:^2.0.0"
- internal-slot: "npm:^1.0.5"
- is-array-buffer: "npm:^3.0.2"
+ hasown: "npm:^2.0.1"
+ internal-slot: "npm:^1.0.7"
+ is-array-buffer: "npm:^3.0.4"
is-callable: "npm:^1.2.7"
is-negative-zero: "npm:^2.0.2"
is-regex: "npm:^1.1.4"
is-shared-array-buffer: "npm:^1.0.2"
is-string: "npm:^1.0.7"
- is-typed-array: "npm:^1.1.12"
+ is-typed-array: "npm:^1.1.13"
is-weakref: "npm:^1.0.2"
object-inspect: "npm:^1.13.1"
object-keys: "npm:^1.1.1"
- object.assign: "npm:^4.1.4"
- regexp.prototype.flags: "npm:^1.5.1"
- safe-array-concat: "npm:^1.0.1"
- safe-regex-test: "npm:^1.0.0"
+ object.assign: "npm:^4.1.5"
+ regexp.prototype.flags: "npm:^1.5.2"
+ safe-array-concat: "npm:^1.1.0"
+ safe-regex-test: "npm:^1.0.3"
string.prototype.trim: "npm:^1.2.8"
string.prototype.trimend: "npm:^1.0.7"
string.prototype.trimstart: "npm:^1.0.7"
- typed-array-buffer: "npm:^1.0.0"
+ typed-array-buffer: "npm:^1.0.1"
typed-array-byte-length: "npm:^1.0.0"
typed-array-byte-offset: "npm:^1.0.0"
typed-array-length: "npm:^1.0.4"
unbox-primitive: "npm:^1.0.2"
- which-typed-array: "npm:^1.1.13"
- checksum: 10/e1ea9738ece15f810733b7bd71d825b555e01bb8c860272560d7d901467a9db1265214d6cf44f3beeb5d73ae421a609b9ad93a39aa47bbcd8cde510d5e0aa875
+ which-typed-array: "npm:^1.1.14"
+ checksum: 10/062e562a000e280c0c0683ad4a7b81732f97463bc769110c668a8edb739cd5df56975fa55965f5304a3256fd6eee03b9b66a47d863076f8976c2050731946b1f
+ languageName: node
+ linkType: hard
+
+"es-array-method-boxes-properly@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "es-array-method-boxes-properly@npm:1.0.0"
+ checksum: 10/27a8a21acf20f3f51f69dce8e643f151e380bffe569e95dc933b9ded9fcd89a765ee21b5229c93f9206c93f87395c6b75f80be8ac8c08a7ceb8771e1822ff1fb
+ languageName: node
+ linkType: hard
+
+"es-define-property@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "es-define-property@npm:1.0.0"
+ dependencies:
+ get-intrinsic: "npm:^1.2.4"
+ checksum: 10/f66ece0a887b6dca71848fa71f70461357c0e4e7249696f81bad0a1f347eed7b31262af4a29f5d726dc026426f085483b6b90301855e647aa8e21936f07293c6
+ languageName: node
+ linkType: hard
+
+"es-errors@npm:^1.0.0, es-errors@npm:^1.2.1, es-errors@npm:^1.3.0":
+ version: 1.3.0
+ resolution: "es-errors@npm:1.3.0"
+ checksum: 10/96e65d640156f91b707517e8cdc454dd7d47c32833aa3e85d79f24f9eb7ea85f39b63e36216ef0114996581969b59fe609a94e30316b08f5f4df1d44134cf8d5
languageName: node
linkType: hard
@@ -7676,7 +7752,7 @@ __metadata:
languageName: node
linkType: hard
-"es-set-tostringtag@npm:^2.0.1":
+"es-set-tostringtag@npm:^2.0.2":
version: 2.0.2
resolution: "es-set-tostringtag@npm:2.0.2"
dependencies:
@@ -7687,7 +7763,7 @@ __metadata:
languageName: node
linkType: hard
-"es-shim-unscopables@npm:^1.0.0":
+"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2":
version: 1.0.2
resolution: "es-shim-unscopables@npm:1.0.2"
dependencies:
@@ -7707,14 +7783,15 @@ __metadata:
languageName: node
linkType: hard
-"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.46, es5-ext@npm:^0.10.50":
- version: 0.10.62
- resolution: "es5-ext@npm:0.10.62"
+"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.46, es5-ext@npm:^0.10.50, es5-ext@npm:^0.10.62, es5-ext@npm:~0.10.14":
+ version: 0.10.63
+ resolution: "es5-ext@npm:0.10.63"
dependencies:
es6-iterator: "npm:^2.0.3"
es6-symbol: "npm:^3.1.3"
+ esniff: "npm:^2.0.1"
next-tick: "npm:^1.1.0"
- checksum: 10/3f6a3bcdb7ff82aaf65265799729828023c687a2645da04005b8f1dc6676a0c41fd06571b2517f89dcf143e0268d3d9ef0fdfd536ab74580083204c688d6fb45
+ checksum: 10/69e373ffcf4664f12697adfab4a043a5cd93386c5e9d9b3eda4bd59f3591c7bebba3647475a3c9ccb1b48ec941b93c9507bf54727f0311a65e7220bc895eade9
languageName: node
linkType: hard
@@ -7752,9 +7829,9 @@ __metadata:
linkType: hard
"escalade@npm:^3.1.1":
- version: 3.1.1
- resolution: "escalade@npm:3.1.1"
- checksum: 10/afa618e73362576b63f6ca83c975456621095a1ed42ff068174e3f5cea48afc422814dda548c96e6ebb5333e7265140c7292abcc81bbd6ccb1757d50d3a4e182
+ version: 3.1.2
+ resolution: "escalade@npm:3.1.2"
+ checksum: 10/a1e07fea2f15663c30e40b9193d658397846ffe28ce0a3e4da0d8e485fedfeca228ab846aee101a05015829adf39f9934ff45b2a3fca47bed37a29646bd05cd3
languageName: node
linkType: hard
@@ -7943,18 +8020,18 @@ __metadata:
languageName: node
linkType: hard
-"eslint-plugin-unused-imports@npm:3.0.0":
- version: 3.0.0
- resolution: "eslint-plugin-unused-imports@npm:3.0.0"
+"eslint-plugin-unused-imports@npm:3.1.0":
+ version: 3.1.0
+ resolution: "eslint-plugin-unused-imports@npm:3.1.0"
dependencies:
eslint-rule-composer: "npm:^0.3.0"
peerDependencies:
- "@typescript-eslint/eslint-plugin": ^6.0.0
- eslint: ^8.0.0
+ "@typescript-eslint/eslint-plugin": 6 - 7
+ eslint: 8
peerDependenciesMeta:
"@typescript-eslint/eslint-plugin":
optional: true
- checksum: 10/9433b80d4efdf3f8e43a38a7662b279b310020f3a80ffd2bbc56a375804b367bedfbe5b611b1969963e2de3b392bf1f389e89d2af810594ea3ab913c7e219ba1
+ checksum: 10/8ad49d6d343492f5a5e6398a57d2c66c28651410d83478b16eac8fadb466cf7785b43cd7cfe33e0fb9624c464c7a92b5b78b34ad2daf418e8ac8fed5c554e1ed
languageName: node
linkType: hard
@@ -8011,15 +8088,15 @@ __metadata:
languageName: node
linkType: hard
-"eslint@npm:8.56.0":
- version: 8.56.0
- resolution: "eslint@npm:8.56.0"
+"eslint@npm:8.57.0":
+ version: 8.57.0
+ resolution: "eslint@npm:8.57.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.2.0"
"@eslint-community/regexpp": "npm:^4.6.1"
"@eslint/eslintrc": "npm:^2.1.4"
- "@eslint/js": "npm:8.56.0"
- "@humanwhocodes/config-array": "npm:^0.11.13"
+ "@eslint/js": "npm:8.57.0"
+ "@humanwhocodes/config-array": "npm:^0.11.14"
"@humanwhocodes/module-importer": "npm:^1.0.1"
"@nodelib/fs.walk": "npm:^1.2.8"
"@ungap/structured-clone": "npm:^1.2.0"
@@ -8055,7 +8132,19 @@ __metadata:
text-table: "npm:^0.2.0"
bin:
eslint: bin/eslint.js
- checksum: 10/ef6193c6e4cef20774b985a5cc2fd4bf6d3c4decd423117cbc4a0196617861745db291217ad3c537bc3a160650cca965bc818f55e1f3e446af1fcb293f9940a5
+ checksum: 10/00496e218b23747a7a9817bf58b522276d0dc1f2e546dceb4eea49f9871574088f72f1f069a6b560ef537efa3a75261b8ef70e51ef19033da1cc4c86a755ef15
+ languageName: node
+ linkType: hard
+
+"esniff@npm:^2.0.1":
+ version: 2.0.1
+ resolution: "esniff@npm:2.0.1"
+ dependencies:
+ d: "npm:^1.0.1"
+ es5-ext: "npm:^0.10.62"
+ event-emitter: "npm:^0.3.5"
+ type: "npm:^2.7.2"
+ checksum: 10/f6a2abd2f8c5fe57c5fcf53e5407c278023313d0f6c3a92688e7122ab9ac233029fd424508a196ae5bc561aa1f67d23f4e2435b1a0d378030f476596129056ac
languageName: node
linkType: hard
@@ -8137,6 +8226,16 @@ __metadata:
languageName: node
linkType: hard
+"event-emitter@npm:^0.3.5":
+ version: 0.3.5
+ resolution: "event-emitter@npm:0.3.5"
+ dependencies:
+ d: "npm:1"
+ es5-ext: "npm:~0.10.14"
+ checksum: 10/a7f5ea80029193f4869782d34ef7eb43baa49cd397013add1953491b24588468efbe7e3cc9eb87d53f33397e7aab690fd74c079ec440bf8b12856f6bdb6e9396
+ languageName: node
+ linkType: hard
+
"eventemitter3@npm:^4.0.0":
version: 4.0.7
resolution: "eventemitter3@npm:4.0.7"
@@ -8408,11 +8507,11 @@ __metadata:
linkType: hard
"fastq@npm:^1.6.0":
- version: 1.16.0
- resolution: "fastq@npm:1.16.0"
+ version: 1.17.1
+ resolution: "fastq@npm:1.17.1"
dependencies:
reusify: "npm:^1.0.4"
- checksum: 10/de151543aab9d91900ed5da88860c46987ece925c628df586fac664235f25e020ec20729e1c032edb5fd2520fd4aa5b537d69e39b689e65e82112cfbecb4479e
+ checksum: 10/a443180068b527dd7b3a63dc7f2a47ceca2f3e97b9c00a1efe5538757e6cc4056a3526df94308075d7727561baf09ebaa5b67da8dcbddb913a021c5ae69d1f69
languageName: node
linkType: hard
@@ -8901,15 +9000,16 @@ __metadata:
languageName: node
linkType: hard
-"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2":
- version: 1.2.2
- resolution: "get-intrinsic@npm:1.2.2"
+"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4":
+ version: 1.2.4
+ resolution: "get-intrinsic@npm:1.2.4"
dependencies:
+ es-errors: "npm:^1.3.0"
function-bind: "npm:^1.1.2"
has-proto: "npm:^1.0.1"
has-symbols: "npm:^1.0.3"
hasown: "npm:^2.0.0"
- checksum: 10/aa96db4f809734d26d49b59bc8669d73a0ae792da561514e987735573a1dfaede516cd102f217a078ea2b42d4c4fb1f83d487932cb15d49826b726cc9cd4470b
+ checksum: 10/85bbf4b234c3940edf8a41f4ecbd4e25ce78e5e6ad4e24ca2f77037d983b9ef943fd72f00f3ee97a49ec622a506b67db49c36246150377efcda1c9eb03e5f06d
languageName: node
linkType: hard
@@ -8934,13 +9034,14 @@ __metadata:
languageName: node
linkType: hard
-"get-symbol-description@npm:^1.0.0":
- version: 1.0.0
- resolution: "get-symbol-description@npm:1.0.0"
+"get-symbol-description@npm:^1.0.2":
+ version: 1.0.2
+ resolution: "get-symbol-description@npm:1.0.2"
dependencies:
- call-bind: "npm:^1.0.2"
- get-intrinsic: "npm:^1.1.1"
- checksum: 10/7e5f298afe0f0872747dce4a949ce490ebc5d6dd6aefbbe5044543711c9b19a4dfaebdbc627aee99e1299d58a435b2fbfa083458c1d58be6dc03a3bada24d359
+ call-bind: "npm:^1.0.5"
+ es-errors: "npm:^1.3.0"
+ get-intrinsic: "npm:^1.2.4"
+ checksum: 10/e1cb53bc211f9dbe9691a4f97a46837a553c4e7caadd0488dc24ac694db8a390b93edd412b48dcdd0b4bbb4c595de1709effc75fc87c0839deedc6968f5bd973
languageName: node
linkType: hard
@@ -9029,7 +9130,7 @@ __metadata:
languageName: node
linkType: hard
-"glob@npm:10.3.10, glob@npm:^10.2.2, glob@npm:^10.3.10":
+"glob@npm:10.3.10, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7":
version: 10.3.10
resolution: "glob@npm:10.3.10"
dependencies:
@@ -9044,17 +9145,16 @@ __metadata:
languageName: node
linkType: hard
-"glob@npm:7.2.0":
- version: 7.2.0
- resolution: "glob@npm:7.2.0"
+"glob@npm:8.1.0, glob@npm:^8.0.3":
+ version: 8.1.0
+ resolution: "glob@npm:8.1.0"
dependencies:
fs.realpath: "npm:^1.0.0"
inflight: "npm:^1.0.4"
inherits: "npm:2"
- minimatch: "npm:^3.0.4"
+ minimatch: "npm:^5.0.1"
once: "npm:^1.3.0"
- path-is-absolute: "npm:^1.0.0"
- checksum: 10/bc78b6ea0735b6e23d20678aba4ae6a4760e8c9527e3c4683ac25b14e70f55f9531245dcf25959b70cbc4aa3dcce1fc37ab65fd026a4cbd70aa3a44880bd396b
+ checksum: 10/9aab1c75eb087c35dbc41d1f742e51d0507aa2b14c910d96fb8287107a10a22f4bbdce26fc0a3da4c69a20f7b26d62f1640b346a4f6e6becfff47f335bb1dc5e
languageName: node
linkType: hard
@@ -9072,19 +9172,6 @@ __metadata:
languageName: node
linkType: hard
-"glob@npm:^8.0.3":
- version: 8.1.0
- resolution: "glob@npm:8.1.0"
- dependencies:
- fs.realpath: "npm:^1.0.0"
- inflight: "npm:^1.0.4"
- inherits: "npm:2"
- minimatch: "npm:^5.0.1"
- once: "npm:^1.3.0"
- checksum: 10/9aab1c75eb087c35dbc41d1f742e51d0507aa2b14c910d96fb8287107a10a22f4bbdce26fc0a3da4c69a20f7b26d62f1640b346a4f6e6becfff47f335bb1dc5e
- languageName: node
- linkType: hard
-
"global-modules@npm:^1.0.0":
version: 1.0.0
resolution: "global-modules@npm:1.0.0"
@@ -9248,17 +9335,16 @@ __metadata:
languageName: node
linkType: hard
-"gulp-json-transform@npm:0.4.8":
- version: 0.4.8
- resolution: "gulp-json-transform@npm:0.4.8"
+"gulp-json-transform@npm:0.5.0":
+ version: 0.5.0
+ resolution: "gulp-json-transform@npm:0.5.0"
dependencies:
ansi-colors: "npm:^1.0.1"
fancy-log: "npm:^1.3.2"
plugin-error: "npm:^1.0.1"
- promise: "npm:^8.0.1"
through2: "npm:^2.0.3"
vinyl: "npm:^2.1.0"
- checksum: 10/5b117e59cd806e530cb4f67089e28eb1a6234bfb1461497e540be2a24cd94c5a8ce573d5ff9222c1481d951316054742a2212c044df0e047256ce10ce7bcd328
+ checksum: 10/0879149337450e4ada1363fa72c351d2386b249df31aa8313c699c267cae3ece14ff1ab77dc7bb6a67827902db68ee0e0232d67ebfca55900dc17f3cfe219c42
languageName: node
linkType: hard
@@ -9348,12 +9434,12 @@ __metadata:
languageName: node
linkType: hard
-"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1":
- version: 1.0.1
- resolution: "has-property-descriptors@npm:1.0.1"
+"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1, has-property-descriptors@npm:^1.0.2":
+ version: 1.0.2
+ resolution: "has-property-descriptors@npm:1.0.2"
dependencies:
- get-intrinsic: "npm:^1.2.2"
- checksum: 10/21a47bb080a24e79594aef1ce71e1a18a1c5ab4120308e218088f67ebb7f6f408847541e2d96e5bd00e90eef5c5a49e4ebbdc8fc2d5b365a2c379aef071642f0
+ es-define-property: "npm:^1.0.0"
+ checksum: 10/2d8c9ab8cebb572e3362f7d06139a4592105983d4317e68f7adba320fe6ddfc8874581e0971e899e633fd5f72e262830edce36d5a0bc863dad17ad20572484b2
languageName: node
linkType: hard
@@ -9371,12 +9457,12 @@ __metadata:
languageName: node
linkType: hard
-"has-tostringtag@npm:^1.0.0":
- version: 1.0.0
- resolution: "has-tostringtag@npm:1.0.0"
+"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.1":
+ version: 1.0.2
+ resolution: "has-tostringtag@npm:1.0.2"
dependencies:
- has-symbols: "npm:^1.0.2"
- checksum: 10/95546e7132efc895a9ae64a8a7cf52588601fc3d52e0304ed228f336992cdf0baaba6f3519d2655e560467db35a1ed79f6420c286cc91a13aa0647a31ed92570
+ has-symbols: "npm:^1.0.3"
+ checksum: 10/c74c5f5ceee3c8a5b8bc37719840dc3749f5b0306d818974141dda2471a1a2ca6c8e46b9d6ac222c5345df7a901c9b6f350b1e6d62763fec877e26609a401bfe
languageName: node
linkType: hard
@@ -9419,12 +9505,12 @@ __metadata:
languageName: node
linkType: hard
-"hasown@npm:^2.0.0":
- version: 2.0.0
- resolution: "hasown@npm:2.0.0"
+"hasown@npm:^2.0.0, hasown@npm:^2.0.1":
+ version: 2.0.1
+ resolution: "hasown@npm:2.0.1"
dependencies:
function-bind: "npm:^1.1.2"
- checksum: 10/c330f8d93f9d23fe632c719d4db3d698ef7d7c367d51548b836069e06a90fa9151e868c8e67353cfe98d67865bf7354855db28fa36eb1b18fa5d4a3f4e7f1c90
+ checksum: 10/b7f9107387ee68abed88e965c2b99e868b5e0e9d289db1ddd080706ffafb69533b4f538b0e6362585bae8d6cbd080249f65e79702f74c225990f66d6106be3f6
languageName: node
linkType: hard
@@ -9437,10 +9523,10 @@ __metadata:
languageName: node
linkType: hard
-"hls.js@npm:1.5.3":
- version: 1.5.3
- resolution: "hls.js@npm:1.5.3"
- checksum: 10/c5b7cb6fddd6ad425a82e1b8b4f818552e6e242254b35c7d7c7b9d3beb4dd40cc85d8bbc32a5d1b57031305d7d9f4973f9d0f80b70351bb8597393f4629072fc
+"hls.js@npm:1.5.6":
+ version: 1.5.6
+ resolution: "hls.js@npm:1.5.6"
+ checksum: 10/795c1d41b5ee682a48c21a78fa995ab8aa2b5badf84593eb12965b0fc58050ca5330df36a115946b8757dff558ba172f9210bb2896b12241416e069269e15d95
languageName: node
linkType: hard
@@ -9456,14 +9542,14 @@ __metadata:
"@babel/preset-typescript": "npm:7.23.3"
"@babel/runtime": "npm:7.23.9"
"@braintree/sanitize-url": "npm:7.0.0"
- "@bundle-stats/plugin-webpack-filter": "npm:4.9.2"
+ "@bundle-stats/plugin-webpack-filter": "npm:4.10.1"
"@codemirror/autocomplete": "npm:6.12.0"
"@codemirror/commands": "npm:6.3.3"
"@codemirror/language": "npm:6.10.1"
"@codemirror/legacy-modes": "npm:6.3.3"
- "@codemirror/search": "npm:6.5.5"
- "@codemirror/state": "npm:6.4.0"
- "@codemirror/view": "npm:6.23.1"
+ "@codemirror/search": "npm:6.5.6"
+ "@codemirror/state": "npm:6.4.1"
+ "@codemirror/view": "npm:6.24.1"
"@egjs/hammerjs": "npm:2.0.17"
"@formatjs/intl-datetimeformat": "npm:6.12.2"
"@formatjs/intl-displaynames": "npm:6.6.6"
@@ -9473,12 +9559,12 @@ __metadata:
"@formatjs/intl-numberformat": "npm:8.10.0"
"@formatjs/intl-pluralrules": "npm:5.2.12"
"@formatjs/intl-relativetimeformat": "npm:11.2.12"
- "@fullcalendar/core": "npm:6.1.10"
- "@fullcalendar/daygrid": "npm:6.1.10"
- "@fullcalendar/interaction": "npm:6.1.10"
- "@fullcalendar/list": "npm:6.1.10"
- "@fullcalendar/luxon3": "npm:6.1.10"
- "@fullcalendar/timegrid": "npm:6.1.10"
+ "@fullcalendar/core": "npm:6.1.11"
+ "@fullcalendar/daygrid": "npm:6.1.11"
+ "@fullcalendar/interaction": "npm:6.1.11"
+ "@fullcalendar/list": "npm:6.1.11"
+ "@fullcalendar/luxon3": "npm:6.1.11"
+ "@fullcalendar/timegrid": "npm:6.1.11"
"@koa/cors": "npm:5.0.0"
"@lezer/highlight": "npm:1.2.0"
"@lit-labs/context": "npm:0.4.1"
@@ -9486,7 +9572,7 @@ __metadata:
"@lit-labs/observers": "npm:2.0.2"
"@lit-labs/virtualizer": "npm:2.0.12"
"@lokalise/node-api": "npm:12.1.0"
- "@lrnwebcomponents/simple-tooltip": "npm:8.0.0"
+ "@lrnwebcomponents/simple-tooltip": "patch:@lrnwebcomponents/simple-tooltip@npm%3A8.0.0#~/.yarn/patches/@lrnwebcomponents-simple-tooltip-npm-8.0.0-77591f2e0c.patch"
"@material/chips": "npm:=14.0.0-canary.53b3cad2f.0"
"@material/data-table": "npm:=14.0.0-canary.53b3cad2f.0"
"@material/mwc-base": "npm:0.27.0"
@@ -9512,7 +9598,7 @@ __metadata:
"@material/mwc-top-app-bar": "npm:0.27.0"
"@material/mwc-top-app-bar-fixed": "npm:0.27.0"
"@material/top-app-bar": "npm:=14.0.0-canary.53b3cad2f.0"
- "@material/web": "npm:=1.2.0"
+ "@material/web": "npm:=1.3.0"
"@mdi/js": "npm:7.4.47"
"@mdi/svg": "npm:7.4.47"
"@octokit/auth-oauth-device": "npm:6.0.1"
@@ -9533,6 +9619,7 @@ __metadata:
"@types/babel__plugin-transform-runtime": "npm:7.9.5"
"@types/chromecast-caf-receiver": "npm:6.0.13"
"@types/chromecast-caf-sender": "npm:1.0.8"
+ "@types/color-name": "npm:1.1.3"
"@types/glob": "npm:8.1.0"
"@types/html-minifier-terser": "npm:7.0.2"
"@types/js-yaml": "npm:4.0.9"
@@ -9542,14 +9629,14 @@ __metadata:
"@types/mocha": "npm:10.0.6"
"@types/qrcode": "npm:1.5.5"
"@types/serve-handler": "npm:6.1.4"
- "@types/sortablejs": "npm:1.15.7"
+ "@types/sortablejs": "npm:1.15.8"
"@types/tar": "npm:6.1.11"
"@types/ua-parser-js": "npm:0.7.39"
"@types/webspeechapi": "npm:0.0.29"
- "@typescript-eslint/eslint-plugin": "npm:6.20.0"
- "@typescript-eslint/parser": "npm:6.20.0"
- "@vaadin/combo-box": "npm:24.3.5"
- "@vaadin/vaadin-themable-mixin": "npm:24.3.5"
+ "@typescript-eslint/eslint-plugin": "npm:7.0.2"
+ "@typescript-eslint/parser": "npm:7.0.2"
+ "@vaadin/combo-box": "npm:24.3.6"
+ "@vaadin/vaadin-themable-mixin": "npm:24.3.6"
"@vibrant/color": "npm:3.2.1-alpha.1"
"@vibrant/core": "npm:3.2.1-alpha.1"
"@vibrant/quantizer-mmcq": "npm:3.2.1-alpha.1"
@@ -9561,10 +9648,11 @@ __metadata:
app-datepicker: "npm:5.1.1"
babel-loader: "npm:9.1.3"
babel-plugin-template-html-minifier: "npm:4.1.0"
- chai: "npm:5.0.3"
+ chai: "npm:5.1.0"
chart.js: "npm:4.4.1"
+ color-name: "npm:2.0.0"
comlink: "npm:4.4.1"
- core-js: "npm:3.35.1"
+ core-js: "npm:3.36.0"
cropperjs: "npm:1.6.1"
date-fns: "npm:2.30.0"
date-fns-tz: "npm:2.0.0"
@@ -9572,7 +9660,7 @@ __metadata:
deep-freeze: "npm:0.0.1"
del: "npm:7.1.0"
element-internals-polyfill: "npm:1.3.10"
- eslint: "npm:8.56.0"
+ eslint: "npm:8.57.0"
eslint-config-airbnb-base: "npm:15.0.0"
eslint-config-airbnb-typescript: "npm:17.1.0"
eslint-config-prettier: "npm:9.1.0"
@@ -9581,7 +9669,7 @@ __metadata:
eslint-plugin-import: "npm:2.29.1"
eslint-plugin-lit: "npm:1.11.0"
eslint-plugin-lit-a11y: "npm:4.1.2"
- eslint-plugin-unused-imports: "npm:3.0.0"
+ eslint-plugin-unused-imports: "npm:3.1.0"
eslint-plugin-wc: "npm:2.0.4"
fancy-log: "npm:2.0.0"
fs-extra: "npm:11.2.0"
@@ -9590,14 +9678,14 @@ __metadata:
google-timezones-json: "npm:1.2.0"
gulp: "npm:4.0.2"
gulp-flatmap: "npm:1.0.2"
- gulp-json-transform: "npm:0.4.8"
+ gulp-json-transform: "npm:0.5.0"
gulp-merge-json: "npm:2.1.2"
gulp-rename: "npm:2.0.0"
gulp-zopfli-green: "npm:6.0.1"
- hls.js: "npm:1.5.3"
+ hls.js: "npm:1.5.6"
home-assistant-js-websocket: "npm:9.1.0"
html-minifier-terser: "npm:7.2.0"
- husky: "npm:9.0.10"
+ husky: "npm:9.0.11"
idb-keyval: "npm:6.2.1"
instant-mocha: "npm:1.5.2"
intl-messageformat: "npm:10.5.11"
@@ -9605,21 +9693,21 @@ __metadata:
jszip: "npm:3.10.1"
leaflet: "npm:1.9.4"
leaflet-draw: "npm:1.0.4"
- lint-staged: "npm:15.2.1"
+ lint-staged: "npm:15.2.2"
lit: "npm:2.8.0"
lit-analyzer: "npm:2.0.3"
lodash.template: "npm:4.5.0"
luxon: "npm:3.4.4"
- magic-string: "npm:0.30.6"
+ magic-string: "npm:0.30.7"
map-stream: "npm:0.0.7"
- marked: "npm:11.2.0"
+ marked: "npm:12.0.0"
memoize-one: "npm:6.0.0"
- mocha: "npm:10.2.0"
+ mocha: "npm:10.3.0"
node-vibrant: "npm:3.2.1-alpha.1"
object-hash: "npm:3.0.0"
open: "npm:10.0.3"
pinst: "npm:3.0.0"
- prettier: "npm:3.2.4"
+ prettier: "npm:3.2.5"
proxy-polyfill: "npm:0.3.2"
punycode: "npm:2.3.1"
qr-scanner: "npm:1.4.2"
@@ -9653,12 +9741,12 @@ __metadata:
vis-network: "npm:9.1.9"
vue: "npm:2.7.16"
vue2-daterange-picker: "npm:0.6.8"
- webpack: "npm:5.90.1"
+ webpack: "npm:5.90.3"
webpack-cli: "npm:5.1.4"
- webpack-dev-server: "npm:4.15.1"
+ webpack-dev-server: "npm:5.0.2"
webpack-manifest-plugin: "npm:5.0.0"
webpack-stats-plugin: "npm:1.1.3"
- webpackbar: "npm:6.0.0"
+ webpackbar: "npm:6.0.1"
weekstart: "npm:2.0.0"
workbox-build: "npm:7.0.0"
workbox-cacheable-response: "npm:7.0.0"
@@ -9706,7 +9794,7 @@ __metadata:
languageName: node
linkType: hard
-"html-entities@npm:^2.3.2":
+"html-entities@npm:^2.4.0":
version: 2.4.0
resolution: "html-entities@npm:2.4.0"
checksum: 10/646f2f19214bad751e060ceef4df98520654a1d0cd631b55d45504df2f0aaf8a14d8c0a5a4f92b353be298774d856157ac2d04a031d78889c9011892078ca157
@@ -9817,12 +9905,12 @@ __metadata:
linkType: hard
"http-proxy-agent@npm:^7.0.0":
- version: 7.0.0
- resolution: "http-proxy-agent@npm:7.0.0"
+ version: 7.0.2
+ resolution: "http-proxy-agent@npm:7.0.2"
dependencies:
agent-base: "npm:^7.1.0"
debug: "npm:^4.3.4"
- checksum: 10/dbaaf3d9f3fc4df4a5d7ec45d456ec50f575240b557160fa63427b447d1f812dd7fe4a4f17d2e1ba003d231f07edf5a856ea6d91cb32d533062ff20a7803ccac
+ checksum: 10/d062acfa0cb82beeb558f1043c6ba770ea892b5fb7b28654dbc70ea2aeea55226dd34c02a294f6c1ca179a5aa483c4ea641846821b182edbd9cc5d89b54c6848
languageName: node
linkType: hard
@@ -9856,12 +9944,12 @@ __metadata:
linkType: hard
"https-proxy-agent@npm:^7.0.1":
- version: 7.0.2
- resolution: "https-proxy-agent@npm:7.0.2"
+ version: 7.0.4
+ resolution: "https-proxy-agent@npm:7.0.4"
dependencies:
agent-base: "npm:^7.0.2"
debug: "npm:4"
- checksum: 10/9ec844f78fd643608239c9c3f6819918631df5cd3e17d104cc507226a39b5d4adda9d790fc9fd63ac0d2bb8a761b2f9f60faa80584a9bf9d7f2e8c5ed0acd330
+ checksum: 10/405fe582bba461bfe5c7e2f8d752b384036854488b828ae6df6a587c654299cbb2c50df38c4b6ab303502c3c5e029a793fbaac965d1e86ee0be03faceb554d63
languageName: node
linkType: hard
@@ -9879,12 +9967,12 @@ __metadata:
languageName: node
linkType: hard
-"husky@npm:9.0.10":
- version: 9.0.10
- resolution: "husky@npm:9.0.10"
+"husky@npm:9.0.11":
+ version: 9.0.11
+ resolution: "husky@npm:9.0.11"
bin:
husky: bin.mjs
- checksum: 10/c303f1862e2b63873605df55a2b08303155e35c799585d7dd677628f62d716e7304bd984fc7d00ec44e740caac07d51720d1a0abb0a23a70a38859d89eb8e72d
+ checksum: 10/8a9b7cb9dc8494b470b3b47b386e65d579608c6206da80d3cc8b71d10e37947264af3dfe00092368dad9673b51d2a5ee87afb4b2291e77ba9e7ec1ac36e56cd1
languageName: node
linkType: hard
@@ -9928,9 +10016,9 @@ __metadata:
linkType: hard
"ignore@npm:^5.2.0, ignore@npm:^5.2.4":
- version: 5.3.0
- resolution: "ignore@npm:5.3.0"
- checksum: 10/51594355cea4c6ad6b28b3b85eb81afa7b988a1871feefd7062baf136c95aa06760ee934fa9590e43d967bd377ce84a4cf6135fbeb6063e063f1182a0e9a3bcd
+ version: 5.3.1
+ resolution: "ignore@npm:5.3.1"
+ checksum: 10/0a884c2fbc8c316f0b9f92beaf84464253b73230a4d4d286697be45fca081199191ca33e1c2e82d9e5f851f5e9a48a78e25a35c951e7eb41e59f150db3530065
languageName: node
linkType: hard
@@ -10041,14 +10129,14 @@ __metadata:
languageName: node
linkType: hard
-"internal-slot@npm:^1.0.5":
- version: 1.0.6
- resolution: "internal-slot@npm:1.0.6"
+"internal-slot@npm:^1.0.5, internal-slot@npm:^1.0.7":
+ version: 1.0.7
+ resolution: "internal-slot@npm:1.0.7"
dependencies:
- get-intrinsic: "npm:^1.2.2"
+ es-errors: "npm:^1.3.0"
hasown: "npm:^2.0.0"
side-channel: "npm:^1.0.4"
- checksum: 10/bc2022eb1f277f2fcb2a60e7ced451c7ffc7a769b12e63c7a3fb247af8b5a1bed06428ce724046a8bca39ed6eb5b6832501a42f2e9a5ec4a9a7dc4e634431616
+ checksum: 10/3e66720508831153ecf37d13def9f6856f9f2960989ec8a0a0476c98f887fca9eff0163127466485cb825c900c2d6fc601aa9117b7783b90ffce23a71ea5d053
languageName: node
linkType: hard
@@ -10085,17 +10173,20 @@ __metadata:
languageName: node
linkType: hard
-"ip@npm:^1.1.5":
- version: 1.1.8
- resolution: "ip@npm:1.1.8"
- checksum: 10/52975ebf84a090162d561fc6948fbc4c53775a8054c05371f09cfcb40e30a53aa225b4efb624f630cff5af2dd8124c82dd68e4df065dc1d1ca91d04e850e9cde
+"ip-address@npm:^9.0.5":
+ version: 9.0.5
+ resolution: "ip-address@npm:9.0.5"
+ dependencies:
+ jsbn: "npm:1.1.0"
+ sprintf-js: "npm:^1.1.3"
+ checksum: 10/1ed81e06721af012306329b31f532b5e24e00cb537be18ddc905a84f19fe8f83a09a1699862bf3a1ec4b9dea93c55a3fa5faf8b5ea380431469df540f38b092c
languageName: node
linkType: hard
-"ip@npm:^2.0.0":
- version: 2.0.0
- resolution: "ip@npm:2.0.0"
- checksum: 10/1270b11e534a466fb4cf4426cbcc3a907c429389f7f4e4e3b288b42823562e88d6a509ceda8141a507de147ca506141f745005c0aa144569d94cf24a54eb52bc
+"ip@npm:^1.1.5":
+ version: 1.1.9
+ resolution: "ip@npm:1.1.9"
+ checksum: 10/29261559b806f64929ada21e6d7e3bf4e67f2b43a4cb67500fdb72cead2e655ce97451a2e325eca3f404081c634ff5c3a68472814744b7f2148ddffc0fdfe66c
languageName: node
linkType: hard
@@ -10106,7 +10197,7 @@ __metadata:
languageName: node
linkType: hard
-"ipaddr.js@npm:^2.0.1":
+"ipaddr.js@npm:^2.1.0":
version: 2.1.0
resolution: "ipaddr.js@npm:2.1.0"
checksum: 10/42c16d95cf451399707c2c46e605b88db1ea2b1477b25774b5a7ee96852b0bb1efdc01adbff01fedbe702ff246e1aca5c5e915a6f5a1f1485233a5f7c2eb73c2
@@ -10132,14 +10223,13 @@ __metadata:
languageName: node
linkType: hard
-"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2":
- version: 3.0.2
- resolution: "is-array-buffer@npm:3.0.2"
+"is-array-buffer@npm:^3.0.4":
+ version: 3.0.4
+ resolution: "is-array-buffer@npm:3.0.4"
dependencies:
call-bind: "npm:^1.0.2"
- get-intrinsic: "npm:^1.2.0"
- is-typed-array: "npm:^1.1.10"
- checksum: 10/dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14
+ get-intrinsic: "npm:^1.2.1"
+ checksum: 10/34a26213d981d58b30724ef37a1e0682f4040d580fa9ff58fdfdd3cefcb2287921718c63971c1c404951e7b747c50fdc7caf6e867e951353fa71b369c04c969b
languageName: node
linkType: hard
@@ -10403,6 +10493,13 @@ __metadata:
languageName: node
linkType: hard
+"is-network-error@npm:^1.0.0":
+ version: 1.0.1
+ resolution: "is-network-error@npm:1.0.1"
+ checksum: 10/165d61500c4186c62db5a3a693d6bfa14ca40fe9b471ef4cd4f27b20ef6760880faf5386dc01ca9867531631782941fedaa94521d09959edf71f046e393c7b91
+ languageName: node
+ linkType: hard
+
"is-number-object@npm:^1.0.4":
version: 1.0.7
resolution: "is-number-object@npm:1.0.7"
@@ -10576,12 +10673,12 @@ __metadata:
languageName: node
linkType: hard
-"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.9":
- version: 1.1.12
- resolution: "is-typed-array@npm:1.1.12"
+"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.9":
+ version: 1.1.13
+ resolution: "is-typed-array@npm:1.1.13"
dependencies:
- which-typed-array: "npm:^1.1.11"
- checksum: 10/d953adfd3c41618d5e01b2a10f21817e4cdc9572772fa17211100aebb3811b6e3c2e308a0558cc87d218a30504cb90154b833013437776551bfb70606fb088ca
+ which-typed-array: "npm:^1.1.14"
+ checksum: 10/f850ba08286358b9a11aee6d93d371a45e3c59b5953549ee1c1a9a55ba5c1dd1bd9952488ae194ad8f32a9cf5e79c8fa5f0cc4d78c00720aa0bbcf238b38062d
languageName: node
linkType: hard
@@ -10673,9 +10770,9 @@ __metadata:
linkType: hard
"isbinaryfile@npm:^5.0.0":
- version: 5.0.0
- resolution: "isbinaryfile@npm:5.0.0"
- checksum: 10/511bb5ce54c903e9881ca46fe7fe06759b29d9d01d6929f3c46cb95a4bf369320d9de858943d5bf4ac446a442b53be095b325b1deebca0e67ccd9f466c53ef74
+ version: 5.0.2
+ resolution: "isbinaryfile@npm:5.0.2"
+ checksum: 10/515d7c963b35c2c443457d18c9152d1f655f3a0e2dceb548448e482145c1897e57a92fc024dece7de98c85c2909f5528e34e3d720c307887529cd689d7a7cd36
languageName: node
linkType: hard
@@ -10790,6 +10887,13 @@ __metadata:
languageName: node
linkType: hard
+"jsbn@npm:1.1.0":
+ version: 1.1.0
+ resolution: "jsbn@npm:1.1.0"
+ checksum: 10/bebe7ae829bbd586ce8cbe83501dd8cb8c282c8902a8aeeed0a073a89dc37e8103b1244f3c6acd60278bcbfe12d93a3f83c9ac396868a3b3bbc3c5e5e3b648ef
+ languageName: node
+ linkType: hard
+
"jsesc@npm:^2.5.1":
version: 2.5.2
resolution: "jsesc@npm:2.5.2"
@@ -11077,7 +11181,7 @@ __metadata:
languageName: node
linkType: hard
-"launch-editor@npm:^2.6.0":
+"launch-editor@npm:^2.6.1":
version: 2.6.1
resolution: "launch-editor@npm:2.6.1"
dependencies:
@@ -11184,9 +11288,9 @@ __metadata:
languageName: node
linkType: hard
-"lint-staged@npm:15.2.1":
- version: 15.2.1
- resolution: "lint-staged@npm:15.2.1"
+"lint-staged@npm:15.2.2":
+ version: 15.2.2
+ resolution: "lint-staged@npm:15.2.2"
dependencies:
chalk: "npm:5.3.0"
commander: "npm:11.1.0"
@@ -11200,7 +11304,7 @@ __metadata:
yaml: "npm:2.3.4"
bin:
lint-staged: bin/lint-staged.js
- checksum: 10/ee2e858b9afea01378ff3a3ff5fbed000f856c553f0ac570d9be6390e27299e586ae047d1efa77fdf17f15aeef0c53f6c658eeb24432748b9203698d929d0c76
+ checksum: 10/5855ae7abf3ffdc2d66e8ad20759915e76544e7c4bcdfef78c82b5c126502284320d9fb0ecde554a6d07747311ab751d0bccbe3468aa5d5a7661774317cd7437
languageName: node
linkType: hard
@@ -11473,9 +11577,9 @@ __metadata:
linkType: hard
"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0":
- version: 10.1.0
- resolution: "lru-cache@npm:10.1.0"
- checksum: 10/207278d6fa711fb1f94a0835d4d4737441d2475302482a14785b10515e4c906a57ebf9f35bf060740c9560e91c7c1ad5a04fd7ed030972a9ba18bce2a228e95b
+ version: 10.2.0
+ resolution: "lru-cache@npm:10.2.0"
+ checksum: 10/502ec42c3309c0eae1ce41afca471f831c278566d45a5273a0c51102dee31e0e250a62fa9029c3370988df33a14188a38e682c16143b794de78668de3643e302
languageName: node
linkType: hard
@@ -11504,12 +11608,12 @@ __metadata:
languageName: node
linkType: hard
-"magic-string@npm:0.30.6, magic-string@npm:^0.30.3":
- version: 0.30.6
- resolution: "magic-string@npm:0.30.6"
+"magic-string@npm:0.30.7, magic-string@npm:^0.30.3":
+ version: 0.30.7
+ resolution: "magic-string@npm:0.30.7"
dependencies:
"@jridgewell/sourcemap-codec": "npm:^1.4.15"
- checksum: 10/046fbf11614a271e7214d32ca02a2af8d18b268403db9d50580f421ff2222261f1cd8bb02a938206130e3c43deefa6423ee4622c4f161212298570f22b4059bb
+ checksum: 10/883eaaf6792a3263e44f4bcdcd35ace272268e4b98ed5a770ad711947958d2f9fc683e474945e306e2bdc152b7e44d369ee312690d87025b9879fc63fbe1409c
languageName: node
linkType: hard
@@ -11582,12 +11686,12 @@ __metadata:
languageName: node
linkType: hard
-"marked@npm:11.2.0":
- version: 11.2.0
- resolution: "marked@npm:11.2.0"
+"marked@npm:12.0.0":
+ version: 12.0.0
+ resolution: "marked@npm:12.0.0"
bin:
marked: bin/marked.js
- checksum: 10/0c8c0d263617a04f066db6f5adfed811a8eb78a685850d4d0b8b9ef351e416fb871813ea7ee7f94f4d5f67da98c3a2a4259b8684e4f93a6a673733fe9d9f2868
+ checksum: 10/ac2e5a3ebf33f8636e65c1eb7f73267cbe101fea1ad08abab60d51e5b4fda30faa59050e2837dc03fb6dbf58f630485c8d01ae5b9d90d36bf4562d7f40c1d33e
languageName: node
linkType: hard
@@ -11610,7 +11714,7 @@ __metadata:
languageName: node
linkType: hard
-"memfs@npm:^3.4.3, memfs@npm:^3.5.0":
+"memfs@npm:^3.5.0":
version: 3.5.3
resolution: "memfs@npm:3.5.3"
dependencies:
@@ -11619,6 +11723,15 @@ __metadata:
languageName: node
linkType: hard
+"memfs@npm:^4.6.0":
+ version: 4.7.6
+ resolution: "memfs@npm:4.7.6"
+ dependencies:
+ tslib: "npm:^2.0.0"
+ checksum: 10/b2a4c95635aa7ed9162c647b60ebbe6f84c541dd91d99e56602f1e904503447aaf92c46918ddf0b84acfb8e52e9af90bd63a6c0cfb1cc8bfdf31379f2fba8e11
+ languageName: node
+ linkType: hard
+
"memoize-one@npm:6.0.0":
version: 6.0.0
resolution: "memoize-one@npm:6.0.0"
@@ -11763,7 +11876,7 @@ __metadata:
languageName: node
linkType: hard
-"minimatch@npm:3.1.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2":
+"minimatch@npm:3.1.2, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2":
version: 3.1.2
resolution: "minimatch@npm:3.1.2"
dependencies:
@@ -11927,9 +12040,9 @@ __metadata:
languageName: node
linkType: hard
-"mocha@npm:10.2.0":
- version: 10.2.0
- resolution: "mocha@npm:10.2.0"
+"mocha@npm:10.3.0":
+ version: 10.3.0
+ resolution: "mocha@npm:10.3.0"
dependencies:
ansi-colors: "npm:4.1.1"
browser-stdout: "npm:1.3.1"
@@ -11938,13 +12051,12 @@ __metadata:
diff: "npm:5.0.0"
escape-string-regexp: "npm:4.0.0"
find-up: "npm:5.0.0"
- glob: "npm:7.2.0"
+ glob: "npm:8.1.0"
he: "npm:1.2.0"
js-yaml: "npm:4.1.0"
log-symbols: "npm:4.1.0"
minimatch: "npm:5.0.1"
ms: "npm:2.1.3"
- nanoid: "npm:3.3.3"
serialize-javascript: "npm:6.0.0"
strip-json-comments: "npm:3.1.1"
supports-color: "npm:8.1.1"
@@ -11955,7 +12067,7 @@ __metadata:
bin:
_mocha: bin/_mocha
mocha: bin/mocha.js
- checksum: 10/f7362898ae65e8fe716cfe62fd014b432d100c9611aaf5abe85ed14efcbfdd82f3bdf32c44bccf00c9059a264c7e8d93a69dd5b830652109052a92beffb7ea35
+ checksum: 10/8b30b3fdb3f365fca7e069fce732e13db4192e1bf8f49e63ec67a3b7857c41cbcd162289ad22178db6ef405fb251b8a0dbb54e942d08c72abf45e1ec3fcdd052
languageName: node
linkType: hard
@@ -12015,15 +12127,6 @@ __metadata:
languageName: node
linkType: hard
-"nanoid@npm:3.3.3":
- version: 3.3.3
- resolution: "nanoid@npm:3.3.3"
- bin:
- nanoid: bin/nanoid.cjs
- checksum: 10/c703ed58a234b68245a8a4826dd25c1453a9017d34fa28bc58e7aa8247de87d854582fa2209d7aee04084cff9ce150be8fd30300abe567dc615d4e8e735f2d99
- languageName: node
- linkType: hard
-
"nanoid@npm:^3.3.7":
version: 3.3.7
resolution: "nanoid@npm:3.3.7"
@@ -12081,15 +12184,15 @@ __metadata:
linkType: hard
"nise@npm:^5.1.5":
- version: 5.1.7
- resolution: "nise@npm:5.1.7"
+ version: 5.1.9
+ resolution: "nise@npm:5.1.9"
dependencies:
"@sinonjs/commons": "npm:^3.0.0"
"@sinonjs/fake-timers": "npm:^11.2.2"
"@sinonjs/text-encoding": "npm:^0.7.2"
just-extend: "npm:^6.2.0"
path-to-regexp: "npm:^6.2.1"
- checksum: 10/4754e3ae52654f66e947d44d0dd40ae823e594c201474ad7c5115acb2188c839c9b8617504327051857aea8042befac946e82918e1e53b99350cb275140332d0
+ checksum: 10/971caf7638d42a0e106eadd63f05adac1217f864b0a7e4519546aea82a0dbfac68586e7ff430704d54a01ff5dbf6cad58f5f67c067e21112a7deacd7789c2172
languageName: node
linkType: hard
@@ -12266,7 +12369,7 @@ __metadata:
languageName: node
linkType: hard
-"object-inspect@npm:^1.13.1, object-inspect@npm:^1.9.0":
+"object-inspect@npm:^1.13.1":
version: 1.13.1
resolution: "object-inspect@npm:1.13.1"
checksum: 10/92f4989ed83422d56431bc39656d4c780348eb15d397ce352ade6b7fec08f973b53744bd41b94af021901e61acaf78fcc19e65bf464ecc0df958586a672700f0
@@ -12289,7 +12392,7 @@ __metadata:
languageName: node
linkType: hard
-"object.assign@npm:^4.0.4, object.assign@npm:^4.1.0, object.assign@npm:^4.1.2, object.assign@npm:^4.1.4":
+"object.assign@npm:^4.0.4, object.assign@npm:^4.1.0, object.assign@npm:^4.1.2, object.assign@npm:^4.1.5":
version: 4.1.5
resolution: "object.assign@npm:4.1.5"
dependencies:
@@ -12336,14 +12439,15 @@ __metadata:
linkType: hard
"object.groupby@npm:^1.0.1":
- version: 1.0.1
- resolution: "object.groupby@npm:1.0.1"
+ version: 1.0.2
+ resolution: "object.groupby@npm:1.0.2"
dependencies:
- call-bind: "npm:^1.0.2"
- define-properties: "npm:^1.2.0"
- es-abstract: "npm:^1.22.1"
- get-intrinsic: "npm:^1.2.1"
- checksum: 10/b7123d91403f95d63978513b23a6079c30f503311f64035fafc863c291c787f287b58df3b21ef002ce1d0b820958c9009dd5a8ab696e0eca325639d345e41524
+ array.prototype.filter: "npm:^1.0.3"
+ call-bind: "npm:^1.0.5"
+ define-properties: "npm:^1.2.1"
+ es-abstract: "npm:^1.22.3"
+ es-errors: "npm:^1.0.0"
+ checksum: 10/07c1bea1772c45f7967a63358a683ef7b0bd99cabe0563e6fee3e8acc061cc5984d2f01a46472ebf10b2cb439298c46776b2134550dce457fd7240baaaa4f592
languageName: node
linkType: hard
@@ -12451,7 +12555,7 @@ __metadata:
languageName: node
linkType: hard
-"open@npm:10.0.3":
+"open@npm:10.0.3, open@npm:^10.0.3":
version: 10.0.3
resolution: "open@npm:10.0.3"
dependencies:
@@ -12463,7 +12567,7 @@ __metadata:
languageName: node
linkType: hard
-"open@npm:^8.0.2, open@npm:^8.0.9, open@npm:^8.4.0":
+"open@npm:^8.0.2, open@npm:^8.4.0":
version: 8.4.2
resolution: "open@npm:8.4.2"
dependencies:
@@ -12578,13 +12682,14 @@ __metadata:
languageName: node
linkType: hard
-"p-retry@npm:^4.5.0":
- version: 4.6.2
- resolution: "p-retry@npm:4.6.2"
+"p-retry@npm:^6.2.0":
+ version: 6.2.0
+ resolution: "p-retry@npm:6.2.0"
dependencies:
- "@types/retry": "npm:0.12.0"
+ "@types/retry": "npm:0.12.2"
+ is-network-error: "npm:^1.0.0"
retry: "npm:^0.13.1"
- checksum: 10/45c270bfddaffb4a895cea16cb760dcc72bdecb6cb45fef1971fa6ea2e91ddeafddefe01e444ac73e33b1b3d5d29fb0dd18a7effb294262437221ddc03ce0f2e
+ checksum: 10/1a5ac16828c96c03c354f78d643dfc7aa8f8b998e1b60e27533da2c75e5cabfb1c7f88ce312e813e09a80b056011fbb372d384132e9c92d27d052bd7c282a978
languageName: node
linkType: hard
@@ -12636,12 +12741,12 @@ __metadata:
linkType: hard
"parse-bmfont-xml@npm:^1.1.4":
- version: 1.1.4
- resolution: "parse-bmfont-xml@npm:1.1.4"
+ version: 1.1.6
+ resolution: "parse-bmfont-xml@npm:1.1.6"
dependencies:
xml-parse-from-string: "npm:^1.0.0"
- xml2js: "npm:^0.4.5"
- checksum: 10/529d9c65da5e7840723d5382707d5a5177d25616e6ea434b4c474548e6229f1e64d0991bc9b38329762038e885c9097c562343007db78d9e9ca1e9b7157e6d7e
+ xml2js: "npm:^0.5.0"
+ checksum: 10/71a202da289a124db7bb7bee1b2a01b8a38b5ba36f93d6a98cea6fc1d140c16c8bc7bcccff48864ec886da035944d337b04cf70723393c411991af952fc6086b
languageName: node
linkType: hard
@@ -13042,13 +13147,13 @@ __metadata:
linkType: hard
"postcss@npm:^8.4.14":
- version: 8.4.33
- resolution: "postcss@npm:8.4.33"
+ version: 8.4.35
+ resolution: "postcss@npm:8.4.35"
dependencies:
nanoid: "npm:^3.3.7"
picocolors: "npm:^1.0.0"
source-map-js: "npm:^1.0.2"
- checksum: 10/e22a4594c255f26117f38419fb494d7ecab0f596cd409f7aadc8a6173abf180ed7ea970cd13fd366ab12b5840be901d2a09b25197700c2ebcb5a8077326bf519
+ checksum: 10/93a7ce50cd6188f5f486a9ca98950ad27c19dfed996c45c414fa242944497e4d084a8760d3537f078630226f2bd3c6ab84b813b488740f4432e7c7039cd73a20
languageName: node
linkType: hard
@@ -13066,12 +13171,12 @@ __metadata:
languageName: node
linkType: hard
-"prettier@npm:3.2.4":
- version: 3.2.4
- resolution: "prettier@npm:3.2.4"
+"prettier@npm:3.2.5":
+ version: 3.2.5
+ resolution: "prettier@npm:3.2.5"
bin:
prettier: bin/prettier.cjs
- checksum: 10/e2b735d0552501b3a7ac8bd3ba3b6de2920bb35bd4cd02d08cb9057ebe3e96d83b9a7e4b903d987b7530a50223b12c74d107c154337236ae2c68156ba1e65cd2
+ checksum: 10/d509f9da0b70e8cacc561a1911c0d99ec75117faed27b95cc8534cb2349667dee6351b0ca83fa9d5703f14127faa52b798de40f5705f02d843da133fc3aa416a
languageName: node
linkType: hard
@@ -13136,15 +13241,6 @@ __metadata:
languageName: node
linkType: hard
-"promise@npm:^8.0.1":
- version: 8.3.0
- resolution: "promise@npm:8.3.0"
- dependencies:
- asap: "npm:~2.0.6"
- checksum: 10/55e9d0d723c66810966bc055c6c77a3658c0af7e4a8cc88ea47aeaf2949ca0bd1de327d9c631df61236f5406ad478384fa19a77afb3f88c0303eba9e5eb0a8d8
- languageName: node
- linkType: hard
-
"proxy-addr@npm:~2.0.7":
version: 2.0.7
resolution: "proxy-addr@npm:2.0.7"
@@ -13423,14 +13519,15 @@ __metadata:
languageName: node
linkType: hard
-"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.1":
- version: 1.5.1
- resolution: "regexp.prototype.flags@npm:1.5.1"
+"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.2":
+ version: 1.5.2
+ resolution: "regexp.prototype.flags@npm:1.5.2"
dependencies:
- call-bind: "npm:^1.0.2"
- define-properties: "npm:^1.2.0"
- set-function-name: "npm:^2.0.0"
- checksum: 10/3fa5610b8e411bbc3a43ddfd13162f3a817beb43155fbd8caa24d4fd0ce2f431a8197541808772a5a06e5946cebfb68464c827827115bde0d11720a92fe2981a
+ call-bind: "npm:^1.0.6"
+ define-properties: "npm:^1.2.1"
+ es-errors: "npm:^1.3.0"
+ set-function-name: "npm:^2.0.1"
+ checksum: 10/9fffc01da9c4e12670ff95bc5204364615fcc12d86fc30642765af908675678ebb0780883c874b2dbd184505fb52fa603d80073ecf69f461ce7f56b15d10be9c
languageName: node
linkType: hard
@@ -13718,9 +13815,9 @@ __metadata:
linkType: hard
"rfdc@npm:^1.3.0":
- version: 1.3.0
- resolution: "rfdc@npm:1.3.0"
- checksum: 10/76dedd9700cdf132947fde7ce1a8838c9cbb7f3e8f9188af0aaf97194cce745f42094dd2cf547426934cc83252ee2c0e432b2e0222a4415ab0db32de82665c69
+ version: 1.3.1
+ resolution: "rfdc@npm:1.3.1"
+ checksum: 10/44cc6a82e2fe1db13b7d3c54e9ffd0b40ef070cbde69ffbfbb38dab8cee46bd68ba686784b96365ff08d04798bc121c3465663a0c91f2c421c90546c4366f4a6
languageName: node
linkType: hard
@@ -13735,6 +13832,17 @@ __metadata:
languageName: node
linkType: hard
+"rimraf@npm:^5.0.5":
+ version: 5.0.5
+ resolution: "rimraf@npm:5.0.5"
+ dependencies:
+ glob: "npm:^10.3.7"
+ bin:
+ rimraf: dist/esm/bin.mjs
+ checksum: 10/a612c7184f96258b7d1328c486b12ca7b60aa30e04229a08bbfa7e964486deb1e9a1b52d917809311bdc39a808a4055c0f950c0280fba194ba0a09e6f0d404f6
+ languageName: node
+ linkType: hard
+
"roboto-fontface@npm:0.10.0":
version: 0.10.0
resolution: "roboto-fontface@npm:0.10.0"
@@ -13832,7 +13940,7 @@ __metadata:
languageName: node
linkType: hard
-"safe-array-concat@npm:^1.0.1":
+"safe-array-concat@npm:^1.1.0":
version: 1.1.0
resolution: "safe-array-concat@npm:1.1.0"
dependencies:
@@ -13858,14 +13966,14 @@ __metadata:
languageName: node
linkType: hard
-"safe-regex-test@npm:^1.0.0":
- version: 1.0.2
- resolution: "safe-regex-test@npm:1.0.2"
+"safe-regex-test@npm:^1.0.3":
+ version: 1.0.3
+ resolution: "safe-regex-test@npm:1.0.3"
dependencies:
- call-bind: "npm:^1.0.5"
- get-intrinsic: "npm:^1.2.2"
+ call-bind: "npm:^1.0.6"
+ es-errors: "npm:^1.3.0"
is-regex: "npm:^1.1.4"
- checksum: 10/0e6a472caa8f44a502c7842ea19749de42c2eb1b41cb00456061dc3746cf3468e907522f56e97a15f3b41d88f660bd3d4f9bdec064a39895f7babae0f7aafc6a
+ checksum: 10/b04de61114b10274d92e25b6de7ccb5de07f11ea15637ff636de4b5190c0f5cd8823fe586dde718504cf78055437d70fd8804976894df502fcf5a210c970afb3
languageName: node
linkType: hard
@@ -13903,7 +14011,7 @@ __metadata:
languageName: node
linkType: hard
-"schema-utils@npm:^4.0.0":
+"schema-utils@npm:^4.0.0, schema-utils@npm:^4.2.0":
version: 4.2.0
resolution: "schema-utils@npm:4.2.0"
dependencies:
@@ -13922,7 +14030,7 @@ __metadata:
languageName: node
linkType: hard
-"selfsigned@npm:^2.1.1":
+"selfsigned@npm:^2.4.1":
version: 2.4.1
resolution: "selfsigned@npm:2.4.1"
dependencies:
@@ -13960,13 +14068,13 @@ __metadata:
linkType: hard
"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.4":
- version: 7.5.4
- resolution: "semver@npm:7.5.4"
+ version: 7.6.0
+ resolution: "semver@npm:7.6.0"
dependencies:
lru-cache: "npm:^6.0.0"
bin:
semver: bin/semver.js
- checksum: 10/985dec0d372370229a262c737063860fabd4a1c730662c1ea3200a2f649117761a42184c96df62a0e885e76fbd5dace41087d6c1ac0351b13c0df5d6bcb1b5ac
+ checksum: 10/1b41018df2d8aca5a1db4729985e8e20428c650daea60fcd16e926e9383217d00f574fab92d79612771884a98d2ee2a1973f49d630829a8d54d6570defe62535
languageName: node
linkType: hard
@@ -14068,20 +14176,21 @@ __metadata:
languageName: node
linkType: hard
-"set-function-length@npm:^1.1.1":
- version: 1.2.0
- resolution: "set-function-length@npm:1.2.0"
+"set-function-length@npm:^1.2.1":
+ version: 1.2.1
+ resolution: "set-function-length@npm:1.2.1"
dependencies:
- define-data-property: "npm:^1.1.1"
+ define-data-property: "npm:^1.1.2"
+ es-errors: "npm:^1.3.0"
function-bind: "npm:^1.1.2"
- get-intrinsic: "npm:^1.2.2"
+ get-intrinsic: "npm:^1.2.3"
gopd: "npm:^1.0.1"
has-property-descriptors: "npm:^1.0.1"
- checksum: 10/6d609cd060c488d7d2178a5d4c3689f8a6afa26fa4c48ff4a0516664ff9b84c1c0898915777f5628092dab55c4fcead205525e2edd15c659423bf86f790fdcae
+ checksum: 10/9ab1d200149574ab27c1a7acae56d6235e02568fc68655fe8afe63e4e02ccad3c27665f55c32408bd1ff40705939dbb7539abfb9c3a07fda27ecad1ab9e449f5
languageName: node
linkType: hard
-"set-function-name@npm:^2.0.0":
+"set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1":
version: 2.0.1
resolution: "set-function-name@npm:2.0.1"
dependencies:
@@ -14158,13 +14267,14 @@ __metadata:
linkType: hard
"side-channel@npm:^1.0.4":
- version: 1.0.4
- resolution: "side-channel@npm:1.0.4"
+ version: 1.0.5
+ resolution: "side-channel@npm:1.0.5"
dependencies:
- call-bind: "npm:^1.0.0"
- get-intrinsic: "npm:^1.0.2"
- object-inspect: "npm:^1.9.0"
- checksum: 10/c4998d9fc530b0e75a7fd791ad868fdc42846f072734f9080ff55cc8dc7d3899abcda24fd896aa6648c3ab7021b4bb478073eb4f44dfd55bce9714bc1a7c5d45
+ call-bind: "npm:^1.0.6"
+ es-errors: "npm:^1.3.0"
+ get-intrinsic: "npm:^1.2.4"
+ object-inspect: "npm:^1.13.1"
+ checksum: 10/27708b70b5d81bf18dc8cc23f38f1b6c9511691a64abc4aaf17956e67d132c855cf8b46f931e2fc5a6262b29371eb60da7755c1b9f4f862eccea8562b469f8f6
languageName: node
linkType: hard
@@ -14296,12 +14406,12 @@ __metadata:
linkType: hard
"socks@npm:^2.7.1":
- version: 2.7.1
- resolution: "socks@npm:2.7.1"
+ version: 2.8.0
+ resolution: "socks@npm:2.8.0"
dependencies:
- ip: "npm:^2.0.0"
+ ip-address: "npm:^9.0.5"
smart-buffer: "npm:^4.2.0"
- checksum: 10/5074f7d6a13b3155fa655191df1c7e7a48ce3234b8ccf99afa2ccb56591c195e75e8bb78486f8e9ea8168e95a29573cbaad55b2b5e195160ae4d2ea6811ba833
+ checksum: 10/ed0224ce2c7daaa7690cb87cf53d9703ffc4e983aca221f6f5b46767b232658df49494fd86acd0bf97ada6de05248ea8ea625c2343d48155d8463fc40d4a340f
languageName: node
linkType: hard
@@ -14425,9 +14535,9 @@ __metadata:
linkType: hard
"spdx-exceptions@npm:^2.1.0":
- version: 2.3.0
- resolution: "spdx-exceptions@npm:2.3.0"
- checksum: 10/cb69a26fa3b46305637123cd37c85f75610e8c477b6476fa7354eb67c08128d159f1d36715f19be6f9daf4b680337deb8c65acdcae7f2608ba51931540687ac0
+ version: 2.5.0
+ resolution: "spdx-exceptions@npm:2.5.0"
+ checksum: 10/bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15
languageName: node
linkType: hard
@@ -14442,9 +14552,9 @@ __metadata:
linkType: hard
"spdx-license-ids@npm:^3.0.0":
- version: 3.0.16
- resolution: "spdx-license-ids@npm:3.0.16"
- checksum: 10/6425c54132ca38d717315cdbd2b620235937d1859972c5978bbc95b4c14400438ffe113709d8aabb0d5498cc27a5b89876fca0fe21b4e26f5ce122bc86d0d88e
+ version: 3.0.17
+ resolution: "spdx-license-ids@npm:3.0.17"
+ checksum: 10/8f6c6ae02ebb25b4ca658b8990d9e8a8f8d8a95e1d8b9fd84d87eed80a7dc8f8073d6a8d50b8a0295c0e8399e1f8814f5c00e2985e6bf3731540a16f7241cbf1
languageName: node
linkType: hard
@@ -14484,6 +14594,13 @@ __metadata:
languageName: node
linkType: hard
+"sprintf-js@npm:^1.1.3":
+ version: 1.1.3
+ resolution: "sprintf-js@npm:1.1.3"
+ checksum: 10/e7587128c423f7e43cc625fe2f87e6affdf5ca51c1cc468e910d8aaca46bb44a7fbcfa552f787b1d3987f7043aeb4527d1b99559e6621e01b42b3f45e5a24cbb
+ languageName: node
+ linkType: hard
+
"ssri@npm:^10.0.0":
version: 10.0.5
resolution: "ssri@npm:10.0.5"
@@ -14561,7 +14678,7 @@ __metadata:
languageName: node
linkType: hard
-"std-env@npm:^3.6.0":
+"std-env@npm:^3.7.0":
version: 3.7.0
resolution: "std-env@npm:3.7.0"
checksum: 10/6ee0cca1add3fd84656b0002cfbc5bfa20340389d9ba4720569840f1caa34bce74322aef4c93f046391583e50649d0cf81a5f8fe1d411e50b659571690a45f12
@@ -14639,13 +14756,13 @@ __metadata:
linkType: hard
"string-width@npm:^7.0.0":
- version: 7.0.0
- resolution: "string-width@npm:7.0.0"
+ version: 7.1.0
+ resolution: "string-width@npm:7.1.0"
dependencies:
emoji-regex: "npm:^10.3.0"
get-east-asian-width: "npm:^1.0.0"
strip-ansi: "npm:^7.1.0"
- checksum: 10/bc0de5700a2690895169fce447ec4ed44bc62de80312c2093d5606bfd48319bb88e48a99e97f269dff2bc9577448b91c26b3804c16e7d9b389699795e4655c3b
+ checksum: 10/a183573fe7209e0d294f661846d33f8caf72aa86d983e5b48a0ed45ab15bcccb02c6f0344b58b571988871105457137b8207855ea536827dbc4a376a0f31bf8f
languageName: node
linkType: hard
@@ -14974,8 +15091,8 @@ __metadata:
linkType: hard
"terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.26.0":
- version: 5.27.0
- resolution: "terser@npm:5.27.0"
+ version: 5.27.1
+ resolution: "terser@npm:5.27.1"
dependencies:
"@jridgewell/source-map": "npm:^0.3.3"
acorn: "npm:^8.8.2"
@@ -14983,7 +15100,7 @@ __metadata:
source-map-support: "npm:~0.5.20"
bin:
terser: bin/terser
- checksum: 10/9b2c5cb00747dea5994034ca064fb3cc7efc1be6b79a35247662d51ab43bdbe9cbf002bbf29170b5f3bd068c811d0212e22d94acd2cf0d8562687b96f1bffc9f
+ checksum: 10/4b5c8c65548071ae09dc1d9fd64616262876229897eaac9f95cf2e44908a1f4a25d7837c2a38caef1a523cf1cf67d254e74a846e9a854d289c0ad3664d581c3c
languageName: node
linkType: hard
@@ -15189,11 +15306,11 @@ __metadata:
linkType: hard
"ts-api-utils@npm:^1.0.1":
- version: 1.0.3
- resolution: "ts-api-utils@npm:1.0.3"
+ version: 1.2.1
+ resolution: "ts-api-utils@npm:1.2.1"
peerDependencies:
typescript: ">=4.2.0"
- checksum: 10/1350a5110eb1e534e9a6178f4081fb8a4fcc439749e19f4ad699baec9090fcb90fe532d5e191d91a062dc6e454a14a8d7eb2ad202f57135a30c4a44a3024f039
+ checksum: 10/6d7f60fd01e3885bb334607f22b9cb1002e72da81dad2e672fef1b0d1a2f640b0f0ff5310369401488fac90c7a7f5d39c89fd18789af59c672c9b5aef4cade3e
languageName: node
linkType: hard
@@ -15226,7 +15343,7 @@ __metadata:
languageName: node
linkType: hard
-"tslib@npm:^2.0.1, tslib@npm:^2.0.2, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0":
+"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.2, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0":
version: 2.6.2
resolution: "tslib@npm:2.6.2"
checksum: 10/bd26c22d36736513980091a1e356378e8b662ded04204453d353a7f34a4c21ed0afc59b5f90719d4ba756e581a162ecbf93118dc9c6be5acf70aa309188166ca
@@ -15404,14 +15521,14 @@ __metadata:
languageName: node
linkType: hard
-"typed-array-buffer@npm:^1.0.0":
- version: 1.0.0
- resolution: "typed-array-buffer@npm:1.0.0"
+"typed-array-buffer@npm:^1.0.1":
+ version: 1.0.1
+ resolution: "typed-array-buffer@npm:1.0.1"
dependencies:
- call-bind: "npm:^1.0.2"
- get-intrinsic: "npm:^1.2.1"
- is-typed-array: "npm:^1.1.10"
- checksum: 10/3e0281c79b2a40cd97fe715db803884301993f4e8c18e8d79d75fd18f796e8cd203310fec8c7fdb5e6c09bedf0af4f6ab8b75eb3d3a85da69328f28a80456bd3
+ call-bind: "npm:^1.0.6"
+ es-errors: "npm:^1.3.0"
+ is-typed-array: "npm:^1.1.13"
+ checksum: 10/1d65e46b2b9b7ec2a30df39b9ddf32e55ad08d6119aec33975506a3dba56057796bdc3c64dbeb7fdb61bf340a75e279dfd55b48ce8f3b874f01731e1da6833d2
languageName: node
linkType: hard
@@ -15428,15 +15545,16 @@ __metadata:
linkType: hard
"typed-array-byte-offset@npm:^1.0.0":
- version: 1.0.0
- resolution: "typed-array-byte-offset@npm:1.0.0"
+ version: 1.0.1
+ resolution: "typed-array-byte-offset@npm:1.0.1"
dependencies:
- available-typed-arrays: "npm:^1.0.5"
- call-bind: "npm:^1.0.2"
+ available-typed-arrays: "npm:^1.0.6"
+ call-bind: "npm:^1.0.7"
for-each: "npm:^0.3.3"
+ gopd: "npm:^1.0.1"
has-proto: "npm:^1.0.1"
- is-typed-array: "npm:^1.1.10"
- checksum: 10/2d81747faae31ca79f6c597dc18e15ae3d5b7e97f7aaebce3b31f46feeb2a6c1d6c92b9a634d901c83731ffb7ec0b74d05c6ff56076f5ae39db0cd19b16a3f92
+ is-typed-array: "npm:^1.1.13"
+ checksum: 10/b174c0bac20bcd8787d2f5ccd7bd8f5e5a128e060ffe0909ffe27d65e486de50a3552248a307a45e5c9c593fd8ec97f5acdf119c3e13806f11943b7a2ce555be
languageName: node
linkType: hard
@@ -16063,57 +16181,60 @@ __metadata:
languageName: node
linkType: hard
-"webpack-dev-middleware@npm:^5.3.1":
- version: 5.3.3
- resolution: "webpack-dev-middleware@npm:5.3.3"
+"webpack-dev-middleware@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "webpack-dev-middleware@npm:7.0.0"
dependencies:
colorette: "npm:^2.0.10"
- memfs: "npm:^3.4.3"
+ memfs: "npm:^4.6.0"
mime-types: "npm:^2.1.31"
range-parser: "npm:^1.2.1"
schema-utils: "npm:^4.0.0"
peerDependencies:
- webpack: ^4.0.0 || ^5.0.0
- checksum: 10/31a2f7a11e58a76bdcde1eb8da310b6643844d9b442f9916f48be5b46c103f23490c393c32a9af501ce68226fbb018b811f5a956635ed60a03f9481a4bcd6c76
+ webpack: ^5.0.0
+ peerDependenciesMeta:
+ webpack:
+ optional: true
+ checksum: 10/e94902c35458c2431cd3332088cf33afe9236333e911605e6045392be11f521140600312c698263acf2a6c52e2092b8e8b3ea4b0ed34568df6cb7a79913aa1d3
languageName: node
linkType: hard
-"webpack-dev-server@npm:4.15.1":
- version: 4.15.1
- resolution: "webpack-dev-server@npm:4.15.1"
+"webpack-dev-server@npm:5.0.2":
+ version: 5.0.2
+ resolution: "webpack-dev-server@npm:5.0.2"
dependencies:
- "@types/bonjour": "npm:^3.5.9"
- "@types/connect-history-api-fallback": "npm:^1.3.5"
- "@types/express": "npm:^4.17.13"
- "@types/serve-index": "npm:^1.9.1"
- "@types/serve-static": "npm:^1.13.10"
- "@types/sockjs": "npm:^0.3.33"
- "@types/ws": "npm:^8.5.5"
+ "@types/bonjour": "npm:^3.5.13"
+ "@types/connect-history-api-fallback": "npm:^1.5.4"
+ "@types/express": "npm:^4.17.21"
+ "@types/serve-index": "npm:^1.9.4"
+ "@types/serve-static": "npm:^1.15.5"
+ "@types/sockjs": "npm:^0.3.36"
+ "@types/ws": "npm:^8.5.10"
ansi-html-community: "npm:^0.0.8"
- bonjour-service: "npm:^1.0.11"
- chokidar: "npm:^3.5.3"
+ bonjour-service: "npm:^1.2.1"
+ chokidar: "npm:^3.6.0"
colorette: "npm:^2.0.10"
compression: "npm:^1.7.4"
connect-history-api-fallback: "npm:^2.0.0"
default-gateway: "npm:^6.0.3"
express: "npm:^4.17.3"
graceful-fs: "npm:^4.2.6"
- html-entities: "npm:^2.3.2"
+ html-entities: "npm:^2.4.0"
http-proxy-middleware: "npm:^2.0.3"
- ipaddr.js: "npm:^2.0.1"
- launch-editor: "npm:^2.6.0"
- open: "npm:^8.0.9"
- p-retry: "npm:^4.5.0"
- rimraf: "npm:^3.0.2"
- schema-utils: "npm:^4.0.0"
- selfsigned: "npm:^2.1.1"
+ ipaddr.js: "npm:^2.1.0"
+ launch-editor: "npm:^2.6.1"
+ open: "npm:^10.0.3"
+ p-retry: "npm:^6.2.0"
+ rimraf: "npm:^5.0.5"
+ schema-utils: "npm:^4.2.0"
+ selfsigned: "npm:^2.4.1"
serve-index: "npm:^1.9.1"
sockjs: "npm:^0.3.24"
spdy: "npm:^4.0.2"
- webpack-dev-middleware: "npm:^5.3.1"
- ws: "npm:^8.13.0"
+ webpack-dev-middleware: "npm:^7.0.0"
+ ws: "npm:^8.16.0"
peerDependencies:
- webpack: ^4.37.0 || ^5.0.0
+ webpack: ^5.0.0
peerDependenciesMeta:
webpack:
optional: true
@@ -16121,7 +16242,7 @@ __metadata:
optional: true
bin:
webpack-dev-server: bin/webpack-dev-server.js
- checksum: 10/fd6dfb6c71eb94696b21930ea4c2f25e95ba85fac1bbc15aa5d03af0a90712eba057901fa9131ed3e901665c95b2379208279aca61e9c48e7cda276c3caa95dd
+ checksum: 10/f47205b56a562c72083ad979fceb499dc60ef35a75a72b6fbcbccd258b6b304ab3a977877dc6ce68aa5fb90cee8ab9387e22ceb8e374a019e3d4ce77ad0c9493
languageName: node
linkType: hard
@@ -16172,9 +16293,9 @@ __metadata:
languageName: node
linkType: hard
-"webpack@npm:5.90.1":
- version: 5.90.1
- resolution: "webpack@npm:5.90.1"
+"webpack@npm:5.90.3":
+ version: 5.90.3
+ resolution: "webpack@npm:5.90.3"
dependencies:
"@types/eslint-scope": "npm:^3.7.3"
"@types/estree": "npm:^1.0.5"
@@ -16205,13 +16326,13 @@ __metadata:
optional: true
bin:
webpack: bin/webpack.js
- checksum: 10/6ad23518123f1742238177920cefa61152d981f986adac5901236845c86ba9bb375a3ba75e188925c856c3d2a76a2ba119e95b8a608a51424968389041089075
+ checksum: 10/48c9696eca950bfa7c943a24b8235fdf0575acd73a8eb1661f8189d3d1f431362f3a0e158e2941a7e4f0852ea6e32d7d4e89283149247e4389a8aad0fe6c247e
languageName: node
linkType: hard
-"webpackbar@npm:6.0.0":
- version: 6.0.0
- resolution: "webpackbar@npm:6.0.0"
+"webpackbar@npm:6.0.1":
+ version: 6.0.1
+ resolution: "webpackbar@npm:6.0.1"
dependencies:
ansi-escapes: "npm:^4.3.2"
chalk: "npm:^4.1.2"
@@ -16219,11 +16340,11 @@ __metadata:
figures: "npm:^3.2.0"
markdown-table: "npm:^2.0.0"
pretty-time: "npm:^1.1.0"
- std-env: "npm:^3.6.0"
+ std-env: "npm:^3.7.0"
wrap-ansi: "npm:^7.0.0"
peerDependencies:
webpack: 3 || 4 || 5
- checksum: 10/aa26c2dff6c2384f39b77e57375af52a65fbd3c54b9a5a8e1c53e79b0c25eaabc8602469ec3742bf93f7d178f5a96e3d6bd4fcbb256808e730eecb91091df466
+ checksum: 10/9da47f8dcbc9173b19e41e3e1049fa451b0c02095ffa003e8c09c56aa2cc544334d1c6fff0797162a807b29090db9cf9a269cd5ec453196142543f9275cbbf70
languageName: node
linkType: hard
@@ -16300,16 +16421,16 @@ __metadata:
languageName: node
linkType: hard
-"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13":
- version: 1.1.13
- resolution: "which-typed-array@npm:1.1.13"
+"which-typed-array@npm:^1.1.14":
+ version: 1.1.14
+ resolution: "which-typed-array@npm:1.1.14"
dependencies:
- available-typed-arrays: "npm:^1.0.5"
- call-bind: "npm:^1.0.4"
+ available-typed-arrays: "npm:^1.0.6"
+ call-bind: "npm:^1.0.5"
for-each: "npm:^0.3.3"
gopd: "npm:^1.0.1"
- has-tostringtag: "npm:^1.0.0"
- checksum: 10/605e3e10b7118af904a0e79d0d50b95275102f06ec902734024989cd71354929f7acee50de43529d3baf5858e2e4eb32c75e6ebd226c888ad976d8140e4a3e71
+ has-tostringtag: "npm:^1.0.1"
+ checksum: 10/56253d2c9d6b41b8a4af96d8c2751bac5508906bd500cdcd0dc5301fb082de0391a4311ab21258bc8d2609ed593f422c1a66f0020fcb3a1e97f719bc928b9018
languageName: node
linkType: hard
@@ -16640,7 +16761,7 @@ __metadata:
languageName: node
linkType: hard
-"ws@npm:^8.13.0":
+"ws@npm:^8.16.0":
version: 8.16.0
resolution: "ws@npm:8.16.0"
peerDependencies:
@@ -16674,13 +16795,13 @@ __metadata:
languageName: node
linkType: hard
-"xml2js@npm:^0.4.5":
- version: 0.4.23
- resolution: "xml2js@npm:0.4.23"
+"xml2js@npm:^0.5.0":
+ version: 0.5.0
+ resolution: "xml2js@npm:0.5.0"
dependencies:
sax: "npm:>=0.6.0"
xmlbuilder: "npm:~11.0.0"
- checksum: 10/52896ef39429f860f32471dd7bb2b89ef25b7e15528e3a4366de0bd5e55a251601565e7814763e70f9e75310c3afe649a42b8826442b74b41eff8a0ae333fccc
+ checksum: 10/27c4d759214e99be5ec87ee5cb1290add427fa43df509d3b92d10152b3806fd2f7c9609697a18b158ccf2caa01e96af067cdba93196f69ca10c90e4f79a08896
languageName: node
linkType: hard