Compare commits

..

1 Commits

Author SHA1 Message Date
Erik e1dff6ad30 Add preview for time_date integration 2024-01-02 22:04:25 +01:00
25 changed files with 337 additions and 398 deletions
+6 -6
View File
@@ -81,8 +81,8 @@
"@material/mwc-top-app-bar-fixed": "0.27.0",
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",
"@material/web": "=1.1.1",
"@mdi/js": "7.4.47",
"@mdi/svg": "7.4.47",
"@mdi/js": "7.3.67",
"@mdi/svg": "7.3.67",
"@polymer/paper-input": "3.2.1",
"@polymer/paper-item": "3.0.1",
"@polymer/paper-listbox": "3.0.1",
@@ -190,7 +190,7 @@
"@web/dev-server-rollup": "0.4.1",
"babel-loader": "9.1.3",
"babel-plugin-template-html-minifier": "4.1.0",
"chai": "5.0.0",
"chai": "4.3.10",
"del": "7.1.0",
"eslint": "8.56.0",
"eslint-config-airbnb-base": "15.0.0",
@@ -223,19 +223,19 @@
"map-stream": "0.0.7",
"mocha": "10.2.0",
"object-hash": "3.0.0",
"open": "10.0.2",
"open": "10.0.1",
"pinst": "3.0.0",
"prettier": "3.1.1",
"rollup": "2.79.1",
"rollup-plugin-string": "3.0.0",
"rollup-plugin-terser": "7.0.2",
"rollup-plugin-visualizer": "5.12.0",
"rollup-plugin-visualizer": "5.11.0",
"serve-handler": "6.1.5",
"sinon": "17.0.1",
"source-map-url": "0.4.1",
"systemjs": "6.14.2",
"tar": "6.2.0",
"terser-webpack-plugin": "5.3.10",
"terser-webpack-plugin": "5.3.9",
"ts-lit-plugin": "2.0.1",
"typescript": "5.3.3",
"vinyl-buffer": "1.0.1",
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20240103.1"
version = "20231228.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"
-4
View File
@@ -29,7 +29,6 @@ import {
mdiFlash,
mdiFlower,
mdiFormatListBulleted,
mdiFormatListCheckbox,
mdiFormTextbox,
mdiGauge,
mdiGoogleAssistant,
@@ -65,7 +64,6 @@ import {
mdiTransmissionTower,
mdiWater,
mdiWaterPercent,
mdiWeatherPartlyCloudy,
mdiWeatherPouring,
mdiWeatherRainy,
mdiWeatherWindy,
@@ -130,7 +128,6 @@ export const FIXED_DOMAIN_ICONS = {
updater: mdiCloudUpload,
vacuum: mdiRobotVacuum,
wake_word: mdiChatSleep,
weather: mdiWeatherPartlyCloudy,
zone: mdiMapMarkerRadius,
};
@@ -169,7 +166,6 @@ export const FIXED_DEVICE_CLASS_ICONS = {
precipitation_intensity: mdiWeatherPouring,
pressure: mdiGauge,
reactive_power: mdiFlash,
shopping_List: mdiFormatListCheckbox,
signal_strength: mdiWifi,
sound_pressure: mdiEarHearing,
speed: mdiSpeedometer,
+2 -16
View File
@@ -18,8 +18,7 @@ export interface datePickerDialogParams {
max?: string;
locale?: string;
firstWeekday?: number;
canClear?: boolean;
onChange: (value: string | undefined) => void;
onChange: (value: string) => void;
}
const showDatePickerDialog = (
@@ -50,8 +49,6 @@ export class HaDateInput extends LitElement {
@property() public helper?: string;
@property({ type: Boolean }) public canClear?: boolean;
render() {
return html`<ha-textfield
.label=${this.label}
@@ -61,7 +58,6 @@ export class HaDateInput extends LitElement {
helperPersistent
readonly
@click=${this._openDialog}
@keydown=${this._keyDown}
.value=${this.value
? formatDateNumeric(
new Date(`${this.value.split("T")[0]}T00:00:00`),
@@ -86,23 +82,13 @@ export class HaDateInput extends LitElement {
min: this.min || "1970-01-01",
max: this.max,
value: this.value,
canClear: this.canClear,
onChange: (value) => this._valueChanged(value),
locale: this.locale.language,
firstWeekday: firstWeekdayIndex(this.locale),
});
}
private _keyDown(ev: KeyboardEvent) {
if (!this.canClear) {
return;
}
if (["Backspace", "Delete"].includes(ev.key)) {
this._valueChanged(undefined);
}
}
private _valueChanged(value: string | undefined) {
private _valueChanged(value: string) {
if (this.value !== value) {
this.value = value;
fireEvent(this, "change");
-14
View File
@@ -50,15 +50,6 @@ export class HaDialogDatePicker extends LitElement {
@datepicker-value-updated=${this._valueChanged}
.firstDayOfWeek=${this._params.firstWeekday}
></app-datepicker>
${this._params.canClear
? html`<mwc-button
slot="secondaryAction"
@click=${this._clear}
class="warning"
>
${this.hass.localize("ui.dialogs.date-picker.clear")}
</mwc-button>`
: nothing}
<mwc-button slot="secondaryAction" @click=${this._setToday}>
${this.hass.localize("ui.dialogs.date-picker.today")}
</mwc-button>
@@ -75,11 +66,6 @@ export class HaDialogDatePicker extends LitElement {
this._value = ev.detail.value;
}
private _clear() {
this._params?.onChange(undefined);
this.closeDialog();
}
private _setToday() {
const today = new Date();
this._value = format(today, "yyyy-MM-dd");
+2 -2
View File
@@ -10,9 +10,9 @@ class HaLabeledSlider extends LitElement {
@property() public caption?: string;
@property({ type: Boolean }) public disabled = false;
@property() public disabled?: boolean;
@property({ type: Boolean }) public required = true;
@property() public required?: boolean;
@property() public min: number = 0;
+7 -21
View File
@@ -4,14 +4,7 @@ import {
HassServices,
HassServiceTarget,
} from "home-assistant-js-websocket";
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
nothing,
} from "lit";
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { ensureArray } from "../common/array/ensure-array";
@@ -90,8 +83,6 @@ export class HaServiceControl extends LitElement {
@property({ type: Boolean }) public showAdvanced?: boolean;
@property({ type: Boolean, reflect: true }) public hidePicker?: boolean;
@state() private _value!: this["value"];
@state() private _checkedKeys = new Set();
@@ -372,14 +363,12 @@ export class HaServiceControl extends LitElement {
)) ||
serviceData?.description;
return html`${this.hidePicker
? nothing
: html`<ha-service-picker
.hass=${this.hass}
.value=${this._value?.service}
.disabled=${this.disabled}
@value-changed=${this._serviceChanged}
></ha-service-picker>`}
return html`<ha-service-picker
.hass=${this.hass}
.value=${this._value?.service}
.disabled=${this.disabled}
@value-changed=${this._serviceChanged}
></ha-service-picker>
<div class="description">
${description ? html`<p>${description}</p>` : ""}
${this._manifest
@@ -746,9 +735,6 @@ export class HaServiceControl extends LitElement {
margin: var(--service-control-padding, 0 16px);
padding: 16px 0;
}
:host([hidePicker]) p {
padding-top: 0;
}
.checkbox-spacer {
width: 32px;
}
+3 -11
View File
@@ -133,7 +133,7 @@ export class HaTracePathDetails extends LitElement {
if (result?.enabled === false) {
return html`${this.hass!.localize(
"ui.panel.config.automation.trace.path.disabled_step"
"ui.panel.config.automation.trace.path.disabled_node"
)}`;
}
@@ -208,19 +208,11 @@ export class HaTracePathDetails extends LitElement {
const paths = this.trace.trace;
const data: ActionTraceStep[] = paths[this.selected.path];
if (data === undefined) {
return html`<div class="padded-box">
${this.hass!.localize(
"ui.panel.config.automation.trace.path.step_not_executed"
)}
</div>`;
}
return html`
<div class="padded-box">
${data.map(
(trace, idx) => html`
${data.length > 1
${idx > 0
? html`<p>
${this.hass!.localize(
"ui.panel.config.automation.trace.path.iteration",
@@ -248,7 +240,7 @@ export class HaTracePathDetails extends LitElement {
if (index === -1) {
return html`<div class="padded-box">
${this.hass!.localize(
"ui.panel.config.automation.trace.path.step_not_executed"
"ui.panel.config.automation.trace.path.node_not_tracked"
)}
</div>`;
}
-2
View File
@@ -52,7 +52,6 @@ export const serviceActionStruct: Describe<ServiceAction> = assign(
target: optional(targetStruct),
data: optional(object()),
response_variable: optional(string()),
metadata: optional(object()),
})
);
@@ -134,7 +133,6 @@ export interface ServiceAction extends BaseAction {
target?: HassServiceTarget;
data?: Record<string, unknown>;
response_variable?: string;
metadata?: Record<string, unknown>;
}
export interface DeviceAction extends BaseAction {
+1 -15
View File
@@ -168,18 +168,6 @@ const tryDescribeAction = <T extends ActionType>(
const service =
hass.localize(`component.${domain}.services.${serviceName}.name`) ||
hass.services[domain][serviceName]?.name;
if (config.metadata) {
return hass.localize(
`${actionTranslationBaseKey}.service.description.service_name`,
{
domain: domainToName(hass.localize, domain),
name: service || config.service,
targets: formatListWithAnds(hass.locale, targets),
}
);
}
return hass.localize(
`${actionTranslationBaseKey}.service.description.service_based_on_name`,
{
@@ -416,9 +404,7 @@ const tryDescribeAction = <T extends ActionType>(
if (actionType === "device_action") {
const config = action as DeviceAction;
if (!config.device_id) {
return hass.localize(
`${actionTranslationBaseKey}.device_id.description.no_device`
);
return "Device action";
}
const localized = localizeDeviceAutomationAction(
hass,
+25
View File
@@ -0,0 +1,25 @@
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { HomeAssistant } from "../types";
export interface TimeDatePreview {
items: [
{
state: string;
attributes: Record<string, any>;
},
];
}
export const subscribePreviewTimeDate = (
hass: HomeAssistant,
flow_id: string,
flow_type: "config_flow" | "options_flow",
user_input: Record<string, any>,
callback: (preview: TimeDatePreview) => void
): Promise<UnsubscribeFunc> =>
hass.connection.subscribeMessage(callback, {
type: "time_date/start_preview",
flow_id,
flow_type,
user_input,
});
+4 -4
View File
@@ -18,8 +18,8 @@ export interface TodoItem {
uid: string;
summary: string;
status: TodoItemStatus;
description?: string | null;
due?: string | null;
description?: string;
due?: string;
}
export const enum TodoListEntityFeature {
@@ -83,9 +83,9 @@ export const updateItem = (
item: item.uid,
rename: item.summary,
status: item.status,
description: item.description || null,
description: item.description || undefined,
due_datetime: item.due?.includes("T") ? item.due : undefined,
due_date: item.due?.includes("T") ? undefined : item.due || null,
due_date: item.due?.includes("T") ? undefined : item.due || undefined,
},
{ entity_id }
);
@@ -0,0 +1,97 @@
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
import { LitElement, html } from "lit";
import { customElement, property, state } from "lit/decorators";
import { FlowType } from "../../../data/data_entry_flow";
import {
TimeDatePreview,
subscribePreviewTimeDate,
} from "../../../data/time_date";
import { HomeAssistant } from "../../../types";
import "./entity-preview-row";
import { debounce } from "../../../common/util/debounce";
@customElement("flow-preview-time_date")
class FlowPreviewTimeDate extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() public flowType!: FlowType;
public handler!: string;
@property() public stepId!: string;
@property() public flowId!: string;
@property() public stepData!: Record<string, any>;
@state() private _preview_items?: HassEntity[];
private _unsub?: Promise<UnsubscribeFunc>;
disconnectedCallback(): void {
super.disconnectedCallback();
if (this._unsub) {
this._unsub.then((unsub) => unsub());
this._unsub = undefined;
}
}
willUpdate(changedProps) {
if (changedProps.has("stepData")) {
this._debouncedSubscribePreview();
}
}
protected render() {
return html`${this._preview_items?.map(
(item) =>
html`<entity-preview-row
.hass=${this.hass}
.stateObj=${item}
></entity-preview-row>`
)}`;
}
private _setPreview = (preview: TimeDatePreview) => {
const now = new Date().toISOString();
this._preview_items = preview.items.map((item) => ({
entity_id: `${this.stepId}.___flow_preview___`,
last_changed: now,
last_updated: now,
context: { id: "", parent_id: null, user_id: null },
...item,
}));
};
private _debouncedSubscribePreview = debounce(() => {
this._subscribePreview();
}, 250);
private async _subscribePreview() {
this._preview_items = undefined;
if (this._unsub) {
(await this._unsub)();
this._unsub = undefined;
}
if (this.flowType === "repair_flow") {
return;
}
try {
this._unsub = subscribePreviewTimeDate(
this.hass,
this.flowId,
this.flowType,
this.stepData,
this._setPreview
);
} catch (err) {
this._preview_items = undefined;
}
}
}
declare global {
interface HTMLElementTagNameMap {
"flow-preview-time_date": FlowPreviewTimeDate;
}
}
@@ -144,9 +144,9 @@ class DialogCalendarEventEditor extends LitElement {
escapeKeyAction
.heading=${createCloseHeading(
this.hass,
this.hass.localize(
`ui.components.calendar.event.${isCreate ? "add" : "edit"}`
)
isCreate
? this.hass.localize("ui.components.calendar.event.add")
: this._summary
)}
>
<div class="content">
@@ -29,8 +29,6 @@ import { classMap } from "lit/directives/class-map";
import { storage } from "../../../../common/decorators/storage";
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../../../common/dom/fire_event";
import { computeDomain } from "../../../../common/entity/compute_domain";
import { domainIconWithoutDefault } from "../../../../common/entity/domain_icon";
import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter";
import { handleStructError } from "../../../../common/structs/handle-errors";
import "../../../../components/ha-alert";
@@ -192,13 +190,7 @@ export default class HaAutomationActionRow extends LitElement {
<h3 slot="header">
<ha-svg-icon
class="action-icon"
.path=${type === "service" &&
"service" in this.action &&
this.action.service
? domainIconWithoutDefault(
computeDomain(this.action.service as string)
) || ACTION_ICONS[type!]
: ACTION_ICONS[type!]}
.path=${ACTION_ICONS[type!]}
></ha-svg-icon>
${capitalizeFirstLetter(
describeAction(this.hass, this._entityReg, this.action)
@@ -191,7 +191,6 @@ export default class HaAutomationAction extends LitElement {
} else if (isService(action)) {
actions = this.actions.concat({
service: getService(action),
metadata: {},
});
} else {
const elClass = customElements.get(
@@ -1,4 +1,4 @@
import { css, CSSResultGroup, html, LitElement } from "lit";
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../../common/dom/fire_event";
@@ -9,10 +9,10 @@ import type { HomeAssistant } from "../../../../../types";
import "../ha-automation-action";
import type { ActionElement } from "../ha-automation-action-row";
import { isTemplate } from "../../../../../common/string/has-template";
import type { LocalizeFunc } from "../../../../../common/translations/localize";
import "../../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../../components/ha-form/types";
import { hasTemplate } from "../../../../../common/string/has-template";
const OPTIONS = ["count", "while", "until", "for_each"] as const;
@@ -32,13 +32,22 @@ export class HaRepeatAction extends LitElement implements ActionElement {
return { repeat: { count: 2, sequence: [] } };
}
public willUpdate(changedProperties: PropertyValues) {
if (!changedProperties.has("action")) {
return;
}
// Check for templates in action. If found, revert to YAML mode.
if (this.action && hasTemplate(this.action)) {
fireEvent(
this,
"ui-mode-not-available",
Error(this.hass.localize("ui.errors.config.no_template_editor_support"))
);
}
}
private _schema = memoizeOne(
(
localize: LocalizeFunc,
type: string,
reOrderMode: boolean,
template: boolean
) =>
(localize: LocalizeFunc, type: string, reOrderMode: boolean) =>
[
{
name: "type",
@@ -59,9 +68,7 @@ export class HaRepeatAction extends LitElement implements ActionElement {
{
name: "count",
required: true,
selector: template
? ({ template: {} } as const)
: ({ number: { mode: "box", min: 1 } } as const),
selector: { number: { mode: "box", min: 1 } },
},
] as const)
: []),
@@ -97,10 +104,7 @@ export class HaRepeatAction extends LitElement implements ActionElement {
const schema = this._schema(
this.hass.localize,
type ?? "count",
this.reOrderMode,
"count" in action && typeof action.count === "string"
? isTemplate(action.count)
: false
this.reOrderMode
);
const data = { ...action, type };
return html`<ha-form
@@ -1,21 +1,14 @@
import "@material/mwc-list/mwc-list";
import { mdiClose, mdiContentPaste, mdiPlus } from "@mdi/js";
import Fuse, { IFuseOptions } from "fuse.js";
import {
CSSResultGroup,
LitElement,
PropertyValues,
css,
html,
nothing,
} from "lit";
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { repeat } from "lit/directives/repeat";
import { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event";
import { domainIconWithoutDefault } from "../../../common/entity/domain_icon";
import { domainIcon } from "../../../common/entity/domain_icon";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import { stringCompare } from "../../../common/string/compare";
import { LocalizeFunc } from "../../../common/translations/localize";
@@ -45,13 +38,10 @@ import { TRIGGER_GROUPS, TRIGGER_ICONS } from "../../../data/trigger";
import { HassDialog } from "../../../dialogs/make-dialog-manager";
import { haStyle, haStyleDialog } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import { brandsUrl } from "../../../util/brands-url";
import {
AddAutomationElementDialogParams,
PASTE_VALUE,
} from "./show-add-automation-element-dialog";
import { computeDomain } from "../../../common/entity/compute_domain";
import { deepEqual } from "../../../common/util/deep-equal";
const TYPES = {
trigger: { groups: TRIGGER_GROUPS, icons: TRIGGER_ICONS },
@@ -69,8 +59,7 @@ interface ListItem {
key: string;
name: string;
description: string;
icon?: string;
image?: string;
icon: string;
group: boolean;
}
@@ -90,8 +79,6 @@ const ENTITY_DOMAINS_OTHER = new Set([
"image_processing",
]);
const ENTITY_DOMAINS_MAIN = new Set(["notify"]);
@customElement("add-automation-element-dialog")
class DialogAddAutomationElement extends LitElement implements HassDialog {
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -106,15 +93,13 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
@state() private _manifests?: DomainManifestLookup;
@state() private _domains?: Set<string>;
@query("ha-dialog") private _dialog?: HaDialog;
private _fullScreen = false;
@state() private _width?: number;
private _width?: number;
@state() private _height?: number;
private _height?: number;
public showDialog(params): void {
this._params = params;
@@ -122,7 +107,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
if (this._params?.type === "action") {
this.hass.loadBackendTranslation("services");
this._fetchManifests();
this._calculateUsedDomains();
}
this._fullScreen = matchMedia(
"all and (max-width: 450px), all and (max-height: 500px)"
@@ -140,19 +124,8 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
this._prev = undefined;
this._filter = "";
this._manifests = undefined;
this._domains = undefined;
}
private _getGroups = (
type: AddAutomationElementDialogParams["type"],
group: string | undefined
): AutomationElementGroup =>
group
? isService(group)
? {}
: TYPES[type].groups[group].members!
: TYPES[type].groups;
private _convertToItem = (
key: string,
options,
@@ -185,7 +158,11 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
services: HomeAssistant["services"],
manifests?: DomainManifestLookup
): ListItem[] => {
const groups = this._getGroups(type, group);
const groups: AutomationElementGroup = group
? isService(group)
? {}
: TYPES[type].groups[group].members!
: TYPES[type].groups;
const flattenGroups = (grp: AutomationElementGroup) =>
Object.entries(grp).map(([key, options]) =>
@@ -215,23 +192,21 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
(
type: AddAutomationElementDialogParams["type"],
group: string | undefined,
domains: Set<string> | undefined,
localize: LocalizeFunc,
services: HomeAssistant["services"],
manifests?: DomainManifestLookup
): ListItem[] => {
if (type === "action" && isService(group)) {
let result = this._services(localize, services, manifests, group);
const result = this._services(localize, services, manifests, group);
if (group === `${SERVICE_PREFIX}media_player`) {
result = [
this._convertToItem("play_media", {}, type, localize),
...result,
];
result.unshift(this._convertToItem("play_media", {}, type, localize));
}
return result;
}
const groups = this._getGroups(type, group);
const groups: AutomationElementGroup = group
? TYPES[type].groups[group].members!
: TYPES[type].groups;
const result = Object.entries(groups).map(([key, options]) =>
this._convertToItem(key, options, type, localize)
@@ -240,33 +215,15 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
if (type === "action") {
if (!this._group) {
result.unshift(
...this._serviceGroups(
localize,
services,
manifests,
domains,
undefined
)
...this._serviceGroups(localize, services, manifests, undefined)
);
} else if (this._group === "helpers") {
result.unshift(
...this._serviceGroups(
localize,
services,
manifests,
domains,
"helper"
)
...this._serviceGroups(localize, services, manifests, "helper")
);
} else if (this._group === "other") {
result.unshift(
...this._serviceGroups(
localize,
services,
manifests,
domains,
"other"
)
...this._serviceGroups(localize, services, manifests, "other")
);
}
}
@@ -286,54 +243,44 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
}
);
private _serviceGroups = (
localize: LocalizeFunc,
services: HomeAssistant["services"],
manifests: DomainManifestLookup | undefined,
domains: Set<string> | undefined,
type: "helper" | "other" | undefined
): ListItem[] => {
if (!services || !manifests) {
return [];
}
const result: ListItem[] = [];
Object.keys(services).forEach((domain) => {
const manifest = manifests[domain];
const domainUsed = !domains ? true : domains.has(domain);
if (
(type === undefined &&
(ENTITY_DOMAINS_MAIN.has(domain) ||
(manifest?.integration_type === "entity" &&
domainUsed &&
!ENTITY_DOMAINS_OTHER.has(domain)))) ||
(type === "helper" && manifest?.integration_type === "helper") ||
(type === "other" &&
!ENTITY_DOMAINS_MAIN.has(domain) &&
(ENTITY_DOMAINS_OTHER.has(domain) ||
(!domainUsed && manifest?.integration_type === "entity") ||
!["helper", "entity"].includes(manifest?.integration_type || "")))
) {
const icon = domainIconWithoutDefault(domain);
result.push({
group: true,
icon,
image: !icon
? brandsUrl({
domain,
type: "icon",
darkOptimized: this.hass.themes?.darkMode,
})
: undefined,
key: `${SERVICE_PREFIX}${domain}`,
name: domainToName(localize, domain, manifest),
description: "",
});
private _serviceGroups = memoizeOne(
(
localize: LocalizeFunc,
services: HomeAssistant["services"],
manifests: DomainManifestLookup | undefined,
type: "helper" | "other" | undefined
): ListItem[] => {
if (!services || !manifests) {
return [];
}
});
return result.sort((a, b) =>
stringCompare(a.name, b.name, this.hass.locale.language)
);
};
const result: ListItem[] = [];
Object.keys(services)
.sort()
.forEach((domain) => {
const manifest = manifests[domain];
if (
(type === undefined &&
manifest?.integration_type === "entity" &&
!ENTITY_DOMAINS_OTHER.has(domain)) ||
(type === "helper" && manifest?.integration_type === "helper") ||
(type === "other" &&
(ENTITY_DOMAINS_OTHER.has(domain) ||
!["helper", "entity"].includes(
manifest?.integration_type || ""
)))
) {
result.push({
group: true,
icon: domainIcon(domain),
key: `${SERVICE_PREFIX}${domain}`,
name: domainToName(localize, domain, manifest),
description: "",
});
}
});
return result;
}
);
private _services = memoizeOne(
(
@@ -357,17 +304,9 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
const services_keys = Object.keys(services[dmn]);
for (const service of services_keys) {
const icon = domainIconWithoutDefault(dmn);
result.push({
group: false,
icon,
image: !icon
? brandsUrl({
domain: dmn,
type: "icon",
darkOptimized: this.hass.themes?.darkMode,
})
: undefined,
icon: domainIcon(dmn),
key: `${SERVICE_PREFIX}${dmn}.${service}`,
name: `${domain ? "" : `${domainToName(localize, dmn)}: `}${
this.hass.localize(`component.${dmn}.services.${service}.name`) ||
@@ -423,13 +362,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
this._manifests = manifests;
}
private _calculateUsedDomains() {
const domains = new Set(Object.keys(this.hass.states).map(computeDomain));
if (!deepEqual(domains, this._domains)) {
this._domains = domains;
}
}
protected _opened(): void {
// Store the width and height so that when we search, box doesn't jump
const boundingRect =
@@ -438,16 +370,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
this._height = boundingRect?.height;
}
protected willUpdate(changedProperties: PropertyValues): void {
if (
this._params?.type === "action" &&
changedProperties.has("hass") &&
changedProperties.get("hass")?.states !== this.hass.states
) {
this._calculateUsedDomains();
}
}
protected render() {
if (!this._params) {
return nothing;
@@ -465,7 +387,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
: this._getGroupItems(
this._params.type,
this._group,
this._domains,
this.hass.localize,
this.hass.services,
this._manifests
@@ -578,18 +499,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
>
${item.name}
<span slot="secondary">${item.description}</span>
${item.icon
? html`<ha-svg-icon
slot="graphic"
.path=${item.icon}
></ha-svg-icon>`
: html`<img
alt=""
slot="graphic"
src=${item.image}
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>`}
<ha-svg-icon slot="graphic" .path=${item.icon}></ha-svg-icon>
${item.group
? html`<ha-icon-next slot="meta"></ha-icon-next>`
: html`<ha-svg-icon
@@ -605,7 +515,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
}
private _back() {
this._dialog!.scrollToPos(0, 0);
if (this._filter) {
this._filter = "";
return;
@@ -654,10 +563,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
ha-icon-next {
width: 24px;
}
mwc-list {
max-height: 468px;
max-width: 100vw;
}
search-input {
display: block;
margin: 0 16px;
@@ -168,7 +168,6 @@ export class HaDeviceCondition extends LitElement {
}
ha-form {
display: block;
margin-top: 24px;
}
`;
@@ -174,7 +174,6 @@ export class HaDeviceTrigger extends LitElement {
}
ha-form {
display: block;
margin-top: 24px;
}
`;
@@ -118,8 +118,6 @@ const OVERRIDE_DEVICE_CLASSES = {
"carbon_monoxide",
"moisture",
], // Alarm
["connectivity"], // Connectivity
["update"], // Update
],
};
@@ -340,9 +340,7 @@ class AddIntegrationDialog extends LitElement {
!("integrations" in integration) &&
!this._flowsInProgress?.length
) {
return this.hass.localize(
"ui.panel.config.integrations.what_device_type"
);
return "What type of device is it?";
}
if (
integration &&
@@ -350,11 +348,9 @@ class AddIntegrationDialog extends LitElement {
!("integrations" in integration) &&
this._flowsInProgress?.length
) {
return this.hass.localize(
"ui.panel.config.integrations.confirm_add_discovered"
);
return "Want to add these discovered devices?";
}
return this.hass.localize("ui.panel.config.integrations.what_to_add");
return "What do you want to add?";
}
private _renderIntegration(
+9 -14
View File
@@ -101,9 +101,9 @@ class DialogTodoItemEditor extends LitElement {
scrimClickAction
.heading=${createCloseHeading(
this.hass,
this.hass.localize(
`ui.components.todo.item.${isCreate ? "add" : "edit"}`
)
isCreate
? this.hass.localize("ui.components.todo.item.add")
: this._summary
)}
>
<div class="content">
@@ -161,8 +161,7 @@ class DialogTodoItemEditor extends LitElement {
.value=${dueDate}
.locale=${this.hass.locale}
.disabled=${!canUpdate}
@value-changed=${this._dueDateChanged}
canClear
@value-changed=${this._endDateChanged}
></ha-date-input>
${this._todoListSupportsFeature(
TodoListEntityFeature.SET_DUE_DATETIME_ON_ITEM
@@ -171,7 +170,7 @@ class DialogTodoItemEditor extends LitElement {
.value=${dueTime}
.locale=${this.hass.locale}
.disabled=${!canUpdate}
@value-changed=${this._dueTimeChanged}
@value-changed=${this._endTimeChanged}
></ha-time-input>`
: nothing}
</div>
@@ -260,16 +259,12 @@ class DialogTodoItemEditor extends LitElement {
this._description = ev.target.value;
}
private _dueDateChanged(ev: CustomEvent) {
if (!ev.detail.value) {
this._due = undefined;
return;
}
private _endDateChanged(ev: CustomEvent) {
const time = this._due ? this._formatTime(this._due) : undefined;
this._due = this._parseDate(`${ev.detail.value}${time ? `T${time}` : ""}`);
}
private _dueTimeChanged(ev: CustomEvent) {
private _endTimeChanged(ev: CustomEvent) {
this._hasTime = true;
this._due = this._parseDate(
`${this._formatDate(this._due || new Date())}T${ev.detail.value}`
@@ -325,13 +320,13 @@ class DialogTodoItemEditor extends LitElement {
TodoListEntityFeature.SET_DESCRIPTION_ON_ITEM
)
? // backend should accept null to clear the field, but it doesn't now
null
" "
: undefined),
due: this._due
? this._hasTime
? this._due.toISOString()
: this._formatDate(this._due)
: null,
: undefined,
status: this._checked
? TodoItemStatus.Completed
: TodoItemStatus.NeedsAction,
+25 -31
View File
@@ -1009,8 +1009,7 @@
"crop_image": "Picture to crop"
},
"date-picker": {
"today": "Today",
"clear": "Clear"
"today": "Today"
},
"more_info_control": {
"dismiss": "Dismiss dialog",
@@ -2492,13 +2491,13 @@
"groups": {
"entity": {
"label": "Entity",
"description": "When something happens to an entity."
"description": "When something happens to an entity"
},
"time_location": {
"label": "Time and location",
"description": "When someone enters or leaves a zone, or at a specific time."
},
"other": { "label": "Other triggers" }
"other": { "label": "Other" }
},
"type": {
"calendar": {
@@ -2534,7 +2533,7 @@
"context_user_picked": "User firing event",
"context_user_pick": "Select user",
"description": {
"picker": "When an event is being received (event is an advanced concept in Home Assistant).",
"picker": "When an event is being received (event is an advanced concept in Home Assistant)",
"full": "When {eventTypes} event is fired"
}
},
@@ -2546,7 +2545,7 @@
"enter": "Enter",
"leave": "Leave",
"description": {
"picker": "When an entity created by a geolocation platform appears in or disappears from a zone.",
"picker": "When an entity created by a geolocation platform appears in or disappears from a zone",
"full": "When {source} {event, select, \n enter {enters}\n leave {leaves} other {} \n} {zone} {numberOfZones, plural,\n one {zone}\n other {zones}\n}"
}
},
@@ -2608,7 +2607,7 @@
"updated": "updated"
},
"description": {
"picker": "When a persistent notification is added or removed.",
"picker": "When a persistent notification is added or removed",
"full": "When a persistent notification is updated"
}
},
@@ -2619,7 +2618,7 @@
"sunset": "Sunset",
"offset": "Offset (optional)",
"description": {
"picker": "When the sun sets or rises.",
"picker": "When the sun sets or rises",
"sets": "When the sun sets{hasDuration, select, \n true { offset by {duration}} \n other {}\n }",
"rises": "When the sun rises{hasDuration, select, \n true { offset by {duration}} \n other {}\n }"
}
@@ -2648,7 +2647,7 @@
"value_template": "Value template",
"for": "For",
"description": {
"picker": "When a template evaluates to true.",
"picker": "When a template is evaluated to true.",
"full": "When a template changes from false to true{hasDuration, select, \n true { for {duration}} \n other {}\n }"
}
},
@@ -2669,7 +2668,7 @@
"minutes": "Minutes",
"seconds": "Seconds",
"description": {
"picker": "Periodically, at a defined interval."
"picker": "Periodically, every defined interval of time."
}
},
"webhook": {
@@ -2692,7 +2691,7 @@
"enter": "Enter",
"leave": "Leave",
"description": {
"picker": "When someone (or something) enters or leaves a zone.",
"picker": "When someone (or something) enters or leaves a zone",
"full": "When {entity} {event, select, \n enter {enters}\n leave {leaves} other {} \n} {zone} {numberOfZones, plural,\n one {zone} \n other {zones}\n}"
}
}
@@ -2734,7 +2733,7 @@
"label": "Time and location",
"description": "If someone is in a zone or if the current time is before or after a specified time."
},
"other": { "label": "Other conditions" },
"other": { "label": "Other" },
"building_blocks": {
"label": "Building blocks",
"description": "Build more complex conditions."
@@ -2760,13 +2759,13 @@
"preset_mode": "Preset mode"
},
"description": {
"picker": "Set of conditions provided by your device. Great way to start."
"picker": "If a device is in a certain state. Great way to start."
}
},
"not": {
"label": "Not",
"description": {
"picker": "Test if a condition is not true.",
"picker": "Test if a condition is not true",
"no_conditions": "Test if no condition matches",
"one_condition": "Test if 1 condition does not match",
"full": "Test if none of {count} conditions match"
@@ -2800,7 +2799,7 @@
"label": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]",
"state": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]",
"description": {
"picker": "If an entity (or attribute) is in a specific state.",
"picker": "If an entity (or attribute) is in a specific state",
"no_entity": "Confirm state",
"full": "Confirm{hasAttribute, select, \n true { {attribute} of}\n other {}\n} {numberOfEntities, plural,\n zero {an entity is}\n one {{entities} is}\n other {{entities} are}\n} {numberOfStates, plural,\n zero {a state}\n other {{states}}\n}{hasDuration, select, \n true { for {duration}} \n other {}\n }"
}
@@ -2821,7 +2820,7 @@
"label": "[%key:ui::panel::config::automation::editor::triggers::type::template::label%]",
"value_template": "[%key:ui::panel::config::automation::editor::triggers::type::template::value_template%]",
"description": {
"picker": "If a template evaluates to true.",
"picker": "If a template is evaluated to true.",
"full": "Test if template renders a value equal to true"
}
},
@@ -2844,7 +2843,7 @@
"sun": "Sunday"
},
"description": {
"picker": "If the current time is before or after a specified time.",
"picker": "If the current time is before or after a specified time",
"full": "Confirm the {hasTime, select, \n after {time is after {time_after}}\n before {time is before {time_before}}\n after_before {time is after {time_after} and before {time_before}} \n other {}\n }{hasTimeAndDay, select, \n true { and the }\n other {}\n}{hasDay, select, \n true { day is {day}}\n other {}\n}"
}
},
@@ -2862,7 +2861,7 @@
"entity": "[%key:ui::panel::config::automation::editor::triggers::type::zone::entity%]",
"zone": "[%key:ui::panel::config::automation::editor::triggers::type::zone::label%]",
"description": {
"picker": "If someone (or something) is in a zone.",
"picker": "If someone (or something) is in a zone",
"full": "Confirm {entity} {numberOfEntities, plural,\n one {is}\n other {are}\n} in {zone} {numberOfZones, plural,\n one {zone} \n other {zones}\n} "
}
}
@@ -2899,7 +2898,7 @@
"continue_on_error": "Continue on error",
"groups": {
"helpers": { "label": "Helpers" },
"other": { "label": "Other actions" },
"other": { "label": "Other" },
"building_blocks": {
"label": "Building blocks",
"description": "Build more complex sequences of actions."
@@ -2914,7 +2913,6 @@
"description": {
"service_based_on_template": "Call a service based on a template on {targets}",
"service_based_on_name": "Call a service ''{name}'' on {targets}",
"service_name": "{domain} ''{name}'' on {targets}",
"service": "Call a service",
"target_template": "templated {name}",
"target_unknown_entity": "unknown entity",
@@ -2991,8 +2989,7 @@
"flash": "Flash"
},
"description": {
"picker": "Do something on a device. Great way to start.",
"no_device": "Device action"
"picker": "Do something on a device. Great way to start."
}
},
"activate_scene": {
@@ -3071,14 +3068,14 @@
"response_variable": "The name of the variable to use as response",
"error": "Stop because of an unexpected error",
"description": {
"picker": "Stop the sequence of actions.",
"picker": "Stop the sequence of actions",
"full": "Stop {hasReason, select, \n true { because: {reason}} \n other {}\n }"
}
},
"parallel": {
"label": "Run in parallel",
"description": {
"picker": "Perform a sequence of actions in parallel.",
"picker": "perform a sequence of actions in parallel.",
"full": "Run {number} {number, plural,\n one {action}\n other {actions}\n} in parallel"
}
},
@@ -3117,15 +3114,15 @@
"blueprint_config": "Blueprint Config"
},
"path": {
"choose": "Select a step on the left for more information.",
"choose": "Select a node on the left for more information.",
"default_action_executed": "The default action was executed because no options matched.",
"no_further_execution": "This step was not executed and so no further trace information is available.",
"disabled_step": "This step was disabled and skipped during execution so no further trace information is available.",
"no_further_execution": "This node was not executed and so no further trace information is available.",
"disabled_node": "This node was disabled and skipped during execution so no further trace information is available.",
"iteration": "Iteration {number}",
"executed": "Executed: {time}",
"error": "Error: {error}",
"result": "Result:",
"step_not_executed": "This step was not executed.",
"node_not_tracked": "Node not tracked.",
"no_logbook_entries": "No Logbook entries found for this step.",
"no_variables_changed": "No variables changed",
"unable_to_find_config": "Unable to find config"
@@ -3802,9 +3799,6 @@
"add_zwave_js_device": "Add Z-Wave device",
"add_zha_device": "Add Zigbee device",
"add_matter_device": "Add Matter device",
"what_device_type": "What type of device is it?",
"what_to_add": "What do you want to add?",
"confirm_add_discovered": "Want to add these discovered devices?",
"disable": {
"show_disabled": "Show disabled integrations",
"disabled_integrations": "{number} disabled",
+72 -66
View File
@@ -2043,7 +2043,7 @@ __metadata:
languageName: node
linkType: hard
"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.9":
"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9":
version: 0.3.20
resolution: "@jridgewell/trace-mapping@npm:0.3.20"
dependencies:
@@ -3146,17 +3146,17 @@ __metadata:
languageName: node
linkType: hard
"@mdi/js@npm:7.4.47":
version: 7.4.47
resolution: "@mdi/js@npm:7.4.47"
checksum: c1a8fc82f23030bccc0cf324b13b73a0034d06140e79f8bc7b0e4e59275624c470e5ca6524d6141ad8c4fe3ad0f314c7af99afb3e38df163eb50d3b13b9eab17
"@mdi/js@npm:7.3.67":
version: 7.3.67
resolution: "@mdi/js@npm:7.3.67"
checksum: 0f54a632d4ab3213931cc348d524f0f5e6b492ea74f8f1babe00298a8e7ae07b2fec88cfaf0cf7be0f1e427026a8da23fb8bed55b22892ad3b40b482e01cfb17
languageName: node
linkType: hard
"@mdi/svg@npm:7.4.47":
version: 7.4.47
resolution: "@mdi/svg@npm:7.4.47"
checksum: e5a6b80bb82cc7b7c98e9a018883aee1eaa0e98edfb62192e7ec5798fa573f30b9226629361d747de6e0a81fe6657fb37e9bc2fd89c68e9b094a07e863be4fba
"@mdi/svg@npm:7.3.67":
version: 7.3.67
resolution: "@mdi/svg@npm:7.3.67"
checksum: bd9593e6cc16d140b681dedacd2a164da7884186d496c89809a9389c980c295d16edf4ba8744338d28bb6e627b1801f47c4c0cbf7b8faf7084ee87cd5d7b4250
languageName: node
linkType: hard
@@ -5895,10 +5895,10 @@ __metadata:
languageName: node
linkType: hard
"assertion-error@npm:^2.0.1":
version: 2.0.1
resolution: "assertion-error@npm:2.0.1"
checksum: a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66
"assertion-error@npm:^1.1.0":
version: 1.1.0
resolution: "assertion-error@npm:1.1.0"
checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf
languageName: node
linkType: hard
@@ -6434,16 +6434,18 @@ __metadata:
languageName: node
linkType: hard
"chai@npm:5.0.0":
version: 5.0.0
resolution: "chai@npm:5.0.0"
"chai@npm:4.3.10":
version: 4.3.10
resolution: "chai@npm:4.3.10"
dependencies:
assertion-error: "npm:^2.0.1"
check-error: "npm:^2.0.0"
deep-eql: "npm:^5.0.1"
loupe: "npm:^3.0.0"
pathval: "npm:^2.0.0"
checksum: c23d1bb3912cc36d12861d7e4010bb992aabf923a8d393bc71e776218c39f5f40778ab9f398ff962dd26857edee07ce732c9ad28a678feb1b76f99384d2e4a90
assertion-error: "npm:^1.1.0"
check-error: "npm:^1.0.3"
deep-eql: "npm:^4.1.3"
get-func-name: "npm:^2.0.2"
loupe: "npm:^2.3.6"
pathval: "npm:^1.1.1"
type-detect: "npm:^4.0.8"
checksum: 9e545fd60f5efee4f06f7ad62f7b1b142932b08fbb3454db69defd511e7c58771ce51843764212da1e129b2c9d1b029fbf5f98da030fe67a95a0853e8679524f
languageName: node
linkType: hard
@@ -6493,10 +6495,12 @@ __metadata:
languageName: node
linkType: hard
"check-error@npm:^2.0.0":
version: 2.0.0
resolution: "check-error@npm:2.0.0"
checksum: 120f252c2e1ad82ef82a616662805345c6c361347bfd6203f8a28c53a158811dd0ea21278f29c8136cc9df12fc7f077d1a07124569d98fb396b3072d08f2f092
"check-error@npm:^1.0.3":
version: 1.0.3
resolution: "check-error@npm:1.0.3"
dependencies:
get-func-name: "npm:^2.0.2"
checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399
languageName: node
linkType: hard
@@ -7180,10 +7184,12 @@ __metadata:
languageName: node
linkType: hard
"deep-eql@npm:^5.0.1":
version: 5.0.1
resolution: "deep-eql@npm:5.0.1"
checksum: f8846820213462cdca23700873810c8bc01263dcc6a1e0f8694964b64f48a6dcb1f323ef7bb8678b15553f4b82420eda19092d4ae2e2709c56af7ea77bd8e6ab
"deep-eql@npm:^4.1.3":
version: 4.1.3
resolution: "deep-eql@npm:4.1.3"
dependencies:
type-detect: "npm:^4.0.0"
checksum: 12ce93ae63de187e77b076d3d51bfc28b11f98910a22c18714cce112791195e86a94f97788180994614b14562a86c9763f67c69f785e4586f806b5df39bf9301
languageName: node
linkType: hard
@@ -7222,13 +7228,13 @@ __metadata:
languageName: node
linkType: hard
"default-browser@npm:^5.2.1":
version: 5.2.1
resolution: "default-browser@npm:5.2.1"
"default-browser@npm:^5.2.0":
version: 5.2.0
resolution: "default-browser@npm:5.2.0"
dependencies:
bundle-name: "npm:^4.1.0"
default-browser-id: "npm:^5.0.0"
checksum: afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840
checksum: 95530de0dca75892b4382d086f42bd798f54a1e25eab748e84e1b64566568b1a02cf1eccfb60a8fbab303d72c09938c2d34e0b38e57d85efd24f13a60d2de802
languageName: node
linkType: hard
@@ -8960,7 +8966,7 @@ __metadata:
languageName: node
linkType: hard
"get-func-name@npm:^2.0.1":
"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2":
version: 2.0.2
resolution: "get-func-name@npm:2.0.2"
checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b
@@ -9579,8 +9585,8 @@ __metadata:
"@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.1.1"
"@mdi/js": "npm:7.4.47"
"@mdi/svg": "npm:7.4.47"
"@mdi/js": "npm:7.3.67"
"@mdi/svg": "npm:7.3.67"
"@octokit/auth-oauth-device": "npm:6.0.1"
"@octokit/plugin-retry": "npm:6.0.1"
"@octokit/rest": "npm:20.0.2"
@@ -9628,7 +9634,7 @@ __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.0"
chai: "npm:4.3.10"
chart.js: "npm:4.4.1"
comlink: "npm:4.4.1"
core-js: "npm:3.34.0"
@@ -9684,7 +9690,7 @@ __metadata:
mocha: "npm:10.2.0"
node-vibrant: "npm:3.2.1-alpha.1"
object-hash: "npm:3.0.0"
open: "npm:10.0.2"
open: "npm:10.0.1"
pinst: "npm:3.0.0"
prettier: "npm:3.1.1"
proxy-polyfill: "npm:0.3.2"
@@ -9695,7 +9701,7 @@ __metadata:
rollup: "npm:2.79.1"
rollup-plugin-string: "npm:3.0.0"
rollup-plugin-terser: "npm:7.0.2"
rollup-plugin-visualizer: "npm:5.12.0"
rollup-plugin-visualizer: "npm:5.11.0"
rrule: "npm:2.8.1"
serve-handler: "npm:6.1.5"
sinon: "npm:17.0.1"
@@ -9705,7 +9711,7 @@ __metadata:
superstruct: "npm:1.0.3"
systemjs: "npm:6.14.2"
tar: "npm:6.2.0"
terser-webpack-plugin: "npm:5.3.10"
terser-webpack-plugin: "npm:5.3.9"
tinykeys: "npm:2.1.0"
ts-lit-plugin: "npm:2.0.1"
tsparticles-engine: "npm:2.12.0"
@@ -11527,12 +11533,12 @@ __metadata:
languageName: node
linkType: hard
"loupe@npm:^3.0.0":
version: 3.0.2
resolution: "loupe@npm:3.0.2"
"loupe@npm:^2.3.6":
version: 2.3.7
resolution: "loupe@npm:2.3.7"
dependencies:
get-func-name: "npm:^2.0.1"
checksum: 256467bf10afaca4a5dd79b32e36fcd042bc2a247232e940c62bcc07cb114c2d7a549218eb103598e7cdb8bd32c6601fe230d80e03b8d49782973d4da11c08ed
checksum: 635c8f0914c2ce7ecfe4e239fbaf0ce1d2c00e4246fafcc4ed000bfdb1b8f89d05db1a220054175cca631ebf3894872a26fffba0124477fcb562f78762848fb1
languageName: node
linkType: hard
@@ -12524,15 +12530,15 @@ __metadata:
languageName: node
linkType: hard
"open@npm:10.0.2":
version: 10.0.2
resolution: "open@npm:10.0.2"
"open@npm:10.0.1":
version: 10.0.1
resolution: "open@npm:10.0.1"
dependencies:
default-browser: "npm:^5.2.1"
default-browser: "npm:^5.2.0"
define-lazy-prop: "npm:^3.0.0"
is-inside-container: "npm:^1.0.0"
is-wsl: "npm:^3.1.0"
checksum: 6f7f9e08204af00930f2998690293df1a919a61c98b225ff9e3aa09a765254b8a98bec101644ffe991452c6aabea0c6f9e49670b559d48a44bfc5238f6b58351
checksum: 7ce545e2e68775f06ab800c2a2ef20369bce2738e1219fd31179e1a1773f2c33fcc6b7f816a4f5e9214821cb58ae9c50f2e3f7dd8f5b02e418fbcafabf481f03
languageName: node
linkType: hard
@@ -12954,10 +12960,10 @@ __metadata:
languageName: node
linkType: hard
"pathval@npm:^2.0.0":
version: 2.0.0
resolution: "pathval@npm:2.0.0"
checksum: b91575bf9cdf01757afd7b5e521eb8a0b874a49bc972d08e0047cfea0cd3c019f5614521d4bc83d2855e3fcc331db6817dfd533dd8f3d90b16bc76fad2450fc1
"pathval@npm:^1.1.1":
version: 1.1.1
resolution: "pathval@npm:1.1.1"
checksum: b50a4751068aa3a5428f5a0b480deecedc6f537666a3630a0c2ae2d5e7c0f4bf0ee77b48404441ec1220bef0c91625e6030b3d3cf5a32ab0d9764018d1d9dbb6
languageName: node
linkType: hard
@@ -13840,9 +13846,9 @@ __metadata:
languageName: node
linkType: hard
"rollup-plugin-visualizer@npm:5.12.0":
version: 5.12.0
resolution: "rollup-plugin-visualizer@npm:5.12.0"
"rollup-plugin-visualizer@npm:5.11.0":
version: 5.11.0
resolution: "rollup-plugin-visualizer@npm:5.11.0"
dependencies:
open: "npm:^8.4.0"
picomatch: "npm:^2.3.1"
@@ -13855,7 +13861,7 @@ __metadata:
optional: true
bin:
rollup-plugin-visualizer: dist/bin/cli.js
checksum: 47358feb672291d6edcfd94197577c192a84c24cb644119425dae8241fb6f5a52556efd0c501f38b276c07534642a80c0885ef681babb474e83c7b5a3b475b84
checksum: 947238aa22706a47a4d3e8ce616855f0e5cb969ed9f61b9a268eaede0a86f461ecb38e27b4e6bf00f4b5e3f63677667f65e0d4af89a659a5160f74add1f192bb
languageName: node
linkType: hard
@@ -15005,15 +15011,15 @@ __metadata:
languageName: node
linkType: hard
"terser-webpack-plugin@npm:5.3.10, terser-webpack-plugin@npm:^5.3.7":
version: 5.3.10
resolution: "terser-webpack-plugin@npm:5.3.10"
"terser-webpack-plugin@npm:5.3.9, terser-webpack-plugin@npm:^5.3.7":
version: 5.3.9
resolution: "terser-webpack-plugin@npm:5.3.9"
dependencies:
"@jridgewell/trace-mapping": "npm:^0.3.20"
"@jridgewell/trace-mapping": "npm:^0.3.17"
jest-worker: "npm:^27.4.5"
schema-utils: "npm:^3.1.1"
serialize-javascript: "npm:^6.0.1"
terser: "npm:^5.26.0"
terser: "npm:^5.16.8"
peerDependencies:
webpack: ^5.1.0
peerDependenciesMeta:
@@ -15023,7 +15029,7 @@ __metadata:
optional: true
uglify-js:
optional: true
checksum: fb1c2436ae1b4e983be043fa0a3d355c047b16b68f102437d08c736d7960c001e7420e2f722b9d99ce0dc70ca26a68cc63c0b82bc45f5b48671142b352a9d938
checksum: 339737a407e034b7a9d4a66e31d84d81c10433e41b8eae2ca776f0e47c2048879be482a9aa08e8c27565a2a949bc68f6e07f451bf4d9aa347dd61b3d000f5353
languageName: node
linkType: hard
@@ -15040,7 +15046,7 @@ __metadata:
languageName: node
linkType: hard
"terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.26.0":
"terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.16.8":
version: 5.26.0
resolution: "terser@npm:5.26.0"
dependencies:
@@ -15400,7 +15406,7 @@ __metadata:
languageName: node
linkType: hard
"type-detect@npm:4.0.8, type-detect@npm:^4.0.8":
"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.8":
version: 4.0.8
resolution: "type-detect@npm:4.0.8"
checksum: 5179e3b8ebc51fce1b13efb75fdea4595484433f9683bbc2dca6d99789dba4e602ab7922d2656f2ce8383987467f7770131d4a7f06a26287db0615d2f4c4ce7d