Compare commits

...

7 Commits

Author SHA1 Message Date
renovate[bot]
ff17ff030f Update dependency typescript-eslint to v8.46.4 2025-11-13 21:34:16 +00:00
Simon Lamon
4ab24cdc72 Rspack: Deprecated layers (#27942) 2025-11-13 22:32:37 +01:00
Aidan Timson
81c27090d2 Create withViewTransition wrapper function (#27918)
* Create withViewTransition wrapper function

* Add missing space

* Remove function, check for view transition, add param

* Document
2025-11-13 17:32:15 +02:00
karwosts
09bdfd3ad7 Fix incorrect (Disabled) string in trigger (#27935) 2025-11-13 14:36:05 +00:00
karwosts
97e49f751c Fix media image on dashboard-level background (#27934) 2025-11-13 15:43:27 +02:00
Aidan Timson
e0d241a2db Move unimplemented base animations to theme styles (#27920) 2025-11-13 15:37:13 +02:00
Petar Petrov
83e065ae98 Power sources chart (#27501)
* Add power configuration to Energy dashboard

* update translation

* Update src/translations/en.json

Co-authored-by: Norbert Rittel <norbert@rittel.de>

* Update src/panels/config/energy/dialogs/dialog-energy-grid-flow-settings.ts

Co-authored-by: Aidan Timson <aidan@timmo.dev>

* Power graph card

* Single stat for bidirectional power

* Rename power graph to power sources graph

* remove debug code

* tweak

* update translations

* remove unused code

* Separate grid power from energy

* update translation

* update translation

* update data format

* Apply suggestions from code review

Co-authored-by: Aidan Timson <aidan@timmo.dev>

* Renamed stat_power to stat_rate

* translation tweak

* rename to stat_rate

* Add a line depicting used power

* Typescript improvements

* Add comment

---------

Co-authored-by: Norbert Rittel <norbert@rittel.de>
Co-authored-by: Aidan Timson <aidan@timmo.dev>
2025-11-13 09:26:49 +00:00
18 changed files with 590 additions and 135 deletions

View File

@@ -260,7 +260,6 @@ const createRspackConfig = ({
),
},
experiments: {
layers: true,
outputModule: true,
},
};

View File

@@ -217,7 +217,7 @@
"terser-webpack-plugin": "5.3.14",
"ts-lit-plugin": "2.0.2",
"typescript": "5.9.3",
"typescript-eslint": "8.46.3",
"typescript-eslint": "8.46.4",
"vite-tsconfig-paths": "5.1.4",
"vitest": "4.0.8",
"webpack-stats-plugin": "1.1.3",

View File

@@ -0,0 +1,30 @@
/**
* Executes a callback within a View Transition if supported, otherwise runs it directly.
*
* @param callback - Function to execute. Can be synchronous or return a Promise. The callback will be passed a boolean indicating whether the view transition is available.
* @returns Promise that resolves when the transition completes (or immediately if not supported)
*
* @example
* ```typescript
* // Synchronous callback
* withViewTransition(() => {
* this.large = !this.large;
* });
*
* // Async callback
* await withViewTransition(async () => {
* await this.updateData();
* });
* ```
*/
export const withViewTransition = (
callback: (viewTransitionAvailable: boolean) => void | Promise<void>
): Promise<void> => {
if (document.startViewTransition) {
return document.startViewTransition(() => callback(true)).finished;
}
// Fallback: Execute callback directly without transition
const result = callback(false);
return result instanceof Promise ? result : Promise.resolve();
};

View File

@@ -360,6 +360,35 @@ export const getReferencedStatisticIds = (
return statIDs;
};
export const getReferencedStatisticIdsPower = (
prefs: EnergyPreferences
): string[] => {
const statIDs: (string | undefined)[] = [];
for (const source of prefs.energy_sources) {
if (source.type === "gas" || source.type === "water") {
continue;
}
if (source.type === "solar") {
statIDs.push(source.stat_rate);
continue;
}
if (source.type === "battery") {
statIDs.push(source.stat_rate);
continue;
}
if (source.power) {
statIDs.push(...source.power.map((p) => p.stat_rate));
}
}
statIDs.push(...prefs.device_consumption.map((d) => d.stat_rate));
return statIDs.filter(Boolean) as string[];
};
export const enum CompareMode {
NONE = "",
PREVIOUS = "previous",
@@ -407,9 +436,10 @@ const getEnergyData = async (
"gas",
"device",
]);
const powerStatIds = getReferencedStatisticIdsPower(prefs);
const waterStatIds = getReferencedStatisticIds(prefs, info, ["water"]);
const allStatIDs = [...energyStatIds, ...waterStatIds];
const allStatIDs = [...energyStatIds, ...waterStatIds, ...powerStatIds];
const dayDifference = differenceInDays(end || new Date(), start);
const period =
@@ -420,6 +450,8 @@ const getEnergyData = async (
: dayDifference > 2
? "day"
: "hour";
const finePeriod =
dayDifference > 64 ? "day" : dayDifference > 8 ? "hour" : "5minute";
const statsMetadata: Record<string, StatisticsMetaData> = {};
const statsMetadataArray = allStatIDs.length
@@ -441,6 +473,9 @@ const getEnergyData = async (
? (gasUnit as (typeof VOLUME_UNITS)[number])
: undefined,
};
const powerUnits: StatisticsUnitConfiguration = {
power: "kW",
};
const waterUnit = getEnergyWaterUnit(hass, prefs, statsMetadata);
const waterUnits: StatisticsUnitConfiguration = {
volume: waterUnit,
@@ -451,6 +486,12 @@ const getEnergyData = async (
"change",
])
: {};
const _powerStats: Statistics | Promise<Statistics> = powerStatIds.length
? fetchStatistics(hass!, start, end, powerStatIds, finePeriod, powerUnits, [
"mean",
])
: {};
const _waterStats: Statistics | Promise<Statistics> = waterStatIds.length
? fetchStatistics(hass!, start, end, waterStatIds, period, waterUnits, [
"change",
@@ -557,6 +598,7 @@ const getEnergyData = async (
const [
energyStats,
powerStats,
waterStats,
energyStatsCompare,
waterStatsCompare,
@@ -564,13 +606,14 @@ const getEnergyData = async (
fossilEnergyConsumptionCompare,
] = await Promise.all([
_energyStats,
_powerStats,
_waterStats,
_energyStatsCompare,
_waterStatsCompare,
_fossilEnergyConsumption,
_fossilEnergyConsumptionCompare,
]);
const stats = { ...energyStats, ...waterStats };
const stats = { ...energyStats, ...waterStats, ...powerStats };
if (compare) {
statsCompare = { ...energyStatsCompare, ...waterStatsCompare };
}

View File

@@ -63,8 +63,7 @@ export default class HaAutomationSidebarTrigger extends LitElement {
protected render() {
const rowDisabled =
this.disabled ||
("enabled" in this.config.config && this.config.config.enabled === false);
"enabled" in this.config.config && this.config.config.enabled === false;
const type = isTriggerList(this.config.config)
? "list"
: this.config.config.trigger;

View File

@@ -16,8 +16,10 @@ import {
import type {
BarSeriesOption,
CallbackDataParams,
LineSeriesOption,
TopLevelFormatterParams,
} from "echarts/types/dist/shared";
import type { LineDataItemOption } from "echarts/types/src/chart/line/LineSeries";
import type { FrontendLocaleData } from "../../../../../data/translation";
import { formatNumber } from "../../../../../common/number/format_number";
import {
@@ -170,11 +172,10 @@ function formatTooltip(
compare
? `${(showCompareYear ? formatDateShort : formatDateVeryShort)(date, locale, config)}: `
: ""
}${formatTime(date, locale, config)} ${formatTime(
addHours(date, 1),
locale,
config
)}`;
}${formatTime(date, locale, config)}`;
if (params[0].componentSubType === "bar") {
period += ` ${formatTime(addHours(date, 1), locale, config)}`;
}
}
const title = `<h4 style="text-align: center; margin: 0;">${period}</h4>`;
@@ -281,6 +282,35 @@ export function fillDataGapsAndRoundCaps(datasets: BarSeriesOption[]) {
});
}
export function fillLineGaps(datasets: LineSeriesOption[]) {
const buckets = Array.from(
new Set(
datasets
.map((dataset) =>
dataset.data!.map((datapoint) => Number(datapoint![0]))
)
.flat()
)
).sort((a, b) => a - b);
buckets.forEach((bucket, index) => {
for (let i = datasets.length - 1; i >= 0; i--) {
const dataPoint = datasets[i].data![index];
const item: LineDataItemOption =
dataPoint && typeof dataPoint === "object" && "value" in dataPoint
? dataPoint
: ({ value: dataPoint } as LineDataItemOption);
const x = item.value?.[0];
if (x === undefined) {
continue;
}
if (Number(x) !== bucket) {
datasets[i].data?.splice(index, 0, [bucket, 0]);
}
}
});
return datasets;
}
export function getCompareTransform(start: Date, compareStart?: Date) {
if (!compareStart) {
return (ts: Date) => ts;

View File

@@ -0,0 +1,335 @@
import { endOfToday, isToday, startOfToday } from "date-fns";
import type { HassConfig, UnsubscribeFunc } from "home-assistant-js-websocket";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import type { LineSeriesOption } from "echarts/charts";
import { graphic } from "echarts";
import "../../../../components/chart/ha-chart-base";
import "../../../../components/ha-card";
import type { EnergyData } from "../../../../data/energy";
import { getEnergyDataCollection } from "../../../../data/energy";
import type { StatisticValue } from "../../../../data/recorder";
import type { FrontendLocaleData } from "../../../../data/translation";
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
import type { HomeAssistant } from "../../../../types";
import type { LovelaceCard } from "../../types";
import type { PowerSourcesGraphCardConfig } from "../types";
import { hasConfigChanged } from "../../common/has-changed";
import { getCommonOptions, fillLineGaps } from "./common/energy-chart-options";
import type { ECOption } from "../../../../resources/echarts/echarts";
import { hex2rgb } from "../../../../common/color/convert-color";
@customElement("hui-power-sources-graph-card")
export class HuiPowerSourcesGraphCard
extends SubscribeMixin(LitElement)
implements LovelaceCard
{
@property({ attribute: false }) public hass!: HomeAssistant;
@state() private _config?: PowerSourcesGraphCardConfig;
@state() private _chartData: LineSeriesOption[] = [];
@state() private _start = startOfToday();
@state() private _end = endOfToday();
@state() private _compareStart?: Date;
@state() private _compareEnd?: Date;
protected hassSubscribeRequiredHostProps = ["_config"];
public hassSubscribe(): UnsubscribeFunc[] {
return [
getEnergyDataCollection(this.hass, {
key: this._config?.collection_key,
}).subscribe((data) => this._getStatistics(data)),
];
}
public getCardSize(): Promise<number> | number {
return 3;
}
public setConfig(config: PowerSourcesGraphCardConfig): void {
this._config = config;
}
protected shouldUpdate(changedProps: PropertyValues): boolean {
return (
hasConfigChanged(this, changedProps) ||
changedProps.size > 1 ||
!changedProps.has("hass")
);
}
protected render() {
if (!this.hass || !this._config) {
return nothing;
}
return html`
<ha-card>
${this._config.title
? html`<h1 class="card-header">${this._config.title}</h1>`
: ""}
<div
class="content ${classMap({
"has-header": !!this._config.title,
})}"
>
<ha-chart-base
.hass=${this.hass}
.data=${this._chartData}
.options=${this._createOptions(
this._start,
this._end,
this.hass.locale,
this.hass.config,
this._compareStart,
this._compareEnd
)}
></ha-chart-base>
${!this._chartData.some((dataset) => dataset.data!.length)
? html`<div class="no-data">
${isToday(this._start)
? this.hass.localize("ui.panel.lovelace.cards.energy.no_data")
: this.hass.localize(
"ui.panel.lovelace.cards.energy.no_data_period"
)}
</div>`
: nothing}
</div>
</ha-card>
`;
}
private _createOptions = memoizeOne(
(
start: Date,
end: Date,
locale: FrontendLocaleData,
config: HassConfig,
compareStart?: Date,
compareEnd?: Date
): ECOption =>
getCommonOptions(
start,
end,
locale,
config,
"kW",
compareStart,
compareEnd
)
);
private async _getStatistics(energyData: EnergyData): Promise<void> {
const datasets: LineSeriesOption[] = [];
const statIds = {
solar: {
stats: [] as string[],
color: "--energy-solar-color",
name: this.hass.localize(
"ui.panel.lovelace.cards.energy.power_graph.solar"
),
},
grid: {
stats: [] as string[],
color: "--energy-grid-consumption-color",
name: this.hass.localize(
"ui.panel.lovelace.cards.energy.power_graph.grid"
),
},
battery: {
stats: [] as string[],
color: "--energy-battery-out-color",
name: this.hass.localize(
"ui.panel.lovelace.cards.energy.power_graph.battery"
),
},
};
const computedStyles = getComputedStyle(this);
for (const source of energyData.prefs.energy_sources) {
if (source.type === "solar") {
if (source.stat_rate) {
statIds.solar.stats.push(source.stat_rate);
}
continue;
}
if (source.type === "battery") {
if (source.stat_rate) {
statIds.battery.stats.push(source.stat_rate);
}
continue;
}
if (source.type === "grid" && source.power) {
statIds.grid.stats.push(...source.power.map((p) => p.stat_rate));
}
}
const commonSeriesOptions: LineSeriesOption = {
type: "line",
smooth: 0.4,
smoothMonotone: "x",
lineStyle: {
width: 1,
},
};
Object.keys(statIds).forEach((key, keyIndex) => {
if (statIds[key].stats.length) {
const colorHex = computedStyles.getPropertyValue(statIds[key].color);
const rgb = hex2rgb(colorHex);
// Echarts is supposed to handle that but it is bugged when you use it together with stacking.
// The interpolation breaks the stacking, so this positive/negative is a workaround
const { positive, negative } = this._processData(
statIds[key].stats.map((id: string) => energyData.stats[id] ?? [])
);
datasets.push({
...commonSeriesOptions,
id: key,
name: statIds[key].name,
color: colorHex,
stack: "positive",
areaStyle: {
color: new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.75)`,
},
{
offset: 1,
color: `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.25)`,
},
]),
},
data: positive,
z: 3 - keyIndex, // draw in reverse order so 0 value lines are overwritten
});
if (key !== "solar") {
datasets.push({
...commonSeriesOptions,
id: `${key}-negative`,
name: statIds[key].name,
color: colorHex,
stack: "negative",
areaStyle: {
color: new graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.75)`,
},
{
offset: 1,
color: `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.25)`,
},
]),
},
data: negative,
z: 4 - keyIndex, // draw in reverse order but above positive series
});
}
}
});
this._start = energyData.start;
this._end = energyData.end || endOfToday();
this._chartData = fillLineGaps(datasets);
const usageData: NonNullable<LineSeriesOption["data"]> = [];
this._chartData[0]?.data!.forEach((item, i) => {
// fillLineGaps ensures all datasets have the same x values
const x =
typeof item === "object" && "value" in item!
? item.value![0]
: item![0];
usageData[i] = [x, 0];
this._chartData.forEach((dataset) => {
const y =
typeof dataset.data![i] === "object" && "value" in dataset.data![i]!
? dataset.data![i].value![1]
: dataset.data![i]![1];
usageData[i]![1] += y as number;
});
});
this._chartData.push({
...commonSeriesOptions,
id: "usage",
name: this.hass.localize(
"ui.panel.lovelace.cards.energy.power_graph.usage"
),
color: computedStyles.getPropertyValue("--primary-color"),
lineStyle: { width: 2 },
data: usageData,
z: 5,
});
}
private _processData(stats: StatisticValue[][]) {
const data: Record<number, number[]> = {};
stats.forEach((statSet) => {
statSet.forEach((point) => {
if (point.mean == null) {
return;
}
const x = (point.start + point.end) / 2;
data[x] = [...(data[x] ?? []), point.mean];
});
});
const positive: [number, number][] = [];
const negative: [number, number][] = [];
Object.entries(data).forEach(([x, y]) => {
const ts = Number(x);
const meanY = y.reduce((a, b) => a + b, 0) / y.length;
positive.push([ts, Math.max(0, meanY)]);
negative.push([ts, Math.min(0, meanY)]);
});
return { positive, negative };
}
static styles = css`
ha-card {
height: 100%;
}
.card-header {
padding-bottom: 0;
}
.content {
padding: var(--ha-space-4);
}
.has-header {
padding-top: 0;
}
.no-data {
position: absolute;
height: 100%;
top: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
padding: 20%;
margin-left: var(--ha-space-8);
margin-inline-start: var(--ha-space-8);
margin-inline-end: initial;
box-sizing: border-box;
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"hui-power-sources-graph-card": HuiPowerSourcesGraphCard;
}
}

View File

@@ -230,6 +230,11 @@ export interface EnergySankeyCardConfig extends EnergyCardBaseConfig {
group_by_area?: boolean;
}
export interface PowerSourcesGraphCardConfig extends EnergyCardBaseConfig {
type: "power-sources-graph";
title?: string;
}
export interface EntityFilterCardConfig extends LovelaceCardConfig {
type: "entity-filter";
entities: (EntityFilterEntityConfig | string)[];

View File

@@ -66,6 +66,8 @@ const LAZY_LOAD_TYPES = {
"energy-usage-graph": () =>
import("../cards/energy/hui-energy-usage-graph-card"),
"energy-sankey": () => import("../cards/energy/hui-energy-sankey-card"),
"power-sources-graph": () =>
import("../cards/energy/hui-power-sources-graph-card"),
"entity-filter": () => import("../cards/hui-entity-filter-card"),
error: () => import("../cards/hui-error-card"),
"home-summary": () => import("../cards/hui-home-summary-card"),

View File

@@ -22,6 +22,7 @@ const NON_STANDARD_URLS = {
"energy-devices-graph": "energy/#devices-energy-graph",
"energy-devices-detail-graph": "energy/#detail-devices-energy-graph",
"energy-sankey": "energy/#sankey-energy-graph",
"power-sources-graph": "energy/#power-sources-graph",
};
export const getCardDocumentationURL = (

View File

@@ -109,6 +109,7 @@ export class HUIViewBackground extends LitElement {
protected willUpdate(changedProperties: PropertyValues<this>) {
super.willUpdate(changedProperties);
let applyTheme = false;
if (changedProperties.has("hass") && this.hass) {
const oldHass = changedProperties.get("hass");
if (
@@ -116,16 +117,18 @@ export class HUIViewBackground extends LitElement {
this.hass.themes !== oldHass.themes ||
this.hass.selectedTheme !== oldHass.selectedTheme
) {
this._applyTheme();
return;
applyTheme = true;
}
}
if (changedProperties.has("background")) {
this._applyTheme();
applyTheme = true;
this._fetchMedia();
}
if (changedProperties.has("resolvedImage")) {
applyTheme = true;
}
if (applyTheme) {
this._applyTheme();
}
}

View File

@@ -199,23 +199,3 @@ export const baseEntrypointStyles = css`
width: 100vw;
}
`;
export const baseAnimationStyles = css`
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
`;

View File

@@ -0,0 +1,30 @@
import { css } from "lit";
export const animationStyles = css`
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes scale {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
`;

View File

@@ -55,6 +55,7 @@ export const coreStyles = css`
--ha-shadow-spread-sm: 0;
--ha-shadow-spread-md: 0;
--ha-shadow-spread-lg: 0;
--ha-animation-base-duration: 350ms;
}

View File

@@ -1,4 +1,5 @@
import { fontStyles } from "../roboto";
import { animationStyles } from "./animations.globals";
import { colorDerivedVariables, colorStylesCollection } from "./color";
import { coreDerivedVariables, coreStyles } from "./core.globals";
import { mainDerivedVariables, mainStyles } from "./main.globals";
@@ -17,6 +18,7 @@ export const themeStyles = [
...colorStylesCollection,
fontStyles.toString(),
waMainStyles.toString(),
animationStyles.toString(),
].join("");
export const derivedStyles = {

View File

@@ -7161,6 +7161,12 @@
"low_carbon_energy_consumed": "Low-carbon electricity consumed",
"low_carbon_energy_not_calculated": "Consumed low-carbon electricity couldn't be calculated"
},
"power_graph": {
"grid": "Grid",
"solar": "Solar",
"battery": "Battery",
"usage": "Used"
},
"energy_compare": {
"info": "You are comparing the period {start} with the period {end}",
"compare_previous_year": "Compare previous year",

View File

@@ -1,26 +1,7 @@
import type { TemplateResult } from "lit";
import { render } from "lit";
import { parseAnimationDuration } from "../common/util/parse-animation-duration";
const removeElement = (
launchScreenElement: HTMLElement,
skipAnimation: boolean
) => {
if (skipAnimation) {
launchScreenElement.parentElement?.removeChild(launchScreenElement);
return;
}
launchScreenElement.classList.add("removing");
const durationFromCss = getComputedStyle(document.documentElement)
.getPropertyValue("--ha-animation-base-duration")
.trim();
setTimeout(() => {
launchScreenElement.parentElement?.removeChild(launchScreenElement);
}, parseAnimationDuration(durationFromCss));
};
import { withViewTransition } from "../common/util/view-transition";
export const removeLaunchScreen = () => {
const launchScreenElement = document.getElementById("ha-launch-screen");
@@ -28,14 +9,22 @@ export const removeLaunchScreen = () => {
return;
}
if (document.startViewTransition) {
document.startViewTransition(() => {
removeElement(launchScreenElement, false);
});
} else {
// Fallback: Direct removal without transition
removeElement(launchScreenElement, true);
}
withViewTransition((viewTransitionAvailable: boolean) => {
if (!viewTransitionAvailable) {
launchScreenElement.parentElement?.removeChild(launchScreenElement);
return;
}
launchScreenElement.classList.add("removing");
const durationFromCss = getComputedStyle(document.documentElement)
.getPropertyValue("--ha-animation-base-duration")
.trim();
setTimeout(() => {
launchScreenElement.parentElement?.removeChild(launchScreenElement);
}, parseAnimationDuration(durationFromCss));
});
};
export const renderLaunchScreenInfoBox = (content: TemplateResult) => {

146
yarn.lock
View File

@@ -4945,106 +4945,106 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/eslint-plugin@npm:8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/eslint-plugin@npm:8.46.3"
"@typescript-eslint/eslint-plugin@npm:8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/eslint-plugin@npm:8.46.4"
dependencies:
"@eslint-community/regexpp": "npm:^4.10.0"
"@typescript-eslint/scope-manager": "npm:8.46.3"
"@typescript-eslint/type-utils": "npm:8.46.3"
"@typescript-eslint/utils": "npm:8.46.3"
"@typescript-eslint/visitor-keys": "npm:8.46.3"
"@typescript-eslint/scope-manager": "npm:8.46.4"
"@typescript-eslint/type-utils": "npm:8.46.4"
"@typescript-eslint/utils": "npm:8.46.4"
"@typescript-eslint/visitor-keys": "npm:8.46.4"
graphemer: "npm:^1.4.0"
ignore: "npm:^7.0.0"
natural-compare: "npm:^1.4.0"
ts-api-utils: "npm:^2.1.0"
peerDependencies:
"@typescript-eslint/parser": ^8.46.3
"@typescript-eslint/parser": ^8.46.4
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/0c1eb81a43f1d04fdd79c4e59f9f0687b86735ae6c98d94fe5eb021da2f83e0e2426a2922fe94296fb0a9ab131d53fe4cde8b54d0948d7b23e01e648a318bd1c
checksum: 10/5ae705d9dbf8cdeaf8cc2198cbfa1c3b70d5bf2fd20b5870448b53e9fe2f5a0d106162850aabd97897d250ec6fe7cebbb3f7ea2b6aa7ca9582b9b1b9e3be459f
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/parser@npm:8.46.3"
"@typescript-eslint/parser@npm:8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/parser@npm:8.46.4"
dependencies:
"@typescript-eslint/scope-manager": "npm:8.46.3"
"@typescript-eslint/types": "npm:8.46.3"
"@typescript-eslint/typescript-estree": "npm:8.46.3"
"@typescript-eslint/visitor-keys": "npm:8.46.3"
"@typescript-eslint/scope-manager": "npm:8.46.4"
"@typescript-eslint/types": "npm:8.46.4"
"@typescript-eslint/typescript-estree": "npm:8.46.4"
"@typescript-eslint/visitor-keys": "npm:8.46.4"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/d36edeba9ce37d219115fb101a4496bca2685969b217d0f64c0c255867a8793a8b41a95b86e26775a09b3abbb7c5b93ef712ea9a0fba3d055dcf385b17825075
checksum: 10/560635f5567dba6342cea2146051e5647dbc48f5fb7b0a7a6d577cada06d43e07030bb3999f90f6cd01d5b0fdb25d829a25252c84cf7a685c5c9373e6e1e4a73
languageName: node
linkType: hard
"@typescript-eslint/project-service@npm:8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/project-service@npm:8.46.3"
"@typescript-eslint/project-service@npm:8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/project-service@npm:8.46.4"
dependencies:
"@typescript-eslint/tsconfig-utils": "npm:^8.46.3"
"@typescript-eslint/types": "npm:^8.46.3"
"@typescript-eslint/tsconfig-utils": "npm:^8.46.4"
"@typescript-eslint/types": "npm:^8.46.4"
debug: "npm:^4.3.4"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10/2f041dfc664209b6a213cf585df28d0913ddf81916b83119c897a10dd9ad20dcd0ee3c523ee95440f498da6ba9d6e50cf08852418c0a2ebddd92c7a7cd295736
checksum: 10/f145da5f0c063833f48d36f2c3a19a37e2fb77156f0cc7046ee15f2e59418309b95628c8e7216e4429fac9f1257fab945c5d3f5abfd8f924223d36125c633d32
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/scope-manager@npm:8.46.3"
"@typescript-eslint/scope-manager@npm:8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/scope-manager@npm:8.46.4"
dependencies:
"@typescript-eslint/types": "npm:8.46.3"
"@typescript-eslint/visitor-keys": "npm:8.46.3"
checksum: 10/6bb6c3210bfcca59cf60860b51bfae8d28b01d074a8608b6f24b3290952ff74103e08d390d11cbf613812fca04aa55ad14ad9da04c3041e23acdca235ab1ff78
"@typescript-eslint/types": "npm:8.46.4"
"@typescript-eslint/visitor-keys": "npm:8.46.4"
checksum: 10/1439ffc1458281282c1ae3aabbe89140ce15c796d4f1c59f0de38e8536803e10143fe322a7e1cb56fe41da9e4617898d70923b71621b47cff4472aa5dae88d7e
languageName: node
linkType: hard
"@typescript-eslint/tsconfig-utils@npm:8.46.3, @typescript-eslint/tsconfig-utils@npm:^8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/tsconfig-utils@npm:8.46.3"
"@typescript-eslint/tsconfig-utils@npm:8.46.4, @typescript-eslint/tsconfig-utils@npm:^8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/tsconfig-utils@npm:8.46.4"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10/e7a16eadf79483d4b61dee56a08d032bafe26d44d634e7863a5875dbb44393570896641272a4e9810f4eac76a4109f59ad667b036d7627ef1647dc672ea19c5e
checksum: 10/eda25b1daee6abf51ee2dd5fc1dc1a5160a14301c0e7bed301ec5eb0f7b45418d509c035361f88a37f4af9771d7334f1dcb9bc7f7a38f07b09e85d4d9d92767f
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/type-utils@npm:8.46.3"
"@typescript-eslint/type-utils@npm:8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/type-utils@npm:8.46.4"
dependencies:
"@typescript-eslint/types": "npm:8.46.3"
"@typescript-eslint/typescript-estree": "npm:8.46.3"
"@typescript-eslint/utils": "npm:8.46.3"
"@typescript-eslint/types": "npm:8.46.4"
"@typescript-eslint/typescript-estree": "npm:8.46.4"
"@typescript-eslint/utils": "npm:8.46.4"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^2.1.0"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/b29cd001c715033ec9cd5fdf2723915f1b4c6c9342283ed00d20e4b942117625facba9a2cf3914b06633c2af9a167430f8f134323627adb0be85f73da4e89d72
checksum: 10/438188d4db8889b1299df60e03be76bbbcfad6500cbdbaad83250bc3671d6d798d3eef01417dd2b4236334ed11e466b90a75d17c0d5b94b667b362ce746dd3e6
languageName: node
linkType: hard
"@typescript-eslint/types@npm:8.46.3, @typescript-eslint/types@npm:^8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/types@npm:8.46.3"
checksum: 10/3de35df2ec2f2937c8f6eb262cd49f34500a18d01e0d8da6f348afd621f6c222c41d4ea15203ebbf0bd59814aa2b4c83fde7eb6d4aad1fa1514ee7a742887c6a
"@typescript-eslint/types@npm:8.46.4, @typescript-eslint/types@npm:^8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/types@npm:8.46.4"
checksum: 10/dd71692722254308f7954ade97800c141ec4a2bbdeef334df4ef9a5ee00db4597db4c3d0783607fc61c22238c9c534803a5421fe0856033a635e13fbe99b3cf0
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/typescript-estree@npm:8.46.3"
"@typescript-eslint/typescript-estree@npm:8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/typescript-estree@npm:8.46.4"
dependencies:
"@typescript-eslint/project-service": "npm:8.46.3"
"@typescript-eslint/tsconfig-utils": "npm:8.46.3"
"@typescript-eslint/types": "npm:8.46.3"
"@typescript-eslint/visitor-keys": "npm:8.46.3"
"@typescript-eslint/project-service": "npm:8.46.4"
"@typescript-eslint/tsconfig-utils": "npm:8.46.4"
"@typescript-eslint/types": "npm:8.46.4"
"@typescript-eslint/visitor-keys": "npm:8.46.4"
debug: "npm:^4.3.4"
fast-glob: "npm:^3.3.2"
is-glob: "npm:^4.0.3"
@@ -5053,32 +5053,32 @@ __metadata:
ts-api-utils: "npm:^2.1.0"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10/b55cf72fe3dff0b9bdf9b1793e43fdb2789fa6d706ba7d69fb94801bea82041056a95659bd8fe1e6f026787b2e8d0f8d060149841095a0a82044e3469b8d82cd
checksum: 10/2a932bdd7ac260e2b7290c952241bf06b2ddbeb3cf636bc624a64a9cfb046619620172a1967f30dbde6ac5f4fbdcfec66e1349af46313da86e01b5575dfebe2e
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/utils@npm:8.46.3"
"@typescript-eslint/utils@npm:8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/utils@npm:8.46.4"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.7.0"
"@typescript-eslint/scope-manager": "npm:8.46.3"
"@typescript-eslint/types": "npm:8.46.3"
"@typescript-eslint/typescript-estree": "npm:8.46.3"
"@typescript-eslint/scope-manager": "npm:8.46.4"
"@typescript-eslint/types": "npm:8.46.4"
"@typescript-eslint/typescript-estree": "npm:8.46.4"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/369c962bc20a2a6022ef4533ad55ab4e3d2403e7e200505b29fae6f0b8fc99be8fe149d929781f5ead0d3f88f2c74904f60aaa3771e6773e2b7dd8f61f07a534
checksum: 10/8e11abb2e44b6e62ccf8fd9b96808cb58e68788564fa999f15b61c0ec929209ced7f92a57ffbfcaec80f926aa14dafcee756755b724ae543b4cbd84b0ffb890d
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:8.46.3":
version: 8.46.3
resolution: "@typescript-eslint/visitor-keys@npm:8.46.3"
"@typescript-eslint/visitor-keys@npm:8.46.4":
version: 8.46.4
resolution: "@typescript-eslint/visitor-keys@npm:8.46.4"
dependencies:
"@typescript-eslint/types": "npm:8.46.3"
"@typescript-eslint/types": "npm:8.46.4"
eslint-visitor-keys: "npm:^4.2.1"
checksum: 10/02659a4cc4780d677907ed7e356e18b941e0ed18883acfda0d74d3e388144f90aa098b8fcdc2f4c01e9e6b60ac6154d1afb009feb6169c483260a5c8b4891171
checksum: 10/bcf479fa5c59857cf7aa7b90d9c00e23f7303473b94a401cc3b64776ebb66978b5342459a1672581dcf1861fa5961bb59c901fe766c28b6bc3f93e60bfc34dae
languageName: node
linkType: hard
@@ -9373,7 +9373,7 @@ __metadata:
tinykeys: "npm:3.0.0"
ts-lit-plugin: "npm:2.0.2"
typescript: "npm:5.9.3"
typescript-eslint: "npm:8.46.3"
typescript-eslint: "npm:8.46.4"
ua-parser-js: "npm:2.0.6"
vite-tsconfig-paths: "npm:5.1.4"
vitest: "npm:4.0.8"
@@ -14295,18 +14295,18 @@ __metadata:
languageName: node
linkType: hard
"typescript-eslint@npm:8.46.3":
version: 8.46.3
resolution: "typescript-eslint@npm:8.46.3"
"typescript-eslint@npm:8.46.4":
version: 8.46.4
resolution: "typescript-eslint@npm:8.46.4"
dependencies:
"@typescript-eslint/eslint-plugin": "npm:8.46.3"
"@typescript-eslint/parser": "npm:8.46.3"
"@typescript-eslint/typescript-estree": "npm:8.46.3"
"@typescript-eslint/utils": "npm:8.46.3"
"@typescript-eslint/eslint-plugin": "npm:8.46.4"
"@typescript-eslint/parser": "npm:8.46.4"
"@typescript-eslint/typescript-estree": "npm:8.46.4"
"@typescript-eslint/utils": "npm:8.46.4"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/2f77eb70c8fd6ec4920d5abf828ef28007df8ff94605246a4ca918fadb996a83f7fb82510a1de69fad7f0159ee8f15246d467ebc42df20a4585919cb6b401715
checksum: 10/6d28371033653395f1108d880f32ed5b03c15d94a4ca7564b81cdb5c563fa618b48cbcb6c00f3341e3399b27711feb1073305b425a22de23786a87c6a3a19ccd
languageName: node
linkType: hard