Compare commits

..

57 Commits

Author SHA1 Message Date
Wendelin
8b82882e15 ha-authorize fix rtl check (#29937)
Add RTL direction handling in updated lifecycle method
2026-03-02 18:22:06 +01:00
Matthias Alphart
2701015eda Fix data-table content bottom margin (#29805)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 17:02:31 +01:00
Aidan Timson
1991a9e493 Code editor fullscreen in dialogs (#29882)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2026-03-02 17:01:13 +01:00
Petar Petrov
2b72c54194 Migrate Energy date selector to new footer (#29867) 2026-03-02 17:00:34 +01:00
Paul Bottein
a7cb2fe7a7 Fix updates, discovered devices and repairs cards flickering (#29935) 2026-03-02 13:50:42 +00:00
Paul Bottein
51ea0c8201 Fix sidebar not closing when reduced motion is enabled (#29934) 2026-03-02 13:19:26 +00:00
Wendelin
ead7081bc6 Dialog: Add show event target check (#29927)
Add event phase check in _handleShow and _handleAfterShow methods
2026-03-02 11:41:52 +00:00
Wendelin
ee982b1899 Add error translation for loading energy preferences (#29924) 2026-03-02 11:49:46 +02:00
Aidan Timson
e8b100a39e Remove cache to fix re-add repo issue (#29926)
Remove cache to fix readd repo issue
2026-03-02 11:49:19 +02:00
Copilot
50c361db62 Add mixin to remove code duplication in automation/script editors (#29842)
* Initial plan

* Changes before error encountered

Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>

* Fix mixin: use function-body syntax for decorators, curried generics for type safety

Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>

* Simplify automation/script editor mixin signature

* Add shared styles and loading animation to automation/script editor mixin

Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>

* Remove underscore prefix from protected members per style guide

Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: Wendelin <w@pe8.at>
2026-03-02 11:44:04 +02:00
sevorl
e7a8d15a13 Use ha-duration-input for wait_template timeout (#29862) 2026-03-02 09:07:51 +01:00
karwosts
fbd0409837 Init ha-form expansion elements to undefined instead of null (#29900)
* Init ha-form expansion elements to undefined instead of null

* revert change to error/warning
2026-03-02 09:29:06 +02:00
karwosts
a0d100611f Fix distribution card stub error (#29915)
* Fix distribution card stub error

* unit check not required
2026-03-02 09:06:10 +02:00
dependabot[bot]
a969bf1065 Bump actions/upload-artifact from 6.0.0 to 7.0.0 (#29922)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](b7c566a772...bbbca2ddaa)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 06:10:19 +00:00
renovate[bot]
a153330610 Update dependency gulp-zopfli-green to v7 (#29919)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-02 07:06:41 +01:00
renovate[bot]
bd2f1ca3a8 Update dependency @html-eslint/eslint-plugin to v0.57.1 (#29905)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-28 20:08:37 +01:00
renovate[bot]
3263034416 Update dependency @codemirror/language to v6.12.2 (#29904)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-28 20:07:43 +01:00
Paul Bottein
82b28b547a Fix control select menu color in ios (#29892) 2026-02-27 17:26:04 +01:00
Bram Kragten
61c2c750b4 Fix overflow for icon buttons (#29891) 2026-02-27 15:44:21 +00:00
Petar Petrov
117690ee70 Fix sensor card graph not updating when value is unchanged (#29889) 2026-02-27 15:41:54 +00:00
Petar Petrov
e753de85eb Make hui-sections-view always fill the screen so footer is at the bottom (#29890) 2026-02-27 15:39:21 +00:00
Paul Bottein
a240019968 Add render icon property to ha-control-select-menu (#29881) 2026-02-27 16:23:58 +01:00
Petar Petrov
0bdf4b8777 Fix monetary device class state display with non-ISO 4217 currency symbols (#29887) 2026-02-27 14:59:14 +01:00
renovate[bot]
6337828ed8 Update dependency barcode-detector to v3.1.0 (#29886)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-27 15:46:29 +02:00
Aidan Timson
b8e5af652b Add audits and yaml mode to more info details (#29854)
* Add audits and yaml mode to more info details

* Reset yaml mode on back

* Use mapped array for state entries

* Typo

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Memoize

* Rename

* Fix

* Format audits in normal mode

* Refactor, dont pass hass

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2026-02-27 14:45:55 +01:00
Petar Petrov
e4ae29e8b5 Fix energy compare tooltip showing wrong year (#29885) 2026-02-27 14:37:52 +01:00
Aidan Timson
08231dbbb0 Use large width on system log dialogs (#29879) 2026-02-27 12:46:10 +01:00
Paul Bottein
0ca656933d Revert "Add render icon property to ha-control-select-menu"
This reverts commit b23cf8eba4.
2026-02-27 12:21:23 +01:00
Paul Bottein
b23cf8eba4 Add render icon property to ha-control-select-menu 2026-02-27 12:20:52 +01:00
Robert Resch
61b546415d Revert "Add vacuum mapping not configured issue" (#29876) 2026-02-27 11:18:49 +01:00
Brandon Chen
4e1b709303 Fix YAML content invisible in dark mode for conversation debug result… (#29874) 2026-02-27 09:11:28 +01:00
renovate[bot]
34e65b302d Update dependency typescript-eslint to v8.56.1 (#29868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-26 18:08:04 +00:00
renovate[bot]
336d0e1b9d Update dependency @html-eslint/eslint-plugin to v0.57.0 (#29863)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-26 17:25:10 +01:00
Paul Bottein
58d4cf8d84 Fix scrollbar in 2026.3 (#29865) 2026-02-26 16:44:12 +01:00
Aidan Timson
d3453aff37 Add missing theming variable support to dialog and bottom sheet (#29857) 2026-02-26 16:43:20 +01:00
Aidan Timson
64ff2e414c Add thread configuration my link (#29861) 2026-02-26 15:06:46 +00:00
Wendelin
2ca25c980f Fix quick search icon size (#29858) 2026-02-26 15:59:27 +01:00
Aidan Timson
73d93bc601 Add matter configuration my link (#29859) 2026-02-26 14:41:43 +00:00
Wendelin
5ca6a8aced Fix ha-icon-button-toggle selected style (#29856) 2026-02-26 13:02:12 +00:00
Aidan Timson
7ff4993e0b Fix esc closing dialogs with prevent scrim close (#29851) 2026-02-26 13:20:05 +02:00
Norbert Rittel
4e6fbacccc Remove trailing periods from "Learn more" etc. links / tooltips (#29835) 2026-02-26 10:38:54 +00:00
Petar Petrov
2958d49e36 Convert Energy Now tiles to badges (#29845) 2026-02-26 10:38:01 +00:00
Norbert Rittel
92289dc7ea Improve "Create a new … helper" option in entity picker (#29853) 2026-02-26 10:34:42 +00:00
Petar Petrov
f6c1a890e4 Dynamically calculate the date range picker's vertical opening direction (#29850) 2026-02-26 09:33:34 +00:00
Wendelin
d06321ed43 Fix protocols dashboards fab padding (#29847) 2026-02-26 10:31:50 +02:00
dependabot[bot]
3c3d8d9974 Bump rollup from 2.79.2 to 2.80.0 (#29841)
Bumps [rollup](https://github.com/rollup/rollup) from 2.79.2 to 2.80.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/v2.80.0/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.79.2...v2.80.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 2.80.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-26 08:18:15 +02:00
Paul Bottein
4f39fa482d Only ask to refresh dashboard in edit mode or yaml mode (#29826) 2026-02-26 08:16:21 +02:00
renovate[bot]
5d0fe3236c Update dependency @swc/helpers to v0.5.19 (#29836)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-26 07:07:37 +01:00
renovate[bot]
b86142ae50 Update Node.js to v24.14.0 (#29831)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-25 19:25:42 +00:00
renovate[bot]
5d2f3ee5e8 Update dependency tar to v7.5.9 (#29832)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-25 19:24:58 +00:00
AlCalzone
e3f7c631a7 Rename "Z-Wave JS" to "Z-Wave" when not referring to the project/org (#29830) 2026-02-25 19:15:16 +00:00
renovate[bot]
49f9d95853 Update dependency vite-tsconfig-paths to v6.1.1 (#29829)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-25 18:53:12 +01:00
renovate[bot]
db3d7701b5 Update dependency typescript-eslint to v8.56.0 (#29828)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-25 17:35:36 +00:00
renovate[bot]
3e55acf531 Update dependency @home-assistant/webawesome to v3.2.1-ha.3 (#29810)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-25 18:26:47 +01:00
renovate[bot]
f102618d9d Update dependency eslint-plugin-wc to v3.1.0 (#29824)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-25 18:25:06 +01:00
renovate[bot]
a3c02b511d Update dependency jsdom to v28.1.0 (#29825)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-25 18:24:38 +01:00
Bram Kragten
74111d248e Fix css minifying (#29827) 2026-02-25 17:53:50 +01:00
19 changed files with 914 additions and 1033 deletions

View File

@@ -89,13 +89,13 @@ jobs:
env:
IS_TEST: "true"
- name: Upload bundle stats
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: frontend-bundle-stats
path: build/stats/*.json
if-no-files-found: error
- name: Upload frontend build
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: frontend-build
path: hass_frontend/

View File

@@ -57,14 +57,14 @@ jobs:
run: tar -czvf translations.tar.gz translations
- name: Upload build artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: wheels
path: dist/home_assistant_frontend*.whl
if-no-files-found: error
- name: Upload translations
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: translations
path: translations.tar.gz

2
.nvmrc
View File

@@ -1 +1 @@
24.13.1
24.14.0

View File

@@ -30,7 +30,7 @@
"@braintree/sanitize-url": "7.1.2",
"@codemirror/autocomplete": "6.20.0",
"@codemirror/commands": "6.10.2",
"@codemirror/language": "6.12.1",
"@codemirror/language": "6.12.2",
"@codemirror/legacy-modes": "6.5.2",
"@codemirror/search": "6.6.0",
"@codemirror/state": "6.5.4",
@@ -52,7 +52,7 @@
"@fullcalendar/list": "6.1.20",
"@fullcalendar/luxon3": "6.1.20",
"@fullcalendar/timegrid": "6.1.20",
"@home-assistant/webawesome": "3.2.1-ha.2",
"@home-assistant/webawesome": "3.2.1-ha.3",
"@lezer/highlight": "1.2.3",
"@lit-labs/motion": "1.1.0",
"@lit-labs/observers": "2.1.0",
@@ -83,7 +83,7 @@
"@mdi/js": "7.4.47",
"@mdi/svg": "7.4.47",
"@replit/codemirror-indentation-markers": "6.5.3",
"@swc/helpers": "0.5.18",
"@swc/helpers": "0.5.19",
"@thomasloven/round-slider": "0.6.0",
"@tsparticles/engine": "3.9.1",
"@tsparticles/preset-links": "3.2.0",
@@ -92,7 +92,7 @@
"@webcomponents/scoped-custom-element-registry": "0.0.10",
"@webcomponents/webcomponentsjs": "2.8.0",
"app-datepicker": "5.1.1",
"barcode-detector": "3.0.8",
"barcode-detector": "3.1.0",
"color-name": "2.1.0",
"comlink": "4.4.2",
"core-js": "3.48.0",
@@ -106,7 +106,7 @@
"element-internals-polyfill": "3.0.2",
"fuse.js": "7.1.0",
"google-timezones-json": "1.2.0",
"gulp-zopfli-green": "6.0.2",
"gulp-zopfli-green": "7.0.0",
"hls.js": "1.6.15",
"home-assistant-js-websocket": "9.6.0",
"idb-keyval": "6.2.2",
@@ -149,7 +149,7 @@
"@babel/plugin-transform-runtime": "7.29.0",
"@babel/preset-env": "7.29.0",
"@bundle-stats/plugin-webpack-filter": "4.21.10",
"@html-eslint/eslint-plugin": "0.56.0",
"@html-eslint/eslint-plugin": "0.57.1",
"@lokalise/node-api": "15.6.1",
"@octokit/auth-oauth-device": "8.0.3",
"@octokit/plugin-retry": "8.1.0",
@@ -172,7 +172,7 @@
"@types/mocha": "10.0.10",
"@types/qrcode": "1.5.6",
"@types/sortablejs": "1.15.9",
"@types/tar": "6.1.13",
"@types/tar": "7.0.87",
"@types/ua-parser-js": "0.7.39",
"@types/webspeechapi": "0.0.29",
"@vitest/coverage-v8": "4.0.18",
@@ -188,7 +188,7 @@
"eslint-plugin-lit": "2.2.1",
"eslint-plugin-lit-a11y": "5.1.1",
"eslint-plugin-unused-imports": "4.4.1",
"eslint-plugin-wc": "3.0.2",
"eslint-plugin-wc": "3.1.0",
"fancy-log": "2.0.0",
"fs-extra": "11.3.3",
"glob": "13.0.6",
@@ -198,7 +198,7 @@
"gulp-rename": "2.1.0",
"html-minifier-terser": "7.2.0",
"husky": "9.1.7",
"jsdom": "28.0.0",
"jsdom": "28.1.0",
"jszip": "3.10.1",
"lint-staged": "16.2.7",
"lit-analyzer": "2.0.3",
@@ -210,12 +210,12 @@
"rspack-manifest-plugin": "5.2.1",
"serve": "14.2.5",
"sinon": "21.0.1",
"tar": "7.5.8",
"tar": "7.5.9",
"terser-webpack-plugin": "5.3.16",
"ts-lit-plugin": "2.0.2",
"typescript": "5.9.3",
"typescript-eslint": "8.54.0",
"vite-tsconfig-paths": "6.0.5",
"typescript-eslint": "8.56.1",
"vite-tsconfig-paths": "6.1.1",
"vitest": "4.0.18",
"webpack-stats-plugin": "1.1.3",
"webpackbar": "7.0.0",
@@ -235,6 +235,6 @@
},
"packageManager": "yarn@4.12.0",
"volta": {
"node": "24.13.1"
"node": "24.14.0"
}
}

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20260302.0"
version = "20260128.0"
license = "Apache-2.0"
license-files = ["LICENSE*"]
description = "The Home Assistant frontend"

View File

@@ -672,11 +672,11 @@ export class HaAssistChat extends LitElement {
--markdown-code-background-color: var(--primary-background-color);
--markdown-code-text-color: var(--primary-text-color);
--markdown-list-indent: 1.15em;
&:not(:has(ha-markdown-element)) {
min-height: 1lh;
min-width: 1lh;
flex-shrink: 0;
}
}
ha-markdown:not(:has(ha-markdown-element)) {
min-height: 1lh;
min-width: 1lh;
flex-shrink: 0;
}
.bouncer {
width: 48px;

View File

@@ -410,29 +410,29 @@ export class HaDialog extends ScrollableFadeMixin(LitElement) {
@media all and (max-width: 450px), all and (max-height: 500px) {
:host([type="standard"]) {
--ha-dialog-border-radius: 0;
}
wa-dialog {
/* Make the container fill the whole screen width and not the safe width */
--full-width: var(--ha-dialog-width-full, 100vw);
--width: var(--full-width);
}
:host([type="standard"]) wa-dialog {
/* Make the container fill the whole screen width and not the safe width */
--full-width: var(--ha-dialog-width-full, 100vw);
--width: var(--full-width);
}
wa-dialog::part(dialog) {
/* Make the dialog fill the whole screen height and not the safe height */
min-height: var(--ha-dialog-min-height, 100vh);
min-height: var(--ha-dialog-min-height, 100dvh);
max-height: var(--ha-dialog-max-height, 100vh);
max-height: var(--ha-dialog-max-height, 100dvh);
margin-top: 0;
margin-bottom: 0;
/* Use safe area as padding instead of the container size */
padding-top: var(--safe-area-inset-top);
padding-bottom: var(--safe-area-inset-bottom);
padding-left: var(--safe-area-inset-left);
padding-right: var(--safe-area-inset-right);
/* Reset the transform to center the dialog */
transform: none;
}
:host([type="standard"]) wa-dialog::part(dialog) {
/* Make the dialog fill the whole screen height and not the safe height */
min-height: var(--ha-dialog-min-height, 100vh);
min-height: var(--ha-dialog-min-height, 100dvh);
max-height: var(--ha-dialog-max-height, 100vh);
max-height: var(--ha-dialog-max-height, 100dvh);
margin-top: 0;
margin-bottom: 0;
/* Use safe area as padding instead of the container size */
padding-top: var(--safe-area-inset-top);
padding-bottom: var(--safe-area-inset-bottom);
padding-left: var(--safe-area-inset-left);
padding-right: var(--safe-area-inset-right);
/* Reset the transform to center the dialog */
transform: none;
}
}

View File

@@ -24,7 +24,7 @@ const LOAD_ELEMENTS = {
};
const getValue = (obj, item) =>
obj ? (!item.name || item.flatten ? obj : obj[item.name]) : null;
obj ? (!item.name || item.flatten ? obj : obj[item.name]) : undefined;
const getError = (obj, item) => (obj && item.name ? obj[item.name] : null);

View File

@@ -84,13 +84,11 @@ export class HaMarkdown extends LitElement {
ha-markdown-element > :is(ol, ul) {
padding-inline-start: var(--markdown-list-indent, revert);
}
li {
&:has(input[type="checkbox"]) {
list-style: none;
& > input[type="checkbox"] {
margin-left: 0;
}
}
li:has(input[type="checkbox"]) {
list-style: none;
}
li:has(input[type="checkbox"]) > input[type="checkbox"] {
margin-left: 0;
}
svg {
background-color: var(--markdown-svg-background-color, none);
@@ -137,10 +135,10 @@ export class HaMarkdown extends LitElement {
--markdown-table-border-width: 0;
--markdown-table-padding-inline: 0;
--markdown-table-padding-block: 0;
th,
td {
vertical-align: middle;
}
}
table[role="presentation"] th,
table[role="presentation"] td {
vertical-align: middle;
}
table[role="presentation"] td[valign="top"],
table[role="presentation"] th[valign="top"] {

View File

@@ -2,10 +2,10 @@ import type { LitElement, PropertyValues } from "lit";
import { property, state } from "lit/decorators";
import type { LocalizeFunc } from "../common/translations/localize";
import { computeLocalize } from "../common/translations/localize";
import { computeDirectionStyles } from "../common/util/compute_rtl";
import { translationMetadata } from "../resources/translations-metadata";
import type { Constructor, Resources } from "../types";
import { getLocalLanguage, getTranslation } from "../util/common-translation";
import { translationMetadata } from "../resources/translations-metadata";
import { computeDirectionStyles } from "../common/util/compute_rtl";
const empty = () => "";
@@ -28,16 +28,16 @@ export const litLocalizeLiteMixin = <T extends Constructor<LitElement>>(
this._initializeLocalizeLite();
}
protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
computeDirectionStyles(
translationMetadata.translations[this.language!].isRTL,
this
);
}
protected willUpdate(changedProperties: PropertyValues) {
super.willUpdate(changedProperties);
if (!this.updated || changedProperties.has("language")) {
computeDirectionStyles(
translationMetadata.translations[this.language!].isRTL,
this
);
}
if (changedProperties.get("language")) {
this._resources = undefined;
this._initializeLocalizeLite();

View File

@@ -1,30 +1,17 @@
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
import { isTemplate } from "../../../../../common/string/has-template";
import type { WaitAction } from "../../../../../data/script";
import type { HomeAssistant } from "../../../../../types";
import type { ActionElement } from "../ha-automation-action-row";
import "../../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../../components/ha-form/types";
import type {
HaFormSchema,
SchemaUnion,
} from "../../../../../components/ha-form/types";
const SCHEMA = [
{
name: "wait_template",
selector: {
template: {},
},
},
{
name: "timeout",
required: false,
selector: {
text: {},
},
},
{
name: "continue_on_timeout",
selector: { boolean: {} },
},
] as const;
type TimeoutType = "string_template" | "object_template" | "duration";
@customElement("ha-automation-action-wait_template")
export class HaWaitAction extends LitElement implements ActionElement {
@@ -38,12 +25,47 @@ export class HaWaitAction extends LitElement implements ActionElement {
return { wait_template: "", continue_on_timeout: true };
}
private _schema = memoizeOne(
(timeoutType: TimeoutType) =>
[
{
name: "wait_template",
selector: { template: {} },
},
{
name: "timeout",
required: false,
selector:
timeoutType === "string_template"
? { template: {} }
: timeoutType === "object_template"
? { object: {} }
: { duration: { enable_millisecond: true } },
},
{
name: "continue_on_timeout",
selector: { boolean: {} },
},
] as const satisfies readonly HaFormSchema[]
);
protected render() {
const timeout = this.action.timeout;
const timeoutType: TimeoutType =
typeof timeout === "string" && isTemplate(timeout)
? "string_template"
: typeof timeout === "object" &&
timeout !== null &&
Object.values(timeout).some(
(v) => typeof v === "string" && isTemplate(v)
)
? "object_template"
: "duration";
return html`
<ha-form
.hass=${this.hass}
.data=${this.action}
.schema=${SCHEMA}
.schema=${this._schema(timeoutType)}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
></ha-form>
@@ -51,7 +73,7 @@ export class HaWaitAction extends LitElement implements ActionElement {
}
private _computeLabelCallback = (
schema: SchemaUnion<typeof SCHEMA>
schema: SchemaUnion<ReturnType<typeof this._schema>>
): string =>
this.hass.localize(
`ui.panel.config.automation.editor.actions.type.wait_template.${

View File

@@ -27,19 +27,15 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { UndoRedoController } from "../../../common/controllers/undo-redo-controller";
import { transform } from "../../../common/decorators/transform";
import { fireEvent } from "../../../common/dom/fire_event";
import { goBack, navigate } from "../../../common/navigate";
import { promiseTimeout } from "../../../common/util/promise-timeout";
import { afterNextRender } from "../../../common/util/render-status";
import "../../../components/ha-button";
import "../../../components/ha-dropdown";
import "../../../components/ha-dropdown-item";
import "../../../components/ha-fab";
import "../../../components/ha-fade-in";
import "../../../components/ha-icon";
import "../../../components/ha-icon-button";
import "../../../components/ha-spinner";
import "../../../components/ha-svg-icon";
import "../../../components/ha-yaml-editor";
import type {
@@ -72,27 +68,22 @@ import {
showAlertDialog,
showConfirmationDialog,
} from "../../../dialogs/generic/show-dialog-box";
import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog";
import "../../../layouts/hass-subpage";
import { KeyboardShortcutMixin } from "../../../mixins/keyboard-shortcut-mixin";
import { PreventUnsavedMixin } from "../../../mixins/prevent-unsaved-mixin";
import { haStyle } from "../../../resources/styles";
import type {
Entries,
HomeAssistant,
Route,
ValueChangedEvent,
} from "../../../types";
import type { Entries, ValueChangedEvent } from "../../../types";
import { isMac } from "../../../util/is_mac";
import { showToast } from "../../../util/toast";
import { showAssignCategoryDialog } from "../category/show-dialog-assign-category";
import { showAutomationModeDialog } from "./automation-mode-dialog/show-dialog-automation-mode";
import {
type EntityRegistryUpdate,
showAutomationSaveDialog,
} from "./automation-save-dialog/show-dialog-automation-save";
import { showAutomationSaveDialog } from "./automation-save-dialog/show-dialog-automation-save";
import { showAutomationSaveTimeoutDialog } from "./automation-save-timeout-dialog/show-dialog-automation-save-timeout";
import "./blueprint-automation-editor";
import {
AutomationScriptEditorMixin,
automationScriptEditorStyles,
} from "./ha-automation-script-editor-mixin";
import "./manual-automation-editor";
import type { HaManualAutomationEditor } from "./manual-automation-editor";
import type { HaDropdownSelectEvent } from "../../../components/ha-dropdown";
@@ -119,53 +110,13 @@ declare global {
}
@customElement("ha-automation-editor")
export class HaAutomationEditor extends PreventUnsavedMixin(
KeyboardShortcutMixin(LitElement)
export class HaAutomationEditor extends AutomationScriptEditorMixin<AutomationConfig>(
PreventUnsavedMixin(KeyboardShortcutMixin(LitElement))
) {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public automationId: string | null = null;
@property({ attribute: false }) public entityId: string | null = null;
@property({ attribute: false }) public automations!: AutomationEntity[];
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
@property({ type: Boolean }) public narrow = false;
@property({ attribute: false }) public route!: Route;
@state() private _config?: AutomationConfig;
@state() private _dirty = false;
@state() private _errors?: string;
@state() private _yamlErrors?: string;
@state() private _entityId?: string;
@state() private _mode: "gui" | "yaml" = "gui";
@state() private _readOnly = false;
@state() private _validationErrors?: (string | TemplateResult)[];
@state() private _blueprintConfig?: BlueprintAutomationConfig;
@state()
@consume({ context: fullEntitiesContext, subscribe: true })
@transform<EntityRegistryEntry[], EntityRegistryEntry>({
transformer: function (this: HaAutomationEditor, value) {
return value.find(({ entity_id }) => entity_id === this._entityId);
},
watch: ["_entityId"],
})
private _registryEntry?: EntityRegistryEntry;
@state() private _saving = false;
@state()
@consume({ context: fullEntitiesContext, subscribe: true })
_entityRegistry!: EntityRegistryEntry[];
@@ -180,24 +131,18 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
private _configSubscriptionsId = 1;
private _entityRegistryUpdate?: EntityRegistryUpdate;
private _newAutomationId?: string;
private _entityRegCreated?: (
value: PromiseLike<EntityRegistryEntry> | EntityRegistryEntry
) => void;
private _undoRedoController = new UndoRedoController<AutomationConfig>(this, {
apply: (config) => this._applyUndoRedo(config),
currentConfig: () => this._config!,
currentConfig: () => this.config!,
});
protected willUpdate(changedProps) {
super.willUpdate(changedProps);
if (
this._entityRegCreated &&
this.entityRegCreated &&
this._newAutomationId &&
changedProps.has("_entityRegistry")
) {
@@ -207,26 +152,22 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
entity.unique_id === this._newAutomationId
);
if (automation) {
this._entityRegCreated(automation);
this._entityRegCreated = undefined;
this.entityRegCreated(automation);
this.entityRegCreated = undefined;
}
}
}
protected render(): TemplateResult | typeof nothing {
if (!this._config) {
return html`
<ha-fade-in .delay=${500}>
<ha-spinner size="large"></ha-spinner>
</ha-fade-in>
`;
if (!this.config) {
return this.renderLoading();
}
const stateObj = this._entityId
? this.hass.states[this._entityId]
const stateObj = this.currentEntityId
? this.hass.states[this.currentEntityId]
: undefined;
const useBlueprint = "use_blueprint" in this._config;
const useBlueprint = "use_blueprint" in this.config;
const shortcutIcon = isMac
? html`<ha-svg-icon .path=${mdiAppleKeyboardCommand}></ha-svg-icon>`
: this.hass.localize("ui.panel.config.automation.editor.ctrl");
@@ -236,11 +177,11 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
.hass=${this.hass}
.narrow=${this.narrow}
.route=${this.route}
.backCallback=${this._backTapped}
.header=${this._config.alias ||
.backCallback=${this.backTapped}
.header=${this.config.alias ||
this.hass.localize("ui.panel.config.automation.editor.default_name")}
>
${this._mode === "gui" && !this.narrow
${this.mode === "gui" && !this.narrow
? html`<ha-icon-button
slot="toolbar-icon"
.label=${this.hass.localize("ui.common.undo")}
@@ -284,7 +225,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
</span>
</ha-tooltip>`
: nothing}
${this._config?.id && !this.narrow
${this.config?.id && !this.narrow
? html`
<ha-button
appearance="plain"
@@ -308,7 +249,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
.path=${mdiDotsVertical}
></ha-icon-button>
${this._mode === "gui" && this.narrow
${this.mode === "gui" && this.narrow
? html`<ha-dropdown-item
value="undo"
.disabled=${!this._undoRedoController.canUndo}
@@ -342,7 +283,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
<ha-dropdown-item .disabled=${!stateObj} value="category">
${this.hass.localize(
`ui.panel.config.scene.picker.${this._registryEntry?.categories?.automation ? "edit_category" : "assign_category"}`
`ui.panel.config.scene.picker.${this.registryEntry?.categories?.automation ? "edit_category" : "assign_category"}`
)}
<ha-svg-icon slot="icon" .path=${mdiTag}></ha-svg-icon>
</ha-dropdown-item>
@@ -366,9 +307,9 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
<ha-dropdown-item
value="rename"
.disabled=${this._readOnly ||
.disabled=${this.readOnly ||
!this.automationId ||
this._mode === "yaml"}
this.mode === "yaml"}
>
${this.hass.localize("ui.panel.config.automation.editor.rename")}
<ha-svg-icon slot="icon" .path=${mdiRenameBox}></ha-svg-icon>
@@ -377,7 +318,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
? html`
<ha-dropdown-item
@click=${this._promptAutomationMode}
.disabled=${this._readOnly || this._mode === "yaml"}
.disabled=${this.readOnly || this.mode === "yaml"}
>
${this.hass.localize(
"ui.panel.config.automation.editor.change_mode"
@@ -391,12 +332,12 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
: nothing}
<ha-dropdown-item
.disabled=${!!this._blueprintConfig ||
(!this._readOnly && !this.automationId)}
.disabled=${!!this.blueprintConfig ||
(!this.readOnly && !this.automationId)}
value="duplicate"
>
${this.hass.localize(
this._readOnly
this.readOnly
? "ui.panel.config.automation.editor.migrate"
: "ui.panel.config.automation.editor.duplicate"
)}
@@ -410,7 +351,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
? html`
<ha-dropdown-item
value="take_control"
.disabled=${this._readOnly}
.disabled=${this.readOnly}
>
${this.hass.localize(
"ui.panel.config.automation.editor.take_control"
@@ -422,7 +363,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
<ha-dropdown-item value="toggle_yaml_mode">
${this.hass.localize(
`ui.panel.config.automation.editor.edit_${this._mode === "gui" ? "yaml" : "ui"}`
`ui.panel.config.automation.editor.edit_${this.mode === "gui" ? "yaml" : "ui"}`
)}
<ha-svg-icon slot="icon" .path=${mdiPlaylistEdit}></ha-svg-icon>
</ha-dropdown-item>
@@ -456,10 +397,10 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
</ha-dropdown-item>
</ha-dropdown>
<div
class=${this._mode === "yaml" ? "yaml-mode" : ""}
class=${this.mode === "yaml" ? "yaml-mode" : ""}
@subscribe-automation-config=${this._subscribeAutomationConfig}
>
${this._mode === "gui"
${this.mode === "gui"
? html`
<div>
${useBlueprint
@@ -469,10 +410,10 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
.narrow=${this.narrow}
.isWide=${this.isWide}
.stateObj=${stateObj}
.config=${this._config}
.disabled=${this._readOnly}
.saving=${this._saving}
.dirty=${this._dirty}
.config=${this.config}
.disabled=${this.readOnly}
.saving=${this.saving}
.dirty=${this.dirty}
@value-changed=${this._valueChanged}
@save-automation=${this._handleSaveAutomation}
></blueprint-automation-editor>
@@ -483,16 +424,16 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
.narrow=${this.narrow}
.isWide=${this.isWide}
.stateObj=${stateObj}
.config=${this._config}
.disabled=${this._readOnly}
.dirty=${this._dirty}
.saving=${this._saving}
.config=${this.config}
.disabled=${this.readOnly}
.dirty=${this.dirty}
.saving=${this.saving}
@value-changed=${this._valueChanged}
@save-automation=${this._handleSaveAutomation}
@editor-save=${this._handleSaveAutomation}
>
<div class="alert-wrapper" slot="alerts">
${this._errors || stateObj?.state === UNAVAILABLE
${this.errors || stateObj?.state === UNAVAILABLE
? html`<ha-alert
alert-type="error"
.title=${stateObj?.state === UNAVAILABLE
@@ -501,7 +442,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
)
: undefined}
>
${this._errors || this._validationErrors}
${this.errors || this.validationErrors}
${stateObj?.state === UNAVAILABLE
? html`<ha-svg-icon
slot="icon"
@@ -510,7 +451,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
: nothing}
</ha-alert>`
: nothing}
${this._blueprintConfig
${this.blueprintConfig
? html`<ha-alert alert-type="info">
${this.hass.localize(
"ui.panel.config.automation.editor.confirm_take_control"
@@ -518,21 +459,21 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
<div slot="action" style="display: flex;">
<ha-button
appearance="plain"
@click=${this._takeControlSave}
@click=${this.takeControlSave}
>${this.hass.localize(
"ui.common.yes"
)}</ha-button
>
<ha-button
appearance="plain"
@click=${this._revertBlueprint}
@click=${this.revertBlueprint}
>${this.hass.localize(
"ui.common.no"
)}</ha-button
>
</div>
</ha-alert>`
: this._readOnly
: this.readOnly
? html`<ha-alert
alert-type="warning"
dismissable
@@ -575,7 +516,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
`}
</div>
`
: this._mode === "yaml"
: this.mode === "yaml"
? html`${stateObj?.state === "off"
? html`
<ha-alert alert-type="info">
@@ -598,7 +539,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
<ha-yaml-editor
.hass=${this.hass}
.defaultValue=${this._preprocessYaml()}
.readOnly=${this._readOnly}
.readOnly=${this.readOnly}
@value-changed=${this._yamlChanged}
@editor-save=${this._handleSaveAutomation}
.showErrors=${false}
@@ -606,9 +547,9 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
></ha-yaml-editor>
<ha-fab
slot="fab"
class=${this._dirty ? "dirty" : ""}
class=${this.dirty ? "dirty" : ""}
.label=${this.hass.localize("ui.common.save")}
.disabled=${this._saving}
.disabled=${this.saving}
extended
@click=${this._handleSaveAutomation}
>
@@ -645,7 +586,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
this.hass
) {
const initData = getAutomationEditorInitData();
this._dirty = !!initData;
this.dirty = !!initData;
let baseConfig: Partial<AutomationConfig> = { description: "" };
if (!initData || !("use_blueprint" in initData)) {
baseConfig = {
@@ -656,35 +597,35 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
actions: [],
};
}
this._config = {
this.config = {
...baseConfig,
...(initData ? normalizeAutomationConfig(initData) : initData),
} as AutomationConfig;
this._entityId = undefined;
this._readOnly = false;
this.currentEntityId = undefined;
this.readOnly = false;
}
if (changedProps.has("entityId") && this.entityId) {
getAutomationStateConfig(this.hass, this.entityId).then((c) => {
this._config = normalizeAutomationConfig(c.config);
this.config = normalizeAutomationConfig(c.config);
this._checkValidation();
});
this._entityId = this.entityId;
this._dirty = false;
this._readOnly = true;
this.currentEntityId = this.entityId;
this.dirty = false;
this.readOnly = true;
}
if (
changedProps.has("automations") &&
this.automationId &&
!this._entityId
!this.currentEntityId
) {
this._setEntityId();
}
if (changedProps.has("_config")) {
if (changedProps.has("config")) {
Object.values(this._configSubscriptions).forEach((sub) =>
sub(this._config)
sub(this.config)
);
}
}
@@ -693,24 +634,24 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
const automation = this.automations.find(
(entity: AutomationEntity) => entity.attributes.id === this.automationId
);
this._entityId = automation?.entity_id;
this.currentEntityId = automation?.entity_id;
}
private async _checkValidation() {
this._validationErrors = undefined;
if (!this._entityId || !this._config) {
this.validationErrors = undefined;
if (!this.currentEntityId || !this.config) {
return;
}
const stateObj = this.hass.states[this._entityId];
const stateObj = this.hass.states[this.currentEntityId];
if (stateObj?.state !== UNAVAILABLE) {
return;
}
const validation = await validateConfig(this.hass, {
triggers: this._config.triggers,
conditions: this._config.conditions,
actions: this._config.actions,
triggers: this.config.triggers,
conditions: this.config.conditions,
actions: this.config.actions,
});
this._validationErrors = (
this.validationErrors = (
Object.entries(validation) as Entries<typeof validation>
).map(([key, value]) =>
value.valid
@@ -728,9 +669,9 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
this.hass,
this.automationId as string
);
this._dirty = false;
this._readOnly = false;
this._config = normalizeAutomationConfig(config);
this.dirty = false;
this.readOnly = false;
this.config = normalizeAutomationConfig(config);
this._checkValidation();
} catch (err: any) {
const entity = this._entityRegistry.find(
@@ -761,34 +702,27 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
private _valueChanged(ev: ValueChangedEvent<AutomationConfig>) {
ev.stopPropagation();
if (this._config) {
this._undoRedoController.commit(this._config);
if (this.config) {
this._undoRedoController.commit(this.config);
}
this._config = ev.detail.value;
if (this._readOnly) {
this.config = ev.detail.value;
if (this.readOnly) {
return;
}
this._dirty = true;
this._errors = undefined;
this.dirty = true;
this.errors = undefined;
}
private _showInfo() {
if (!this.hass || !this._entityId) {
if (!this.hass || !this.currentEntityId) {
return;
}
fireEvent(this, "hass-more-info", { entityId: this._entityId });
}
private _showSettings() {
showMoreInfoDialog(this, {
entityId: this._entityId!,
view: "settings",
});
fireEvent(this, "hass-more-info", { entityId: this.currentEntityId });
}
private _editCategory() {
if (!this._registryEntry) {
if (!this.registryEntry) {
showAlertDialog(this, {
title: this.hass.localize(
"ui.panel.config.scene.picker.no_category_support"
@@ -801,36 +735,36 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
}
showAssignCategoryDialog(this, {
scope: "automation",
entityReg: this._registryEntry,
entityReg: this.registryEntry,
});
}
private async _showTrace() {
if (this._config?.id) {
const result = await this._confirmUnsavedChanged();
if (this.config?.id) {
const result = await this.confirmUnsavedChanged();
if (result) {
navigate(
`/config/automation/trace/${encodeURIComponent(this._config.id)}`
`/config/automation/trace/${encodeURIComponent(this.config.id)}`
);
}
}
}
private _runActions() {
if (!this.hass || !this._entityId) {
if (!this.hass || !this.currentEntityId) {
return;
}
triggerAutomationActions(
this.hass,
this.hass.states[this._entityId].entity_id
this.hass.states[this.currentEntityId].entity_id
);
}
private async _toggle(): Promise<void> {
if (!this.hass || !this._entityId) {
if (!this.hass || !this.currentEntityId) {
return;
}
const stateObj = this.hass.states[this._entityId];
const stateObj = this.hass.states[this.currentEntityId];
const service = stateObj.state === "off" ? "turn_on" : "turn_off";
await this.hass.callService("automation", service, {
entity_id: stateObj.entity_id,
@@ -838,42 +772,42 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
}
private _preprocessYaml() {
if (!this._config) {
if (!this.config) {
return {};
}
const cleanConfig: AutomationConfig = { ...this._config };
const cleanConfig: AutomationConfig = { ...this.config };
delete cleanConfig.id;
return cleanConfig;
}
private _yamlChanged(ev: CustomEvent) {
ev.stopPropagation();
this._dirty = true;
this.dirty = true;
if (!ev.detail.isValid) {
this._yamlErrors = ev.detail.errorMsg;
this.yamlErrors = ev.detail.errorMsg;
return;
}
this._yamlErrors = undefined;
this._config = {
id: this._config?.id,
this.yamlErrors = undefined;
this.config = {
id: this.config?.id,
...normalizeAutomationConfig(ev.detail.value),
};
this._errors = undefined;
this.errors = undefined;
}
private async _confirmUnsavedChanged(): Promise<boolean> {
if (!this._dirty) {
protected async confirmUnsavedChanged(): Promise<boolean> {
if (!this.dirty) {
return true;
}
return new Promise<boolean>((resolve) => {
showAutomationSaveDialog(this, {
config: this._config!,
config: this.config!,
domain: "automation",
updateConfig: async (config, entityRegistryUpdate) => {
this._config = config;
this._entityRegistryUpdate = entityRegistryUpdate;
this._dirty = true;
this.config = config;
this.entityRegistryUpdate = entityRegistryUpdate;
this.dirty = true;
this.requestUpdate();
const id = this.automationId || String(Date.now());
@@ -889,8 +823,8 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
},
onClose: () => resolve(false),
onDiscard: () => resolve(true),
entityRegistryUpdate: this._entityRegistryUpdate,
entityRegistryEntry: this._registryEntry,
entityRegistryUpdate: this.entityRegistryUpdate,
entityRegistryEntry: this.registryEntry,
title: this.hass.localize(
this.automationId
? "ui.panel.config.automation.editor.leave.unsaved_confirm_title"
@@ -906,15 +840,8 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
});
}
private _backTapped = async () => {
const result = await this._confirmUnsavedChanged();
if (result) {
afterNextRender(() => goBack("/config"));
}
};
private async _takeControl() {
const config = this._config as BlueprintAutomationConfig;
const config = this.config as BlueprintAutomationConfig;
try {
const result = await substituteBlueprint(
@@ -931,35 +858,20 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
description: config.description,
};
this._blueprintConfig = config;
this._config = newConfig;
if (this._mode === "yaml") {
this.renderRoot.querySelector("ha-yaml-editor")?.setValue(this._config);
this.blueprintConfig = config;
this.config = newConfig;
if (this.mode === "yaml") {
this.renderRoot.querySelector("ha-yaml-editor")?.setValue(this.config);
}
this._readOnly = true;
this._errors = undefined;
this.readOnly = true;
this.errors = undefined;
} catch (err: any) {
this._errors = err.message;
this.errors = err.message;
}
}
private _revertBlueprint() {
this._config = this._blueprintConfig;
if (this._mode === "yaml") {
this.renderRoot.querySelector("ha-yaml-editor")?.setValue(this._config);
}
this._blueprintConfig = undefined;
this._readOnly = false;
}
private _takeControlSave() {
this._readOnly = false;
this._dirty = true;
this._blueprintConfig = undefined;
}
private async _duplicate() {
const result = this._readOnly
const result = this.readOnly
? await showConfirmationDialog(this, {
title: this.hass.localize(
"ui.panel.config.automation.picker.migrate_automation"
@@ -968,12 +880,12 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
"ui.panel.config.automation.picker.migrate_automation_description"
),
})
: await this._confirmUnsavedChanged();
: await this.confirmUnsavedChanged();
if (result) {
showAutomationEditor({
...this._config,
...this.config,
id: undefined,
alias: this._readOnly ? this._config?.alias : undefined,
alias: this.readOnly ? this.config?.alias : undefined,
});
}
}
@@ -985,7 +897,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
),
text: this.hass.localize(
"ui.panel.config.automation.picker.delete_confirm_text",
{ name: this._config?.alias }
{ name: this.config?.alias }
),
confirmText: this.hass!.localize("ui.common.delete"),
destructive: true,
@@ -1001,43 +913,21 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
}
}
private async _switchUiMode() {
if (this._yamlErrors) {
const result = await showConfirmationDialog(this, {
text: html`${this.hass.localize(
"ui.panel.config.automation.editor.switch_ui_yaml_error"
)}<br /><br />${this._yamlErrors}`,
confirmText: this.hass!.localize("ui.common.continue"),
destructive: true,
dismissText: this.hass!.localize("ui.common.cancel"),
});
if (!result) {
return;
}
}
this._yamlErrors = undefined;
this._mode = "gui";
}
private _switchYamlMode() {
this._mode = "yaml";
}
private async _promptAutomationAlias(): Promise<boolean> {
return new Promise((resolve) => {
showAutomationSaveDialog(this, {
config: this._config!,
config: this.config!,
domain: "automation",
updateConfig: async (config, entityRegistryUpdate) => {
this._config = config;
this._entityRegistryUpdate = entityRegistryUpdate;
this._dirty = true;
this.config = config;
this.entityRegistryUpdate = entityRegistryUpdate;
this.dirty = true;
this.requestUpdate();
resolve(true);
},
onClose: () => resolve(false),
entityRegistryUpdate: this._entityRegistryUpdate,
entityRegistryEntry: this._registryEntry,
entityRegistryUpdate: this.entityRegistryUpdate,
entityRegistryEntry: this.registryEntry,
});
});
}
@@ -1045,10 +935,10 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
private async _promptAutomationMode(): Promise<void> {
return new Promise((resolve) => {
showAutomationModeDialog(this, {
config: this._config!,
config: this.config!,
updateConfig: (config) => {
this._config = config;
this._dirty = true;
this.config = config;
this.dirty = true;
this.requestUpdate();
resolve();
},
@@ -1058,9 +948,9 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
}
private async _handleSaveAutomation(): Promise<void> {
if (this._yamlErrors) {
if (this.yamlErrors) {
showToast(this, {
message: this._yamlErrors,
message: this.yamlErrors,
});
return;
}
@@ -1082,22 +972,22 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
}
private async _saveAutomation(id): Promise<void> {
this._saving = true;
this._validationErrors = undefined;
this.saving = true;
this.validationErrors = undefined;
let entityRegPromise: Promise<EntityRegistryEntry> | undefined;
if (this._entityRegistryUpdate !== undefined && !this._entityId) {
if (this.entityRegistryUpdate !== undefined && !this.currentEntityId) {
this._newAutomationId = id;
entityRegPromise = new Promise<EntityRegistryEntry>((resolve) => {
this._entityRegCreated = resolve;
this.entityRegCreated = resolve;
});
}
try {
await saveAutomationConfig(this.hass, id, this._config!);
await saveAutomationConfig(this.hass, id, this.config!);
if (this._entityRegistryUpdate !== undefined) {
let entityId = this._entityId;
if (this.entityRegistryUpdate !== undefined) {
let entityId = this.currentEntityId;
// wait for automation to appear in entity registry when creating a new automation
if (entityRegPromise) {
@@ -1131,23 +1021,23 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
if (entityId) {
await updateEntityRegistryEntry(this.hass, entityId, {
categories: {
automation: this._entityRegistryUpdate.category || null,
automation: this.entityRegistryUpdate.category || null,
},
labels: this._entityRegistryUpdate.labels || [],
area_id: this._entityRegistryUpdate.area || null,
labels: this.entityRegistryUpdate.labels || [],
area_id: this.entityRegistryUpdate.area || null,
});
}
}
this._dirty = false;
this.dirty = false;
} catch (errors: any) {
this._errors = errors.body?.message || errors.error || errors.body;
this.errors = errors.body?.message || errors.error || errors.body;
showToast(this, {
message: errors.body?.message || errors.error || errors.body,
});
throw errors;
} finally {
this._saving = false;
this.saving = false;
}
}
@@ -1157,7 +1047,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
ev.detail.unsub = () => {
delete this._configSubscriptions[id];
};
ev.detail.callback(this._config);
ev.detail.callback(this.config);
}
protected supportedShortcuts(): SupportedShortcuts {
@@ -1173,14 +1063,6 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
};
}
protected get isDirty() {
return this._dirty;
}
protected async promptDiscardChanges() {
return this._confirmUnsavedChanged();
}
// @ts-ignore
private _collapseAll() {
this._manualEditor?.collapseAll();
@@ -1205,8 +1087,8 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
private _applyUndoRedo(config: AutomationConfig) {
this._manualEditor?.triggerCloseSidebar();
this._config = config;
this._dirty = true;
this.config = config;
this.dirty = true;
}
private _undo() {
@@ -1235,7 +1117,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
this._showInfo();
break;
case "settings":
this._showSettings();
this.showSettings();
break;
case "category":
this._editCategory();
@@ -1256,11 +1138,11 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
this._takeControl();
break;
case "toggle_yaml_mode":
if (this._mode === "gui") {
this._switchYamlMode();
if (this.mode === "gui") {
this.switchYamlMode();
break;
}
this._switchUiMode();
this.switchUiMode();
break;
case "disable":
this._toggle();
@@ -1277,25 +1159,8 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
static get styles(): CSSResultGroup {
return [
haStyle,
automationScriptEditorStyles,
css`
:host {
--ha-automation-editor-max-width: var(
--ha-automation-editor-width,
1540px
);
}
ha-fade-in {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.yaml-mode {
height: 100%;
display: flex;
flex-direction: column;
padding-bottom: 0;
}
manual-automation-editor,
blueprint-automation-editor {
margin: 0 auto;
@@ -1309,17 +1174,6 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
padding: 0 12px;
}
ha-yaml-editor {
flex-grow: 1;
--actions-border-radius: var(--ha-border-radius-square);
--code-mirror-height: 100%;
min-height: 0;
display: flex;
flex-direction: column;
}
p {
margin-bottom: 0;
}
ha-entity-toggle {
margin-right: 8px;
margin-inline-end: 8px;
@@ -1335,24 +1189,6 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
max-width: 1040px;
padding: 28px 20px 0;
}
ha-fab {
position: fixed;
right: calc(16px + var(--safe-area-inset-right, 0px));
bottom: calc(-80px - var(--safe-area-inset-bottom));
transition: bottom 0.3s;
}
ha-fab.dirty {
bottom: calc(16px + var(--safe-area-inset-bottom, 0px));
}
ha-tooltip ha-svg-icon {
width: 12px;
}
ha-tooltip .shortcut {
display: inline-flex;
flex-direction: row;
align-items: center;
gap: 2px;
}
`,
];
}

View File

@@ -0,0 +1,199 @@
import { consume } from "@lit/context";
import type { CSSResult, TemplateResult, LitElement } from "lit";
import { css, html } from "lit";
import { property, state } from "lit/decorators";
import { transform } from "../../../common/decorators/transform";
import { goBack } from "../../../common/navigate";
import { afterNextRender } from "../../../common/util/render-status";
import { fullEntitiesContext } from "../../../data/context";
import type { EntityRegistryEntry } from "../../../data/entity/entity_registry";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog";
import type { Constructor, HomeAssistant, Route } from "../../../types";
import type { EntityRegistryUpdate } from "./automation-save-dialog/show-dialog-automation-save";
import "../../../components/ha-fade-in";
import "../../../components/ha-spinner"; // used by renderLoading() provided to both editors
/** Minimum config shape shared by both AutomationConfig and ScriptConfig. */
interface BaseEditorConfig {
alias?: string;
}
/** Shared CSS styles for both automation and script editors. */
export const automationScriptEditorStyles: CSSResult = css`
:host {
--ha-automation-editor-max-width: var(--ha-automation-editor-width, 1540px);
}
ha-fade-in {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.yaml-mode {
height: 100%;
display: flex;
flex-direction: column;
padding-bottom: 0;
}
ha-yaml-editor {
flex-grow: 1;
--actions-border-radius: var(--ha-border-radius-square);
--code-mirror-height: 100%;
min-height: 0;
display: flex;
flex-direction: column;
}
p {
margin-bottom: 0;
}
ha-fab {
position: fixed;
right: calc(16px + var(--safe-area-inset-right, 0px));
bottom: calc(-80px - var(--safe-area-inset-bottom));
transition: bottom 0.3s;
}
ha-fab.dirty {
bottom: calc(16px + var(--safe-area-inset-bottom, 0px));
}
ha-tooltip ha-svg-icon {
width: 12px;
}
ha-tooltip .shortcut {
display: inline-flex;
flex-direction: row;
align-items: center;
gap: 2px;
}
`;
export const AutomationScriptEditorMixin = <TConfig extends BaseEditorConfig>(
superClass: Constructor<LitElement>
) => {
class AutomationScriptEditorClass extends superClass {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
@property({ type: Boolean }) public narrow = false;
@property({ attribute: false }) public route!: Route;
@property({ attribute: false }) public entityId: string | null = null;
@state() protected dirty = false;
@state() protected errors?: string;
@state() protected yamlErrors?: string;
@state() protected currentEntityId?: string;
@state() protected mode: "gui" | "yaml" = "gui";
@state() protected readOnly = false;
@state() protected saving = false;
@state() protected validationErrors?: (string | TemplateResult)[];
@state() protected config?: TConfig;
@state() protected blueprintConfig?: TConfig;
@state()
@consume({ context: fullEntitiesContext, subscribe: true })
@transform<EntityRegistryEntry[], EntityRegistryEntry>({
transformer: function (this: { currentEntityId?: string }, value) {
return value.find(
({ entity_id }) => entity_id === this.currentEntityId
);
},
watch: ["currentEntityId"],
})
protected registryEntry?: EntityRegistryEntry;
protected entityRegistryUpdate?: EntityRegistryUpdate;
protected entityRegCreated?: (
value: PromiseLike<EntityRegistryEntry> | EntityRegistryEntry
) => void;
protected renderLoading(): TemplateResult {
return html`
<ha-fade-in .delay=${500}>
<ha-spinner size="large"></ha-spinner>
</ha-fade-in>
`;
}
protected showSettings() {
showMoreInfoDialog(this, {
entityId: this.currentEntityId!,
view: "settings",
});
}
protected async switchUiMode() {
if (this.yamlErrors) {
const result = await showConfirmationDialog(this, {
text: html`${this.hass.localize(
"ui.panel.config.automation.editor.switch_ui_yaml_error"
)}<br /><br />${this.yamlErrors}`,
confirmText: this.hass!.localize("ui.common.continue"),
destructive: true,
dismissText: this.hass!.localize("ui.common.cancel"),
});
if (!result) {
return;
}
}
this.yamlErrors = undefined;
this.mode = "gui";
}
protected switchYamlMode() {
this.mode = "yaml";
}
protected takeControlSave() {
this.readOnly = false;
this.dirty = true;
this.blueprintConfig = undefined;
}
protected revertBlueprint() {
this.config = this.blueprintConfig;
if (this.mode === "yaml") {
this.renderRoot.querySelector("ha-yaml-editor")?.setValue(this.config);
}
this.blueprintConfig = undefined;
this.readOnly = false;
}
protected backTapped = async () => {
const result = await this.confirmUnsavedChanged();
if (result) {
afterNextRender(() => goBack("/config"));
}
};
protected get isDirty() {
return this.dirty;
}
protected async promptDiscardChanges() {
return this.confirmUnsavedChanged();
}
/**
* Asks whether unsaved changes should be discarded.
* Subclasses must override this to show a confirmation dialog.
* @returns true to proceed (discard/save changes), false to cancel.
*/
protected confirmUnsavedChanged(): Promise<boolean> {
return Promise.resolve(true);
}
}
return AutomationScriptEditorClass;
};

View File

@@ -1,5 +1,4 @@
import "@home-assistant/webawesome/dist/components/divider/divider";
import { consume } from "@lit/context";
import {
mdiAppleKeyboardCommand,
mdiCog,
@@ -22,15 +21,13 @@ import {
} from "@mdi/js";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { customElement, property, query } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { UndoRedoController } from "../../../common/controllers/undo-redo-controller";
import { transform } from "../../../common/decorators/transform";
import { fireEvent } from "../../../common/dom/fire_event";
import { goBack, navigate } from "../../../common/navigate";
import { slugify } from "../../../common/string/slugify";
import { promiseTimeout } from "../../../common/util/promise-timeout";
import { afterNextRender } from "../../../common/util/render-status";
import "../../../components/ha-button";
import "../../../components/ha-dropdown";
import "../../../components/ha-dropdown-item";
@@ -40,7 +37,6 @@ import "../../../components/ha-svg-icon";
import "../../../components/ha-yaml-editor";
import { substituteBlueprint } from "../../../data/blueprint";
import { validateConfig } from "../../../data/config";
import { fullEntitiesContext } from "../../../data/context";
import { UNAVAILABLE } from "../../../data/entity/entity";
import {
type EntityRegistryEntry,
@@ -67,88 +63,47 @@ import { KeyboardShortcutMixin } from "../../../mixins/keyboard-shortcut-mixin";
import { PreventUnsavedMixin } from "../../../mixins/prevent-unsaved-mixin";
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import { haStyle } from "../../../resources/styles";
import type { Entries, HomeAssistant, Route } from "../../../types";
import type { Entries } from "../../../types";
import { isMac } from "../../../util/is_mac";
import { showToast } from "../../../util/toast";
import { showAutomationModeDialog } from "../automation/automation-mode-dialog/show-dialog-automation-mode";
import type { EntityRegistryUpdate } from "../automation/automation-save-dialog/show-dialog-automation-save";
import { showAutomationSaveDialog } from "../automation/automation-save-dialog/show-dialog-automation-save";
import { showAutomationSaveTimeoutDialog } from "../automation/automation-save-timeout-dialog/show-dialog-automation-save-timeout";
import { showAssignCategoryDialog } from "../category/show-dialog-assign-category";
import "./blueprint-script-editor";
import {
AutomationScriptEditorMixin,
automationScriptEditorStyles,
} from "../automation/ha-automation-script-editor-mixin";
import "./manual-script-editor";
import type { HaManualScriptEditor } from "./manual-script-editor";
import type { HaDropdownSelectEvent } from "../../../components/ha-dropdown";
@customElement("ha-script-editor")
export class HaScriptEditor extends SubscribeMixin(
PreventUnsavedMixin(KeyboardShortcutMixin(LitElement))
AutomationScriptEditorMixin<ScriptConfig>(
PreventUnsavedMixin(KeyboardShortcutMixin(LitElement))
)
) {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public scriptId: string | null = null;
@property({ attribute: false }) public entityId: string | null = null;
@property({ attribute: false }) public entityRegistry!: EntityRegistryEntry[];
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
@property({ type: Boolean }) public narrow = false;
@property({ attribute: false }) public route!: Route;
@state() private _config?: ScriptConfig;
@state() private _dirty = false;
@state() private _errors?: string;
@state() private _yamlErrors?: string;
@state() private _entityId?: string;
@state() private _mode: "gui" | "yaml" = "gui";
@state() private _readOnly = false;
@state()
@consume({ context: fullEntitiesContext, subscribe: true })
@transform<EntityRegistryEntry[], EntityRegistryEntry>({
transformer: function (this: HaScriptEditor, value) {
return value.find(({ entity_id }) => entity_id === this._entityId);
},
watch: ["_entityId"],
})
private _registryEntry?: EntityRegistryEntry;
@query("manual-script-editor")
private _manualEditor?: HaManualScriptEditor;
@state() private _validationErrors?: (string | TemplateResult)[];
@state() private _blueprintConfig?: BlueprintScriptConfig;
@state() private _saving = false;
private _entityRegistryUpdate?: EntityRegistryUpdate;
private _newScriptId?: string;
private _entityRegCreated?: (
value: PromiseLike<EntityRegistryEntry> | EntityRegistryEntry
) => void;
private _undoRedoController = new UndoRedoController<ScriptConfig>(this, {
apply: (config) => this._applyUndoRedo(config),
currentConfig: () => this._config!,
currentConfig: () => this.config!,
});
protected willUpdate(changedProps) {
super.willUpdate(changedProps);
if (
this._entityRegCreated &&
this.entityRegCreated &&
this._newScriptId &&
changedProps.has("entityRegistry")
) {
@@ -157,22 +112,22 @@ export class HaScriptEditor extends SubscribeMixin(
entity.platform === "script" && entity.unique_id === this._newScriptId
);
if (script) {
this._entityRegCreated(script);
this._entityRegCreated = undefined;
this.entityRegCreated(script);
this.entityRegCreated = undefined;
}
}
}
protected render(): TemplateResult | typeof nothing {
if (!this._config) {
return nothing;
if (!this.config) {
return this.renderLoading();
}
const stateObj = this._entityId
? this.hass.states[this._entityId]
const stateObj = this.currentEntityId
? this.hass.states[this.currentEntityId]
: undefined;
const useBlueprint = "use_blueprint" in this._config;
const useBlueprint = "use_blueprint" in this.config;
const shortcutIcon = isMac
? html`<ha-svg-icon .path=${mdiAppleKeyboardCommand}></ha-svg-icon>`
: this.hass.localize("ui.panel.config.automation.editor.ctrl");
@@ -182,11 +137,11 @@ export class HaScriptEditor extends SubscribeMixin(
.hass=${this.hass}
.narrow=${this.narrow}
.route=${this.route}
.backCallback=${this._backTapped}
.header=${this._config.alias ||
.backCallback=${this.backTapped}
.header=${this.config.alias ||
this.hass.localize("ui.panel.config.script.editor.default_name")}
>
${this._mode === "gui" && !this.narrow
${this.mode === "gui" && !this.narrow
? html`<ha-icon-button
slot="toolbar-icon"
.label=${this.hass.localize("ui.common.undo")}
@@ -252,7 +207,7 @@ export class HaScriptEditor extends SubscribeMixin(
.path=${mdiDotsVertical}
></ha-icon-button>
${this._mode === "gui" && this.narrow
${this.mode === "gui" && this.narrow
? html`<ha-dropdown-item
value="undo"
.disabled=${!this._undoRedoController.canUndo}
@@ -286,7 +241,7 @@ export class HaScriptEditor extends SubscribeMixin(
<ha-dropdown-item .disabled=${!stateObj} value="category">
${this.hass.localize(
`ui.panel.config.scene.picker.${this._registryEntry?.categories?.script ? "edit_category" : "assign_category"}`
`ui.panel.config.scene.picker.${this.registryEntry?.categories?.script ? "edit_category" : "assign_category"}`
)}
<ha-svg-icon slot="icon" .path=${mdiTag}></ha-svg-icon>
</ha-dropdown-item>
@@ -307,10 +262,10 @@ export class HaScriptEditor extends SubscribeMixin(
></ha-svg-icon>
</ha-dropdown-item>`
: nothing}
${!useBlueprint && !("fields" in this._config)
${!useBlueprint && !("fields" in this.config)
? html`
<ha-dropdown-item
.disabled=${this._readOnly || this._mode === "yaml"}
.disabled=${this.readOnly || this.mode === "yaml"}
value="add_fields"
>
${this.hass.localize(
@@ -326,9 +281,7 @@ export class HaScriptEditor extends SubscribeMixin(
<ha-dropdown-item
value="rename"
.disabled=${!this.scriptId ||
this._readOnly ||
this._mode === "yaml"}
.disabled=${!this.scriptId || this.readOnly || this.mode === "yaml"}
>
${this.hass.localize("ui.panel.config.script.editor.rename")}
<ha-svg-icon slot="icon" .path=${mdiRenameBox}></ha-svg-icon>
@@ -337,7 +290,7 @@ export class HaScriptEditor extends SubscribeMixin(
? html`
<ha-dropdown-item
value="change_mode"
.disabled=${this._readOnly || this._mode === "yaml"}
.disabled=${this.readOnly || this.mode === "yaml"}
>
${this.hass.localize(
"ui.panel.config.script.editor.change_mode"
@@ -351,12 +304,12 @@ export class HaScriptEditor extends SubscribeMixin(
: nothing}
<ha-dropdown-item
.disabled=${!!this._blueprintConfig ||
(!this._readOnly && !this.scriptId)}
.disabled=${!!this.blueprintConfig ||
(!this.readOnly && !this.scriptId)}
value="duplicate"
>
${this.hass.localize(
this._readOnly
this.readOnly
? "ui.panel.config.script.editor.migrate"
: "ui.panel.config.script.editor.duplicate"
)}
@@ -370,7 +323,7 @@ export class HaScriptEditor extends SubscribeMixin(
? html`
<ha-dropdown-item
value="take_control"
.disabled=${this._readOnly}
.disabled=${this.readOnly}
>
${this.hass.localize(
"ui.panel.config.script.editor.take_control"
@@ -382,7 +335,7 @@ export class HaScriptEditor extends SubscribeMixin(
<ha-dropdown-item value="toggle_yaml_mode">
${this.hass.localize(
`ui.panel.config.automation.editor.edit_${this._mode === "gui" ? "yaml" : "ui"}`
`ui.panel.config.automation.editor.edit_${this.mode === "gui" ? "yaml" : "ui"}`
)}
<ha-svg-icon slot="icon" .path=${mdiPlaylistEdit}></ha-svg-icon>
</ha-dropdown-item>
@@ -390,7 +343,7 @@ export class HaScriptEditor extends SubscribeMixin(
<wa-divider></wa-divider>
<ha-dropdown-item
.disabled=${this._readOnly || !this.scriptId}
.disabled=${this.readOnly || !this.scriptId}
value="delete"
.variant=${this.scriptId ? "danger" : "default"}
>
@@ -403,8 +356,8 @@ export class HaScriptEditor extends SubscribeMixin(
</ha-svg-icon>
</ha-dropdown-item>
</ha-dropdown>
<div class=${this._mode === "yaml" ? "yaml-mode" : ""}>
${this._mode === "gui"
<div class=${this.mode === "yaml" ? "yaml-mode" : ""}>
${this.mode === "gui"
? html`
<div>
${useBlueprint
@@ -413,10 +366,10 @@ export class HaScriptEditor extends SubscribeMixin(
.hass=${this.hass}
.narrow=${this.narrow}
.isWide=${this.isWide}
.config=${this._config}
.disabled=${this._readOnly}
.saving=${this._saving}
.dirty=${this._dirty}
.config=${this.config}
.disabled=${this.readOnly}
.saving=${this.saving}
.dirty=${this.dirty}
@value-changed=${this._valueChanged}
@save-script=${this._handleSaveScript}
></blueprint-script-editor>
@@ -426,16 +379,16 @@ export class HaScriptEditor extends SubscribeMixin(
.hass=${this.hass}
.narrow=${this.narrow}
.isWide=${this.isWide}
.config=${this._config}
.disabled=${this._readOnly}
.dirty=${this._dirty}
.saving=${this._saving}
.config=${this.config}
.disabled=${this.readOnly}
.dirty=${this.dirty}
.saving=${this.saving}
@value-changed=${this._valueChanged}
@editor-save=${this._handleSaveScript}
@save-script=${this._handleSaveScript}
>
<div class="alert-wrapper" slot="alerts">
${this._errors || stateObj?.state === UNAVAILABLE
${this.errors || stateObj?.state === UNAVAILABLE
? html`<ha-alert
alert-type="error"
.title=${stateObj?.state === UNAVAILABLE
@@ -444,7 +397,7 @@ export class HaScriptEditor extends SubscribeMixin(
)
: undefined}
>
${this._errors || this._validationErrors}
${this.errors || this.validationErrors}
${stateObj?.state === UNAVAILABLE
? html`<ha-svg-icon
slot="icon"
@@ -453,7 +406,7 @@ export class HaScriptEditor extends SubscribeMixin(
: nothing}
</ha-alert>`
: nothing}
${this._blueprintConfig
${this.blueprintConfig
? html`<ha-alert alert-type="info">
${this.hass.localize(
"ui.panel.config.script.editor.confirm_take_control"
@@ -461,21 +414,21 @@ export class HaScriptEditor extends SubscribeMixin(
<div slot="action" style="display: flex;">
<ha-button
appearance="plain"
@click=${this._takeControlSave}
@click=${this.takeControlSave}
>${this.hass.localize(
"ui.common.yes"
)}</ha-button
>
<ha-button
appearance="plain"
@click=${this._revertBlueprint}
@click=${this.revertBlueprint}
>${this.hass.localize(
"ui.common.no"
)}</ha-button
>
</div>
</ha-alert>`
: this._readOnly
: this.readOnly
? html`<ha-alert
alert-type="warning"
dismissable
@@ -498,11 +451,11 @@ export class HaScriptEditor extends SubscribeMixin(
`}
</div>
`
: this._mode === "yaml"
: this.mode === "yaml"
? html`<ha-yaml-editor
.hass=${this.hass}
.defaultValue=${this._preprocessYaml()}
.readOnly=${this._readOnly}
.readOnly=${this.readOnly}
disable-fullscreen
@value-changed=${this._yamlChanged}
@editor-save=${this._handleSaveScript}
@@ -510,9 +463,9 @@ export class HaScriptEditor extends SubscribeMixin(
></ha-yaml-editor>
<ha-fab
slot="fab"
class=${!this._readOnly && this._dirty ? "dirty" : ""}
class=${!this.readOnly && this.dirty ? "dirty" : ""}
.label=${this.hass.localize("ui.common.save")}
.disabled=${this._saving}
.disabled=${this.saving}
extended
@click=${this._handleSaveScript}
>
@@ -551,26 +504,26 @@ export class HaScriptEditor extends SubscribeMixin(
const entity = this.entityRegistry.find(
(ent) => ent.platform === "script" && ent.unique_id === this.scriptId
);
this._entityId = entity?.entity_id;
this.currentEntityId = entity?.entity_id;
}
if (changedProps.has("scriptId") && !this.scriptId && this.hass) {
const initData = getScriptEditorInitData();
this._dirty = !!initData;
this.dirty = !!initData;
const baseConfig: Partial<ScriptConfig> = {};
if (!initData || !("use_blueprint" in initData)) {
baseConfig.sequence = [];
}
this._config = {
this.config = {
...baseConfig,
...initData,
} as ScriptConfig;
this._readOnly = false;
this.readOnly = false;
}
if (changedProps.has("entityId") && this.entityId) {
getScriptStateConfig(this.hass, this.entityId).then((c) => {
this._config = normalizeScriptConfig(c.config);
this.config = normalizeScriptConfig(c.config);
this._checkValidation();
});
const regEntry = this.entityRegistry.find(
@@ -579,25 +532,25 @@ export class HaScriptEditor extends SubscribeMixin(
if (regEntry?.unique_id) {
this.scriptId = regEntry.unique_id;
}
this._entityId = this.entityId;
this._dirty = false;
this._readOnly = true;
this.currentEntityId = this.entityId;
this.dirty = false;
this.readOnly = true;
}
}
private async _checkValidation() {
this._validationErrors = undefined;
if (!this._entityId || !this._config) {
this.validationErrors = undefined;
if (!this.currentEntityId || !this.config) {
return;
}
const stateObj = this.hass.states[this._entityId];
const stateObj = this.hass.states[this.currentEntityId];
if (stateObj?.state !== UNAVAILABLE) {
return;
}
const validation = await validateConfig(this.hass, {
actions: this._config.sequence,
actions: this.config.sequence,
});
this._validationErrors = (
this.validationErrors = (
Object.entries(validation) as Entries<typeof validation>
).map(([key, value]) =>
value.valid
@@ -612,13 +565,13 @@ export class HaScriptEditor extends SubscribeMixin(
private async _loadConfig() {
fetchScriptFileConfig(this.hass, this.scriptId!).then(
(config) => {
this._dirty = false;
this._readOnly = false;
this._config = normalizeScriptConfig(config);
this.dirty = false;
this.readOnly = false;
this.config = normalizeScriptConfig(config);
const entity = this.entityRegistry.find(
(ent) => ent.platform === "script" && ent.unique_id === this.scriptId
);
this._entityId = entity?.entity_id;
this.currentEntityId = entity?.entity_id;
this._checkValidation();
},
(resp) => {
@@ -647,19 +600,19 @@ export class HaScriptEditor extends SubscribeMixin(
}
private _valueChanged(ev) {
if (this._config) {
this._undoRedoController.commit(this._config);
if (this.config) {
this._undoRedoController.commit(this.config);
}
this._config = ev.detail.value;
this._errors = undefined;
this._dirty = true;
this.config = ev.detail.value;
this.errors = undefined;
this.dirty = true;
}
private async _runScript() {
if (hasScriptFields(this.hass, this._entityId!)) {
if (hasScriptFields(this.hass, this.currentEntityId!)) {
showMoreInfoDialog(this, {
entityId: this._entityId!,
entityId: this.currentEntityId!,
});
return;
}
@@ -667,20 +620,13 @@ export class HaScriptEditor extends SubscribeMixin(
await triggerScript(this.hass, this.scriptId!);
showToast(this, {
message: this.hass.localize("ui.notification_toast.triggered", {
name: this._config!.alias,
name: this.config!.alias,
}),
});
}
private _showSettings() {
showMoreInfoDialog(this, {
entityId: this._entityId!,
view: "settings",
});
}
private _editCategory() {
if (!this._registryEntry) {
if (!this.registryEntry) {
showAlertDialog(this, {
title: this.hass.localize(
"ui.panel.config.scene.picker.no_category_support"
@@ -693,7 +639,7 @@ export class HaScriptEditor extends SubscribeMixin(
}
showAssignCategoryDialog(this, {
scope: "script",
entityReg: this._registryEntry,
entityReg: this.registryEntry,
});
}
@@ -730,7 +676,7 @@ export class HaScriptEditor extends SubscribeMixin(
private async _showTrace() {
if (this.scriptId) {
const result = await this._confirmUnsavedChanged();
const result = await this.confirmUnsavedChanged();
if (result) {
navigate(`/config/script/trace/${this.scriptId}`);
}
@@ -738,47 +684,47 @@ export class HaScriptEditor extends SubscribeMixin(
}
private _addFields() {
if ("fields" in this._config!) {
if ("fields" in this.config!) {
return;
}
if (this._config) {
this._undoRedoController.commit(this._config);
if (this.config) {
this._undoRedoController.commit(this.config);
}
this._manualEditor?.addFields();
this._dirty = true;
this.dirty = true;
}
private _preprocessYaml() {
return this._config;
return this.config;
}
private _yamlChanged(ev: CustomEvent) {
ev.stopPropagation();
this._dirty = true;
this.dirty = true;
if (!ev.detail.isValid) {
this._yamlErrors = ev.detail.errorMsg;
this.yamlErrors = ev.detail.errorMsg;
return;
}
this._yamlErrors = undefined;
this._config = ev.detail.value;
this._errors = undefined;
this.yamlErrors = undefined;
this.config = ev.detail.value;
this.errors = undefined;
}
private async _confirmUnsavedChanged(): Promise<boolean> {
if (!this._dirty) {
protected async confirmUnsavedChanged(): Promise<boolean> {
if (!this.dirty) {
return true;
}
return new Promise<boolean>((resolve) => {
showAutomationSaveDialog(this, {
config: this._config!,
config: this.config!,
domain: "script",
updateConfig: async (config, entityRegistryUpdate) => {
this._config = config;
this._entityRegistryUpdate = entityRegistryUpdate;
this._dirty = true;
this.config = config;
this.entityRegistryUpdate = entityRegistryUpdate;
this.dirty = true;
this.requestUpdate();
const id = this.scriptId || String(Date.now());
@@ -794,8 +740,8 @@ export class HaScriptEditor extends SubscribeMixin(
},
onClose: () => resolve(false),
onDiscard: () => resolve(true),
entityRegistryUpdate: this._entityRegistryUpdate,
entityRegistryEntry: this._registryEntry,
entityRegistryUpdate: this.entityRegistryUpdate,
entityRegistryEntry: this.registryEntry,
title: this.hass.localize(
this.scriptId
? "ui.panel.config.script.editor.leave.unsaved_confirm_title"
@@ -811,15 +757,8 @@ export class HaScriptEditor extends SubscribeMixin(
});
}
private _backTapped = async () => {
const result = await this._confirmUnsavedChanged();
if (result) {
afterNextRender(() => goBack("/config"));
}
};
private async _takeControl() {
const config = this._config as BlueprintScriptConfig;
const config = this.config as BlueprintScriptConfig;
try {
const result = await substituteBlueprint(
@@ -835,35 +774,20 @@ export class HaScriptEditor extends SubscribeMixin(
description: config.description,
};
this._blueprintConfig = config;
this._config = newConfig;
if (this._mode === "yaml") {
this.renderRoot.querySelector("ha-yaml-editor")?.setValue(this._config);
this.blueprintConfig = config;
this.config = newConfig;
if (this.mode === "yaml") {
this.renderRoot.querySelector("ha-yaml-editor")?.setValue(this.config);
}
this._readOnly = true;
this._errors = undefined;
this.readOnly = true;
this.errors = undefined;
} catch (err: any) {
this._errors = err.message;
this.errors = err.message;
}
}
private _revertBlueprint() {
this._config = this._blueprintConfig;
if (this._mode === "yaml") {
this.renderRoot.querySelector("ha-yaml-editor")?.setValue(this._config);
}
this._blueprintConfig = undefined;
this._readOnly = false;
}
private _takeControlSave() {
this._readOnly = false;
this._dirty = true;
this._blueprintConfig = undefined;
}
private async _duplicate() {
const result = this._readOnly
const result = this.readOnly
? await showConfirmationDialog(this, {
title: this.hass.localize(
"ui.panel.config.script.picker.migrate_script"
@@ -872,14 +796,14 @@ export class HaScriptEditor extends SubscribeMixin(
"ui.panel.config.script.picker.migrate_script_description"
),
})
: await this._confirmUnsavedChanged();
: await this.confirmUnsavedChanged();
if (result) {
this._entityId = undefined;
this.currentEntityId = undefined;
showScriptEditor({
...this._config,
alias: this._readOnly
? this._config?.alias
: `${this._config?.alias} (${this.hass.localize(
...this.config,
alias: this.readOnly
? this.config?.alias
: `${this.config?.alias} (${this.hass.localize(
"ui.panel.config.script.picker.duplicate"
)})`,
});
@@ -893,7 +817,7 @@ export class HaScriptEditor extends SubscribeMixin(
),
text: this.hass.localize(
"ui.panel.config.script.editor.delete_confirm_text",
{ name: this._config?.alias }
{ name: this.config?.alias }
),
confirmText: this.hass!.localize("ui.common.delete"),
destructive: true,
@@ -907,42 +831,20 @@ export class HaScriptEditor extends SubscribeMixin(
goBack("/config");
}
private async _switchUiMode() {
if (this._yamlErrors) {
const result = await showConfirmationDialog(this, {
text: html`${this.hass.localize(
"ui.panel.config.automation.editor.switch_ui_yaml_error"
)}<br /><br />${this._yamlErrors}`,
confirmText: this.hass!.localize("ui.common.continue"),
destructive: true,
dismissText: this.hass!.localize("ui.common.cancel"),
});
if (!result) {
return;
}
}
this._yamlErrors = undefined;
this._mode = "gui";
}
private _switchYamlMode() {
this._mode = "yaml";
}
private async _promptScriptAlias(): Promise<boolean> {
return new Promise((resolve) => {
showAutomationSaveDialog(this, {
config: this._config!,
config: this.config!,
domain: "script",
updateConfig: async (config, entityRegistryUpdate) => {
this._config = config;
this._entityRegistryUpdate = entityRegistryUpdate;
this._dirty = true;
this.config = config;
this.entityRegistryUpdate = entityRegistryUpdate;
this.dirty = true;
this.requestUpdate();
resolve(true);
},
onClose: () => resolve(false),
entityRegistryUpdate: this._entityRegistryUpdate,
entityRegistryUpdate: this.entityRegistryUpdate,
entityRegistryEntry: this.entityRegistry.find(
(entry) => entry.unique_id === this.scriptId
),
@@ -953,10 +855,10 @@ export class HaScriptEditor extends SubscribeMixin(
private async _promptScriptMode(): Promise<void> {
return new Promise((resolve) => {
showAutomationModeDialog(this, {
config: this._config!,
config: this.config!,
updateConfig: (config) => {
this._config = config;
this._dirty = true;
this.config = config;
this.dirty = true;
this.requestUpdate();
resolve();
},
@@ -966,9 +868,9 @@ export class HaScriptEditor extends SubscribeMixin(
}
private async _handleSaveScript() {
if (this._yamlErrors) {
if (this.yamlErrors) {
showToast(this, {
message: this._yamlErrors,
message: this.yamlErrors,
});
return;
}
@@ -980,9 +882,9 @@ export class HaScriptEditor extends SubscribeMixin(
if (!saved) {
return;
}
this._entityId = this._computeEntityIdFromAlias(this._config!.alias);
this.currentEntityId = this._computeEntityIdFromAlias(this.config!.alias);
}
const id = this.scriptId || this._entityId || Date.now();
const id = this.scriptId || this.currentEntityId || Date.now();
await this._saveScript(id);
if (!this.scriptId) {
@@ -991,13 +893,13 @@ export class HaScriptEditor extends SubscribeMixin(
}
private async _saveScript(id): Promise<void> {
this._saving = true;
this.saving = true;
let entityRegPromise: Promise<EntityRegistryEntry> | undefined;
if (this._entityRegistryUpdate !== undefined && !this.scriptId) {
if (this.entityRegistryUpdate !== undefined && !this.scriptId) {
this._newScriptId = id.toString();
entityRegPromise = new Promise<EntityRegistryEntry>((resolve) => {
this._entityRegCreated = resolve;
this.entityRegCreated = resolve;
});
}
@@ -1005,11 +907,11 @@ export class HaScriptEditor extends SubscribeMixin(
await this.hass!.callApi(
"POST",
"config/script/config/" + id,
this._config
this.config
);
if (this._entityRegistryUpdate !== undefined) {
let entityId = this._entityId;
if (this.entityRegistryUpdate !== undefined) {
let entityId = this.currentEntityId;
// wait for new script to appear in entity registry
if (entityRegPromise) {
@@ -1044,23 +946,23 @@ export class HaScriptEditor extends SubscribeMixin(
if (entityId) {
await updateEntityRegistryEntry(this.hass, entityId, {
categories: {
script: this._entityRegistryUpdate.category || null,
script: this.entityRegistryUpdate.category || null,
},
labels: this._entityRegistryUpdate.labels || [],
area_id: this._entityRegistryUpdate.area || null,
labels: this.entityRegistryUpdate.labels || [],
area_id: this.entityRegistryUpdate.area || null,
});
}
}
this._dirty = false;
this.dirty = false;
} catch (errors: any) {
this._errors = errors.body?.message || errors.error || errors.body;
this.errors = errors.body?.message || errors.error || errors.body;
showToast(this, {
message: errors.body?.message || errors.error || errors.body,
});
throw errors;
} finally {
this._saving = false;
this.saving = false;
}
}
@@ -1077,14 +979,6 @@ export class HaScriptEditor extends SubscribeMixin(
};
}
protected get isDirty() {
return this._dirty;
}
protected async promptDiscardChanges() {
return this._confirmUnsavedChanged();
}
// @ts-ignore
private _collapseAll() {
this._manualEditor?.collapseAll();
@@ -1109,8 +1003,8 @@ export class HaScriptEditor extends SubscribeMixin(
private _applyUndoRedo(config: ScriptConfig) {
this._manualEditor?.triggerCloseSidebar();
this._config = config;
this._dirty = true;
this.config = config;
this.dirty = true;
}
private _undo() {
@@ -1139,7 +1033,7 @@ export class HaScriptEditor extends SubscribeMixin(
this._showInfo();
break;
case "settings":
this._showSettings();
this.showSettings();
break;
case "category":
this._editCategory();
@@ -1163,11 +1057,11 @@ export class HaScriptEditor extends SubscribeMixin(
this._takeControl();
break;
case "toggle_yaml_mode":
if (this._mode === "gui") {
this._switchYamlMode();
if (this.mode === "gui") {
this.switchYamlMode();
break;
}
this._switchUiMode();
this.switchUiMode();
break;
case "delete":
this._deleteConfirm();
@@ -1181,19 +1075,8 @@ export class HaScriptEditor extends SubscribeMixin(
static get styles(): CSSResultGroup {
return [
haStyle,
automationScriptEditorStyles,
css`
:host {
--ha-automation-editor-max-width: var(
--ha-automation-editor-width,
1540px
);
}
.yaml-mode {
height: 100%;
display: flex;
flex-direction: column;
padding-bottom: 0;
}
manual-script-editor,
blueprint-script-editor {
margin: 0 auto;
@@ -1244,29 +1127,9 @@ export class HaScriptEditor extends SubscribeMixin(
padding: 0 12px;
}
ha-yaml-editor {
flex-grow: 1;
--actions-border-radius: var(--ha-border-radius-square);
--code-mirror-height: 100%;
min-height: 0;
display: flex;
flex-direction: column;
}
p {
margin-bottom: 0;
}
span[slot="introduction"] a {
color: var(--primary-color);
}
ha-fab {
position: fixed;
right: 16px;
bottom: calc(-80px - var(--safe-area-inset-bottom));
transition: bottom 0.3s;
}
ha-fab.dirty {
bottom: calc(16px + var(--safe-area-inset-bottom, 0px));
}
.header {
display: flex;
margin: 16px 0;
@@ -1280,15 +1143,6 @@ export class HaScriptEditor extends SubscribeMixin(
.header a {
color: var(--secondary-text-color);
}
ha-tooltip ha-svg-icon {
width: 12px;
}
ha-tooltip .shortcut {
display: inline-flex;
flex-direction: row;
align-items: center;
gap: 2px;
}
`,
];
}

View File

@@ -239,28 +239,15 @@ export class LovelacePanel extends LitElement {
const newConfig = checkLovelaceConfig(generatedConfig) as LovelaceConfig;
// Ask to regenerate if the config changed
// Regenerate if the config changed
if (!deepEqual(newConfig, oldConfig)) {
this._askRegenerateStrategyConfig();
this._regenerateStrategyConfig();
}
};
private _strategyConfigChanged = (ev: CustomEvent) => {
ev.stopPropagation();
this._askRegenerateStrategyConfig();
};
private _askRegenerateStrategyConfig = () => {
showToast(this, {
message: this.hass!.localize("ui.panel.lovelace.changed_toast.message"),
action: {
action: () => this._regenerateStrategyConfig(),
text: this.hass!.localize("ui.common.refresh"),
},
duration: -1,
id: "regenerate-strategy-config",
dismissable: false,
});
this._regenerateStrategyConfig();
};
private async _regenerateStrategyConfig() {
@@ -313,8 +300,14 @@ export class LovelacePanel extends LitElement {
this._fetchConfigOnConnect = true;
return;
}
if (!this.lovelace?.editMode && this._panelState !== "yaml-editor") {
this._fetchConfig(false);
return;
}
showToast(this, {
message: this.hass!.localize("ui.panel.lovelace.changed_toast.message"),
message: this.hass!.localize(
"ui.panel.lovelace.externally_updated_toast.message"
),
action: {
action: () => this._fetchConfig(false),
text: this.hass!.localize("ui.common.refresh"),

View File

@@ -7,21 +7,20 @@ import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { array, assert, object, optional, string, type } from "superstruct";
import { deepEqual } from "../../common/util/deep-equal";
import "../../components/ha-button";
import "../../components/ha-code-editor";
import type { HaCodeEditor } from "../../components/ha-code-editor";
import "../../components/ha-icon-button";
import "../../components/ha-button";
import "../../components/ha-top-app-bar-fixed";
import type { LovelaceRawConfig } from "../../data/lovelace/config/types";
import { isStrategyDashboard } from "../../data/lovelace/config/types";
import {
showAlertDialog,
showConfirmationDialog,
} from "../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
import { showToast } from "../../util/toast";
import type { Lovelace } from "./types";
import "../../components/ha-top-app-bar-fixed";
import type { LovelaceRawConfig } from "../../data/lovelace/config/types";
import { isStrategyDashboard } from "../../data/lovelace/config/types";
const lovelaceStruct = type({
title: optional(string()),
@@ -113,21 +112,7 @@ class LovelaceFullConfigEditor extends LitElement {
oldLovelace.rawConfig !== this.lovelace.rawConfig &&
!deepEqual(oldLovelace.rawConfig, this.lovelace.rawConfig)
) {
showToast(this, {
message: this.hass!.localize(
"ui.panel.lovelace.editor.raw_editor.lovelace_changed"
),
action: {
action: () => {
this.yamlEditor.value = dump(this.lovelace!.rawConfig);
},
text: this.hass!.localize(
"ui.panel.lovelace.editor.raw_editor.reload"
),
},
duration: -1,
dismissable: false,
});
this.yamlEditor.value = dump(this.lovelace!.rawConfig);
}
}

View File

@@ -186,24 +186,10 @@ export const haStyleDialog = css`
var(--safe-area-inset-right, 0) var(--safe-area-inset-bottom, 0)
var(--safe-area-inset-left, 0);
--vertical-align-dialog: flex-end;
}
ha-dialog {
--ha-dialog-border-radius: var(--ha-border-radius-square);
ha-dialog,
ha-adaptive-dialog {
--mdc-dialog-min-width: 100vw;
--mdc-dialog-max-width: 100vw;
--mdc-dialog-min-height: 100vh;
--mdc-dialog-min-height: 100svh;
--mdc-dialog-max-height: 100vh;
--mdc-dialog-max-height: 100svh;
--dialog-container-padding: 0px;
--dialog-surface-padding: var(--safe-area-inset-top, 0)
var(--safe-area-inset-right, 0) var(--safe-area-inset-bottom, 0)
var(--safe-area-inset-left, 0);
--vertical-align-dialog: flex-end;
}
ha-dialog {
--ha-dialog-border-radius: var(--ha-border-radius-square);
}
}
}
.error {
color: var(--error-color);

View File

@@ -548,7 +548,7 @@
},
"template": {
"yaml_warning": "It appears you may be writing YAML into this template field (saw ''{string}''), which is likely incorrect. This field is intended for templates only (e.g. '{{ states(sensor.test) > 0 }}' ).",
"learn_more": "Learn more about templating."
"learn_more": "Learn more about templating"
},
"text": {
"show_password": "Show password",
@@ -679,9 +679,9 @@
"no_entities": "You don't have any entities",
"no_match": "No entities found for {term}",
"show_entities": "Show entities",
"new_entity": "Create a new entity",
"new_entity": "Creates a new entity",
"placeholder": "Select an entity",
"create_helper": "Create a new {domain, select, \n undefined {} \n other {{domain} }\n } helper.",
"create_helper": "Create a new {domain, select, \n undefined {} \n other {{domain} }\n }helper",
"unknown": "Unknown entity selected"
},
"entity-name-picker": {
@@ -3812,7 +3812,7 @@
"grid": {
"title": "Electricity grid",
"sub": "Configure the amount of energy that you consume from the grid and, if you produce energy, give back to the grid. This allows Home Assistant to track your whole home energy usage.",
"learn_more": "More information on how to get started.",
"learn_more": "More information on how to get started",
"grid_connections": "Grid connections",
"add_connection": "Add grid connection",
"edit_connection": "Edit grid connection",
@@ -3873,7 +3873,7 @@
"solar": {
"title": "Solar panels",
"sub": "Let Home Assistant monitor your solar panels and give you insight on their performance.",
"learn_more": "More information on how to get started.",
"learn_more": "More information on how to get started",
"solar_production": "Solar production",
"edit_solar_production": "Edit solar production",
"delete_solar_production": "Remove solar production",
@@ -3896,7 +3896,7 @@
"battery": {
"title": "Home battery storage",
"sub": "If you have a battery system, you can configure it to monitor how much energy was stored and used from your battery.",
"learn_more": "More information on how to get started.",
"learn_more": "More information on how to get started",
"battery_systems": "Battery systems",
"edit_battery_system": "Edit battery system",
"delete_battery_system": "Remove battery system",
@@ -3923,7 +3923,7 @@
"gas": {
"title": "Gas consumption",
"sub": "Let Home Assistant monitor your gas usage.",
"learn_more": "More information on how to get started.",
"learn_more": "More information on how to get started",
"gas_consumption": "Gas consumption",
"edit_gas_source": "Edit gas source",
"delete_gas_source": "Remove gas source",
@@ -3952,7 +3952,7 @@
"water": {
"title": "Water consumption",
"sub": "Let Home Assistant monitor your water usage.",
"learn_more": "More information on how to get started.",
"learn_more": "More information on how to get started",
"water_consumption": "Water consumption",
"edit_water_source": "Edit water source",
"delete_water_source": "Remove water source",
@@ -3978,7 +3978,7 @@
"device_consumption": {
"title": "Individual electrical devices",
"sub": "Tracking the energy usage of individual devices allows Home Assistant to break down your energy usage by device.",
"learn_more": "More information on how to get started.",
"learn_more": "More information on how to get started",
"add_stat": "Pick entity to track energy of",
"selected_stat": "Tracking energy for",
"devices": "Devices",
@@ -3997,7 +3997,7 @@
"device_consumption_water": {
"title": "Individual water devices",
"sub": "Tracking the water usage of individual devices allows Home Assistant to break down your water usage by device.",
"learn_more": "More information on how to get started.",
"learn_more": "More information on how to get started",
"devices": "Devices",
"add_device": "Add device",
"dialog": {
@@ -5749,7 +5749,7 @@
"key_not_null": "The field key must not be empty.",
"key_not_unique": "The field key must not be the same value as another field.",
"fields": "Fields",
"link_help_fields": "Learn more about fields.",
"link_help_fields": "Learn more about fields",
"add_fields": "Add fields",
"add_field": "Add field",
"field": "field",
@@ -5777,7 +5777,7 @@
"delete_confirm_text": "{name} will be permanently deleted.",
"sequence": "Sequence",
"sequence_sentence": "The sequence of actions of this script.",
"link_available_actions": "Learn more about available actions.",
"link_available_actions": "Learn more about available actions",
"leave": {
"unsaved_new_title": "Save new script?",
"unsaved_new_text": "You can save your changes, or delete this script. You can't undo this action.",
@@ -6050,7 +6050,7 @@
"no_hooks_yet_link_integration": "webhook-based integration",
"no_hooks_yet2": " or by creating a ",
"no_hooks_yet_link_automation": "webhook automation",
"link_learn_more": "Learn more about creating webhook-powered automations.",
"link_learn_more": "Learn more about creating webhook-powered automations",
"loading": "Loading…",
"manage": "Manage",
"disable_hook_error_msg": "Failed to disable webhook:"
@@ -7042,7 +7042,7 @@
"remove_node": "Remove foreign device",
"remove_a_node": "Remove a device",
"rebuild_network_routes": "Discover and assign new routes",
"in_progress_inclusion_exclusion": "Z-Wave JS is searching for devices",
"in_progress_inclusion_exclusion": "Z-Wave is searching for devices",
"cancel_inclusion_exclusion": "Stop searching"
},
"dashboard": {
@@ -7517,7 +7517,7 @@
"caption": "Logs",
"title": "Z-Wave logs",
"log_level": "Log level",
"subscribed_to_logs": "Subscribed to Z-Wave JS log messages…",
"subscribed_to_logs": "Subscribed to Z-Wave log messages…",
"log_level_changed": "Log level changed to: {level}",
"download_logs": "Download logs"
},
@@ -7629,7 +7629,7 @@
},
"picker": {
"title": "Select Z-Wave network",
"no_entries": "No Z-Wave networks configured. Set up the Z-Wave JS integration first."
"no_entries": "No Z-Wave networks configured. Set up the Z-Wave integration first."
}
},
"matter": {
@@ -8353,7 +8353,6 @@
"unsaved_changes": "Unsaved changes",
"saved": "Saved",
"reload": "Reload",
"lovelace_changed": "Your dashboard was updated, do you want to load the updated config in the editor and lose your current changes?",
"confirm_reset_config_title": "Reset dashboard configuration?",
"confirm_reset_config_text": "Your dashboard will be reset to an empty state. You can start fresh and build your dashboard from scratch.",
"confirm_unsaved_changes": "You have unsaved changes, are you sure you want to exit?",
@@ -9676,8 +9675,8 @@
"entity_unavailable": "Entity is currently unavailable: {entity}",
"starting": "Home Assistant is starting. Not everything may be available yet."
},
"changed_toast": {
"message": "Your dashboard was updated. Refresh to see changes?"
"externally_updated_toast": {
"message": "Dashboard updated in another session. Refreshing will discard your unsaved changes."
},
"components": {
"timestamp-display": {

537
yarn.lock
View File

@@ -25,29 +25,29 @@ __metadata:
languageName: node
linkType: hard
"@asamuzakjp/css-color@npm:^4.1.1":
version: 4.1.1
resolution: "@asamuzakjp/css-color@npm:4.1.1"
"@asamuzakjp/css-color@npm:^4.1.2":
version: 4.1.2
resolution: "@asamuzakjp/css-color@npm:4.1.2"
dependencies:
"@csstools/css-calc": "npm:^2.1.4"
"@csstools/css-color-parser": "npm:^3.1.0"
"@csstools/css-parser-algorithms": "npm:^3.0.5"
"@csstools/css-tokenizer": "npm:^3.0.4"
lru-cache: "npm:^11.2.4"
checksum: 10/4b7e900d9d18a86e01a42d6140936a0373801e44854bcdd70fc7c06022b7e6a793d1960fbe9f6a65bdad1874798a30c0cd91e52bfd5eae909b3347c98cc1c4f5
"@csstools/css-calc": "npm:^3.0.0"
"@csstools/css-color-parser": "npm:^4.0.1"
"@csstools/css-parser-algorithms": "npm:^4.0.0"
"@csstools/css-tokenizer": "npm:^4.0.0"
lru-cache: "npm:^11.2.5"
checksum: 10/0938a4598a1d06d4db53b8aff406815f77047419eccb78f484dd26d13bd6cafaff247bc42f5493f2cb585477f461a38fba0db3c7a407ba9f281d27bc0d8f1983
languageName: node
linkType: hard
"@asamuzakjp/dom-selector@npm:^6.7.6":
version: 6.7.6
resolution: "@asamuzakjp/dom-selector@npm:6.7.6"
"@asamuzakjp/dom-selector@npm:^6.8.1":
version: 6.8.1
resolution: "@asamuzakjp/dom-selector@npm:6.8.1"
dependencies:
"@asamuzakjp/nwsapi": "npm:^2.3.9"
bidi-js: "npm:^1.0.3"
css-tree: "npm:^3.1.0"
is-potential-custom-element-name: "npm:^1.0.1"
lru-cache: "npm:^11.2.4"
checksum: 10/91a479f5f59a3b1b23f46407d874882c05b50e72316e57af105c88603fb1008120c46c7fe7504c5be556ea4c9a68ee10aee43433bd8d34f000b9aaf6dcae4d5c
lru-cache: "npm:^11.2.6"
checksum: 10/4d1c63bf094aa35c9c60ad8d2faf45ee4f5f8d1520fbb158e2552c456f8264029932ff4464ea18ea760a89b3075b4bf70e43b2086191d256f35eff46fde3eb24
languageName: node
linkType: hard
@@ -1204,6 +1204,17 @@ __metadata:
languageName: node
linkType: hard
"@bramus/specificity@npm:^2.4.2":
version: 2.4.2
resolution: "@bramus/specificity@npm:2.4.2"
dependencies:
css-tree: "npm:^3.0.0"
bin:
specificity: bin/cli.js
checksum: 10/4255ed6ff12f7db9ec3c21acfd0da2327d30ec29deb199345810cdcad992618f40039c5483eefeb665913bffbc80b690e9f1b954fbbbfa93480c6a22f9c3a69c
languageName: node
linkType: hard
"@bundle-stats/plugin-webpack-filter@npm:4.21.10":
version: 4.21.10
resolution: "@bundle-stats/plugin-webpack-filter@npm:4.21.10"
@@ -1239,9 +1250,9 @@ __metadata:
languageName: node
linkType: hard
"@codemirror/language@npm:6.12.1, @codemirror/language@npm:^6.0.0":
version: 6.12.1
resolution: "@codemirror/language@npm:6.12.1"
"@codemirror/language@npm:6.12.2, @codemirror/language@npm:^6.0.0":
version: 6.12.2
resolution: "@codemirror/language@npm:6.12.2"
dependencies:
"@codemirror/state": "npm:^6.0.0"
"@codemirror/view": "npm:^6.23.0"
@@ -1249,7 +1260,7 @@ __metadata:
"@lezer/highlight": "npm:^1.0.0"
"@lezer/lr": "npm:^1.0.0"
style-mod: "npm:^4.0.0"
checksum: 10/a24c3512d38cbb2a20cc3128da0eea074b4a6102b6a5a041b3dfd5e67638fb61dcdf4743ed87708db882df5d72a84d9f891aac6fa68447830989c8e2d9ffa2ba
checksum: 10/9afc704e17cad4782b68ad02869503a27103c4c3ac6927d2ffa3c6decfad627ade40b0ed78d1d6e941b2e879a7a79bda0d573e58604f3923f9e1f3311108ec36
languageName: node
linkType: hard
@@ -1294,56 +1305,56 @@ __metadata:
languageName: node
linkType: hard
"@csstools/color-helpers@npm:^5.1.0":
version: 5.1.0
resolution: "@csstools/color-helpers@npm:5.1.0"
checksum: 10/0138b3d5ccbe77aeccf6721fd008a53523c70e932f0c82dca24a1277ca780447e1d8357da47512ebf96358476f8764de57002f3e491920d67e69202f5a74c383
"@csstools/color-helpers@npm:^6.0.2":
version: 6.0.2
resolution: "@csstools/color-helpers@npm:6.0.2"
checksum: 10/c47a943e947d76980d0e1071027cb70481ac481968e744a05a7aea7ede9886f10d062b2e3691e03c115d97b053d4140c1ca28e24c1ffe2d21693e126de6522e9
languageName: node
linkType: hard
"@csstools/css-calc@npm:^2.1.4":
version: 2.1.4
resolution: "@csstools/css-calc@npm:2.1.4"
"@csstools/css-calc@npm:^3.0.0, @csstools/css-calc@npm:^3.1.1":
version: 3.1.1
resolution: "@csstools/css-calc@npm:3.1.1"
peerDependencies:
"@csstools/css-parser-algorithms": ^3.0.5
"@csstools/css-tokenizer": ^3.0.4
checksum: 10/06975b650c0f44c60eeb7afdb3fd236f2dd607b2c622e0bc908d3f54de39eb84e0692833320d03dac04bd6c1ab0154aa3fa0dd442bd9e5f917cf14d8e2ba8d74
"@csstools/css-parser-algorithms": ^4.0.0
"@csstools/css-tokenizer": ^4.0.0
checksum: 10/faa3aa2736b20757ceafd76e3d2841e8726ec9e7ae78e387684eb462aba73d533ba384039338685c3a52196196300ccdfecb051e59864b1d3b457fe927b7f53b
languageName: node
linkType: hard
"@csstools/css-color-parser@npm:^3.1.0":
version: 3.1.0
resolution: "@csstools/css-color-parser@npm:3.1.0"
"@csstools/css-color-parser@npm:^4.0.1":
version: 4.0.2
resolution: "@csstools/css-color-parser@npm:4.0.2"
dependencies:
"@csstools/color-helpers": "npm:^5.1.0"
"@csstools/css-calc": "npm:^2.1.4"
"@csstools/color-helpers": "npm:^6.0.2"
"@csstools/css-calc": "npm:^3.1.1"
peerDependencies:
"@csstools/css-parser-algorithms": ^3.0.5
"@csstools/css-tokenizer": ^3.0.4
checksum: 10/4741095fdc4501e8e7ada4ed14fbf9dbbe6fea9b989818790ebca15657c29c62defbebacf18592cde2aa638a1d098bbe86d742d2c84ba932fbc00fac51cb8805
"@csstools/css-parser-algorithms": ^4.0.0
"@csstools/css-tokenizer": ^4.0.0
checksum: 10/6418bfadc8c15d3a65c1e80278df383b542f0437446c0ba21d591dd564bcc19ab0b11243edf62672f4c62cc778f9b386fa4349e9a8d1de2b414148ea8a1ac775
languageName: node
linkType: hard
"@csstools/css-parser-algorithms@npm:^3.0.5":
version: 3.0.5
resolution: "@csstools/css-parser-algorithms@npm:3.0.5"
"@csstools/css-parser-algorithms@npm:^4.0.0":
version: 4.0.0
resolution: "@csstools/css-parser-algorithms@npm:4.0.0"
peerDependencies:
"@csstools/css-tokenizer": ^3.0.4
checksum: 10/e93083b5cb36a3c1e7a47ce10cf62961d05bd1e4c608bb3ee50186ff740157ab0ec16a3956f7b86251efd10703034d849693201eea858ae904848c68d2d46ada
"@csstools/css-tokenizer": ^4.0.0
checksum: 10/000f3ba55f440d9fbece50714e88f9d4479e2bde9e0568333492663f2c6034dc31d0b9ef5d66d196c76be58eea145ca6920aa8bdfdcc6361894806c21b5402d0
languageName: node
linkType: hard
"@csstools/css-syntax-patches-for-csstree@npm:^1.0.21":
version: 1.0.25
resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.25"
checksum: 10/42dfcd164ed6a66eee8dd3fcdbdaa58d032ab8c3bb5ead2453915429367766879b25332e09379a67357fd33742b856160e7c0182c7d90be00f57571b916c18e7
"@csstools/css-syntax-patches-for-csstree@npm:^1.0.26":
version: 1.0.28
resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.28"
checksum: 10/b7b393a4285b2d91aec71ef714ebe356f6607d6358e025306eaf567bd7bbd201e3a5d1f0a8d3cd9063b3dd40bbdbfd6664b4c658c2bca45c4c1b122a54a0804e
languageName: node
linkType: hard
"@csstools/css-tokenizer@npm:^3.0.4":
version: 3.0.4
resolution: "@csstools/css-tokenizer@npm:3.0.4"
checksum: 10/eb6c84c086312f6bb8758dfe2c85addd7475b0927333c5e39a4d59fb210b9810f8c346972046f95e60a721329cffe98895abe451e51de753ad1ca7a8c24ec65f
"@csstools/css-tokenizer@npm:^4.0.0":
version: 4.0.0
resolution: "@csstools/css-tokenizer@npm:4.0.0"
checksum: 10/074ade1a7fc3410b813c8982cf07a56814a55af509c533c2dc80d5689f34d2ba38219f8fa78fa36ea2adc6c5db506ea3c3a667388dda1b59b1281fdd2a2d1e28
languageName: node
linkType: hard
@@ -1962,9 +1973,9 @@ __metadata:
languageName: node
linkType: hard
"@home-assistant/webawesome@npm:3.2.1-ha.2":
version: 3.2.1-ha.2
resolution: "@home-assistant/webawesome@npm:3.2.1-ha.2"
"@home-assistant/webawesome@npm:3.2.1-ha.3":
version: 3.2.1-ha.3
resolution: "@home-assistant/webawesome@npm:3.2.1-ha.3"
dependencies:
"@ctrl/tinycolor": "npm:4.1.0"
"@floating-ui/dom": "npm:^1.6.13"
@@ -1975,78 +1986,80 @@ __metadata:
lit: "npm:^3.2.1"
nanoid: "npm:^5.1.5"
qr-creator: "npm:^1.0.0"
checksum: 10/36f15a10760fe4c13c9551e4440d9ad395c894d6f3735494da2032948fae052056ea6e762fbfa3b2e7e0cb94a8d1e214bb73478e682813cb3ed9c44b2daec98d
checksum: 10/e5182d4ce11ed6a0b17e6da7783f0dea20dc743593b9873cbfcaf26425a78383e9f90dbb152618b96422ea37be6fb8ff09aa9903b012d5fe0ab5ebc0570154a4
languageName: node
linkType: hard
"@html-eslint/core@npm:^0.56.0":
version: 0.56.0
resolution: "@html-eslint/core@npm:0.56.0"
"@html-eslint/core@npm:^0.57.0":
version: 0.57.0
resolution: "@html-eslint/core@npm:0.57.0"
dependencies:
"@html-eslint/types": "npm:^0.56.0"
"@html-eslint/types": "npm:^0.57.0"
eslint: "npm:^9.39.1"
html-standard: "npm:^0.0.13"
checksum: 10/0722e7405e56b256c471229dbd0ccb49cf0edd3e5224a087240f1954c74af0a6f289e5be0b83957480f1fa5abf6f7cbad7212134a6872a3fd66e1dc1ad879d66
checksum: 10/18b7aaf455969008dc5b79f6fd4b38792d893053e77c098c56a9238fe9b3ac3fa36441a88b908ade71de2f5179d5b4c45f552d7da5beff1d5c8df9cb3fd14e63
languageName: node
linkType: hard
"@html-eslint/eslint-plugin@npm:0.56.0":
version: 0.56.0
resolution: "@html-eslint/eslint-plugin@npm:0.56.0"
"@html-eslint/eslint-plugin@npm:0.57.1":
version: 0.57.1
resolution: "@html-eslint/eslint-plugin@npm:0.57.1"
dependencies:
"@eslint/plugin-kit": "npm:^0.4.1"
"@html-eslint/core": "npm:^0.56.0"
"@html-eslint/parser": "npm:^0.56.0"
"@html-eslint/template-parser": "npm:^0.56.0"
"@html-eslint/template-syntax-parser": "npm:^0.56.0"
"@html-eslint/types": "npm:^0.56.0"
"@html-eslint/core": "npm:^0.57.0"
"@html-eslint/parser": "npm:^0.57.1"
"@html-eslint/template-parser": "npm:^0.57.0"
"@html-eslint/template-syntax-parser": "npm:^0.57.0"
"@html-eslint/types": "npm:^0.57.0"
"@rviscomi/capo.js": "npm:^2.1.0"
html-standard: "npm:^0.0.13"
peerDependencies:
eslint: ">=8.0.0 || ^10.0.0-0"
checksum: 10/16c5d638045266ca201b5dc154b3706262801668b2edde4f0905bdba9ba2e14b7175eacf9ca7d2ad5a5a03e3369843822d34ee607b6b7fbbeb020ac7f87629fb
checksum: 10/21a923a1ee8efb02f01c015345a23b38cd0a9e98c4f3fa07d79afe1f8e9f26651e0a9d6983b2f9cfae76be71c14f3224fd64433612535c1e04e3c9b440e46245
languageName: node
linkType: hard
"@html-eslint/parser@npm:^0.56.0":
version: 0.56.0
resolution: "@html-eslint/parser@npm:0.56.0"
"@html-eslint/parser@npm:^0.57.1":
version: 0.57.1
resolution: "@html-eslint/parser@npm:0.57.1"
dependencies:
"@eslint/css-tree": "npm:^3.6.9"
"@html-eslint/template-syntax-parser": "npm:^0.56.0"
"@html-eslint/types": "npm:^0.56.0"
"@html-eslint/template-syntax-parser": "npm:^0.57.0"
"@html-eslint/types": "npm:^0.57.0"
css-tree: "npm:^3.1.0"
es-html-parser: "npm:0.3.1"
checksum: 10/1fead2be97481f461ee7030f4ea9274e5f969540118b4429e3eea361f62138660c1b7538668c7f8d55a8ae6985deff3056968d71bae62b91fb001d4209a24b50
checksum: 10/3e148f0bf83600e5b931938dc02d01e805c275b0534fad0adc8ac68ceb37220896c007b1d33ebc4347cb59ab35d1cc3c57207ff798f08d2327d92abf1c88e72b
languageName: node
linkType: hard
"@html-eslint/template-parser@npm:^0.56.0":
version: 0.56.0
resolution: "@html-eslint/template-parser@npm:0.56.0"
"@html-eslint/template-parser@npm:^0.57.0":
version: 0.57.0
resolution: "@html-eslint/template-parser@npm:0.57.0"
dependencies:
"@html-eslint/types": "npm:^0.56.0"
"@html-eslint/types": "npm:^0.57.0"
es-html-parser: "npm:0.3.1"
checksum: 10/45e41dc8fb46336f40d1b78ef55ee3150d7a1034d393529eb40ce37a7d0a8fa04f6ed8f9a63478ff884d9588b1359b97a799681a37cd485d237dce867b7f9d20
checksum: 10/160d7f6156f242ed7bd4e7f13d79c350bf5db7fef089ba7b404ef770d80547620e9ee860ead8892a4079668db1cdccf6a6c6b91183a8c478a634314b39efea32
languageName: node
linkType: hard
"@html-eslint/template-syntax-parser@npm:^0.56.0":
version: 0.56.0
resolution: "@html-eslint/template-syntax-parser@npm:0.56.0"
"@html-eslint/template-syntax-parser@npm:^0.57.0":
version: 0.57.0
resolution: "@html-eslint/template-syntax-parser@npm:0.57.0"
dependencies:
"@html-eslint/types": "npm:^0.56.0"
checksum: 10/2cc4f2cbfa58c6381b2542ca86e424a97429326aa0b8b6b09e0a51d27b0e26fd723a4550e4c17536e00cfd506cbd0c61d8fd3dff1c829714c4432406096b4a01
"@html-eslint/types": "npm:^0.57.0"
checksum: 10/147d8d15ebc5ea9b75eea04463b9f29cfc476be2e98c5a2129442be6f66d32a9e8bb11a1be13cc3778df25e14d7ed1cd345342951ecec05292545f64bb3d92c6
languageName: node
linkType: hard
"@html-eslint/types@npm:^0.56.0":
version: 0.56.0
resolution: "@html-eslint/types@npm:0.56.0"
"@html-eslint/types@npm:^0.57.0":
version: 0.57.0
resolution: "@html-eslint/types@npm:0.57.0"
dependencies:
"@types/css-tree": "npm:^2.3.11"
"@types/estree": "npm:^1.0.6"
es-html-parser: "npm:0.3.1"
eslint: "npm:^9.39.1"
checksum: 10/5359ccfb8f431ccedfe7d9c0b20d883d19bbb6a24eee925c036c7774d6f2177eda021826abbc6f947b59c2364d7cf25a596591e852c1141000a3fab6ea70acc9
checksum: 10/44d0bde592786a2da966beab13c3d543e6669b1e38b6e5feea0f01121eec928be0081969df3ada1f27c9bd43d6286596afa56a2e075da843251079a940cf0825
languageName: node
linkType: hard
@@ -4246,6 +4259,13 @@ __metadata:
languageName: node
linkType: hard
"@rviscomi/capo.js@npm:^2.1.0":
version: 2.1.0
resolution: "@rviscomi/capo.js@npm:2.1.0"
checksum: 10/83ce30106ec6bd4b4791af12556119c568cb9d0ec7550b7b015a8c2c1c49687d8c6605564415d9d85e991581958212109ee5caa0db4166c1d3628033175e80b8
languageName: node
linkType: hard
"@shoelace-style/animations@npm:^1.2.0":
version: 1.2.0
resolution: "@shoelace-style/animations@npm:1.2.0"
@@ -4321,12 +4341,12 @@ __metadata:
languageName: node
linkType: hard
"@swc/helpers@npm:0.5.18":
version: 0.5.18
resolution: "@swc/helpers@npm:0.5.18"
"@swc/helpers@npm:0.5.19":
version: 0.5.19
resolution: "@swc/helpers@npm:0.5.19"
dependencies:
tslib: "npm:^2.8.0"
checksum: 10/03c7efa3e62d965fddd0baea98ee7a4c3ba7fa58187f07f26ec8d86740572f5ffd6f7517578a1d3201f64c85399be1538eba4dd30cef79d073060ecb101d753c
checksum: 10/3fd365fb3265f97e1241bcbcea9bfa5e15e03c630424e1b54597e00d30be2c271cb0c74f45e1739c6bc5ae892647302fab412de5138941aa96e66aebf4586700
languageName: node
linkType: hard
@@ -5013,13 +5033,12 @@ __metadata:
languageName: node
linkType: hard
"@types/tar@npm:6.1.13":
version: 6.1.13
resolution: "@types/tar@npm:6.1.13"
"@types/tar@npm:7.0.87":
version: 7.0.87
resolution: "@types/tar@npm:7.0.87"
dependencies:
"@types/node": "npm:*"
minipass: "npm:^4.0.0"
checksum: 10/d325223cf90399fd03f366d0eabe2383e75e550b3e40a006d5f062d006b894a475cd7c0968d258a8eb8eae5df30b6e7f4607d493a474f89134bbff65362b77ed
tar: "npm:*"
checksum: 10/f53a63d49d1775928a60afee5524c8d58052cf0896c0e051461f4faf4131caa0cec1d2e3d711374d91d55a59de3e898c43243e5026e5faca9436b69cb5e414b0
languageName: node
linkType: hard
@@ -5053,138 +5072,138 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/eslint-plugin@npm:8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/eslint-plugin@npm:8.54.0"
"@typescript-eslint/eslint-plugin@npm:8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/eslint-plugin@npm:8.56.1"
dependencies:
"@eslint-community/regexpp": "npm:^4.12.2"
"@typescript-eslint/scope-manager": "npm:8.54.0"
"@typescript-eslint/type-utils": "npm:8.54.0"
"@typescript-eslint/utils": "npm:8.54.0"
"@typescript-eslint/visitor-keys": "npm:8.54.0"
"@typescript-eslint/scope-manager": "npm:8.56.1"
"@typescript-eslint/type-utils": "npm:8.56.1"
"@typescript-eslint/utils": "npm:8.56.1"
"@typescript-eslint/visitor-keys": "npm:8.56.1"
ignore: "npm:^7.0.5"
natural-compare: "npm:^1.4.0"
ts-api-utils: "npm:^2.4.0"
peerDependencies:
"@typescript-eslint/parser": ^8.54.0
eslint: ^8.57.0 || ^9.0.0
"@typescript-eslint/parser": ^8.56.1
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/8f1c74ac77d7a84ae3f201bb09cb67271662befed036266af1eaa0653d09b545353441640516c1c86e0a94939887d32f0473c61a642488b14d46533742bfbd1b
checksum: 10/669d19cff91fcad5fe34dba97cc8c0c2df3160ae14646759fb23dfd6ffbb861d00d8d081e74d1060d544bfba0ea4d05588c5b73ae104907af26cc18189c0d139
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/parser@npm:8.54.0"
"@typescript-eslint/parser@npm:8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/parser@npm:8.56.1"
dependencies:
"@typescript-eslint/scope-manager": "npm:8.54.0"
"@typescript-eslint/types": "npm:8.54.0"
"@typescript-eslint/typescript-estree": "npm:8.54.0"
"@typescript-eslint/visitor-keys": "npm:8.54.0"
"@typescript-eslint/scope-manager": "npm:8.56.1"
"@typescript-eslint/types": "npm:8.56.1"
"@typescript-eslint/typescript-estree": "npm:8.56.1"
"@typescript-eslint/visitor-keys": "npm:8.56.1"
debug: "npm:^4.4.3"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/d2e09462c9966ef3deeba71d9e41d1d4876c61eea65888c93a3db6fba48b89a2165459c6519741d40e969da05ed98d3f4c87a7f56c5521ab5699743cc315f6cb
checksum: 10/280b041a69153caf9e721b307781830483dd39d881b02d993156635bd8600e30e6a816aaead8bdd662ae5149b8870aef7b3823d3b98ec974d924c23a786fb6d9
languageName: node
linkType: hard
"@typescript-eslint/project-service@npm:8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/project-service@npm:8.54.0"
"@typescript-eslint/project-service@npm:8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/project-service@npm:8.56.1"
dependencies:
"@typescript-eslint/tsconfig-utils": "npm:^8.54.0"
"@typescript-eslint/types": "npm:^8.54.0"
"@typescript-eslint/tsconfig-utils": "npm:^8.56.1"
"@typescript-eslint/types": "npm:^8.56.1"
debug: "npm:^4.4.3"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10/93f0483f6bbcf7cf776a53a130f7606f597fba67cf111e1897873bf1531efaa96e4851cfd461da0f0cc93afbdb51e47bcce11cf7dd4fb68b7030c7f9f240b92f
checksum: 10/5e7fdc95aebcefc72fec77806bb0821a9a59e5e88f86d72b15ad011eb6110da05419b803875f021716a219fc7fb8517331a6736364344c8613a90209539a6d32
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/scope-manager@npm:8.54.0"
"@typescript-eslint/scope-manager@npm:8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/scope-manager@npm:8.56.1"
dependencies:
"@typescript-eslint/types": "npm:8.54.0"
"@typescript-eslint/visitor-keys": "npm:8.54.0"
checksum: 10/3474f3197e8647754393dee62b3145c9de71eaa66c8a68f61c8283aa332141803885db9c96caa6a51f78128ad9ef92f774a90361655e57bd951d5b57eb76f914
"@typescript-eslint/types": "npm:8.56.1"
"@typescript-eslint/visitor-keys": "npm:8.56.1"
checksum: 10/f358cf8bd32952eed005d4f34c1e95805baefe35abee96d866222b0eff8027cc02f831cee04b308707d74db2b415437a134191207b4213ee8acbc6d67a435616
languageName: node
linkType: hard
"@typescript-eslint/tsconfig-utils@npm:8.54.0, @typescript-eslint/tsconfig-utils@npm:^8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/tsconfig-utils@npm:8.54.0"
"@typescript-eslint/tsconfig-utils@npm:8.56.1, @typescript-eslint/tsconfig-utils@npm:^8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/tsconfig-utils@npm:8.56.1"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10/e9d6b29538716f007919bfcee94f09b7f8e7d2b684ad43d1a3c8d43afb9f0539c7707f84a34f42054e31c8c056b0ccf06575d89e860b4d34632ffefaefafe1fc
checksum: 10/d509f1ae4b14969173e498db6d15c833b6407db456c7fca9e25396798a35014229a73754691f353c4a99f5f0bbb4535b4144f42f84e596645a16d88a2022135f
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/type-utils@npm:8.54.0"
"@typescript-eslint/type-utils@npm:8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/type-utils@npm:8.56.1"
dependencies:
"@typescript-eslint/types": "npm:8.54.0"
"@typescript-eslint/typescript-estree": "npm:8.54.0"
"@typescript-eslint/utils": "npm:8.54.0"
"@typescript-eslint/types": "npm:8.56.1"
"@typescript-eslint/typescript-estree": "npm:8.56.1"
"@typescript-eslint/utils": "npm:8.56.1"
debug: "npm:^4.4.3"
ts-api-utils: "npm:^2.4.0"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/60e92fb32274abd70165ce6f4187e4cffa55416374c63731d7de8fdcfb7a558b4dd48909ff1ad38ac39d2ea1248ec54d6ce38dbc065fd34529a217fc2450d5b1
checksum: 10/2b07c674c26d797d05c05779ac5c89761b6b96680ecaf01440957727d12c6d06a2e48f0b139e45752eb4b53bf13c03940628656c519d362082b716d6a0ece6d9
languageName: node
linkType: hard
"@typescript-eslint/types@npm:8.54.0, @typescript-eslint/types@npm:^8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/types@npm:8.54.0"
checksum: 10/c25cc0bdf90fb150cf6ce498897f43fe3adf9e872562159118f34bd91a9bfab5f720cb1a41f3cdf253b2e840145d7d372089b7cef5156624ef31e98d34f91b31
"@typescript-eslint/types@npm:8.56.1, @typescript-eslint/types@npm:^8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/types@npm:8.56.1"
checksum: 10/4bcffab5b0fd48adb731fcade86a776ca4a66e229defa5a282b58ba9c95af16ffc459a7d188e27c988a35be1f6fb5b812f9cf0952692eac38d5b3e87daafb20a
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/typescript-estree@npm:8.54.0"
"@typescript-eslint/typescript-estree@npm:8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/typescript-estree@npm:8.56.1"
dependencies:
"@typescript-eslint/project-service": "npm:8.54.0"
"@typescript-eslint/tsconfig-utils": "npm:8.54.0"
"@typescript-eslint/types": "npm:8.54.0"
"@typescript-eslint/visitor-keys": "npm:8.54.0"
"@typescript-eslint/project-service": "npm:8.56.1"
"@typescript-eslint/tsconfig-utils": "npm:8.56.1"
"@typescript-eslint/types": "npm:8.56.1"
"@typescript-eslint/visitor-keys": "npm:8.56.1"
debug: "npm:^4.4.3"
minimatch: "npm:^9.0.5"
minimatch: "npm:^10.2.2"
semver: "npm:^7.7.3"
tinyglobby: "npm:^0.2.15"
ts-api-utils: "npm:^2.4.0"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10/3a545037c6f9319251d3ba44cf7a3216b1372422469e27f7ed3415244ebf42553da1ab4644da42d3f0ae2706a8cad12529ffebcb2e75406f74e3b30b812d010d
checksum: 10/af39dae0a8fada72295a11f0efb49f311241134b0a3d819100eeda6a2f92368844645873ba785de5513ad541cd9c2ba17b9bfed2679daac4682fa2a3b627f087
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/utils@npm:8.54.0"
"@typescript-eslint/utils@npm:8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/utils@npm:8.56.1"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.9.1"
"@typescript-eslint/scope-manager": "npm:8.54.0"
"@typescript-eslint/types": "npm:8.54.0"
"@typescript-eslint/typescript-estree": "npm:8.54.0"
"@typescript-eslint/scope-manager": "npm:8.56.1"
"@typescript-eslint/types": "npm:8.56.1"
"@typescript-eslint/typescript-estree": "npm:8.56.1"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/9f88a2a7ab3e11aa0ff7f99c0e66a0cf2cba10b640def4c64a4f4ef427fecfb22f28dbe5697535915eb01f6507515ac43e45e0ff384bf82856e3420194d9ffdd
checksum: 10/528cbd187d8288a8cfce24a043f993b93711087f53d2b6f95cdd615a1a4087af1dab083a747761af97474a621c7b14f11c84ee50c250f31566ebc64cf73867fe
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:8.54.0":
version: 8.54.0
resolution: "@typescript-eslint/visitor-keys@npm:8.54.0"
"@typescript-eslint/visitor-keys@npm:8.56.1":
version: 8.56.1
resolution: "@typescript-eslint/visitor-keys@npm:8.56.1"
dependencies:
"@typescript-eslint/types": "npm:8.54.0"
eslint-visitor-keys: "npm:^4.2.1"
checksum: 10/cca5380ee30250302ee1459e5a0a38de8c16213026dbbff3d167fa7d71d012f31d60ac4483ad45ebd13f2ac963d1ca52dd5f22759a68d4ee57626e421769187a
"@typescript-eslint/types": "npm:8.56.1"
eslint-visitor-keys: "npm:^5.0.0"
checksum: 10/efed6a9867e7be203eec543e5a65da5aaec96aae55fba6fe74a305bf600e57c707764835e82bb8eb541f49a9b70442ff1e1a0ecf3543c78c91b84dda43b95c53
languageName: node
linkType: hard
@@ -6068,12 +6087,12 @@ __metadata:
languageName: node
linkType: hard
"barcode-detector@npm:3.0.8":
version: 3.0.8
resolution: "barcode-detector@npm:3.0.8"
"barcode-detector@npm:3.1.0":
version: 3.1.0
resolution: "barcode-detector@npm:3.1.0"
dependencies:
zxing-wasm: "npm:2.2.4"
checksum: 10/7de6225f659c69a0f4101d080a9e0812f2404c485fa2406424b8b13eaff274f6e7405c94de24827a09def52c32a63b19b9c9fba61c5274b074d558f696ec1684
zxing-wasm: "npm:3.0.0"
checksum: 10/60767161081b827e290b60bb3416999dee616bab39291ee55565df9b72d59f0bbbf511fd3bb85db18eee7c0ad9acf1ff90359cdb21e10f80793acd0105c86a1d
languageName: node
linkType: hard
@@ -6924,7 +6943,7 @@ __metadata:
languageName: node
linkType: hard
"css-tree@npm:^3.1.0":
"css-tree@npm:^3.0.0, css-tree@npm:^3.1.0":
version: 3.1.0
resolution: "css-tree@npm:3.1.0"
dependencies:
@@ -6941,15 +6960,15 @@ __metadata:
languageName: node
linkType: hard
"cssstyle@npm:^5.3.7":
version: 5.3.7
resolution: "cssstyle@npm:5.3.7"
"cssstyle@npm:^6.0.1":
version: 6.0.2
resolution: "cssstyle@npm:6.0.2"
dependencies:
"@asamuzakjp/css-color": "npm:^4.1.1"
"@csstools/css-syntax-patches-for-csstree": "npm:^1.0.21"
"@asamuzakjp/css-color": "npm:^4.1.2"
"@csstools/css-syntax-patches-for-csstree": "npm:^1.0.26"
css-tree: "npm:^3.1.0"
lru-cache: "npm:^11.2.4"
checksum: 10/bd4469af81f068537dbbce53c4247f192e91202c19abc066b77b4ee7bbf256526bc82471198bec762ac70ea53ce17b8044aec69fd7982d2d0fd9fd7780329e2d
lru-cache: "npm:^11.2.5"
checksum: 10/88f102b618d1b86fba9fe967f5252fde090f8eea45f5f46bfbedd61a4839bc1dab85287ffc14e912af0f9a80a86c904654b9f6c04c09521aa147d70b1b9b5917
languageName: node
linkType: hard
@@ -7134,7 +7153,7 @@ __metadata:
languageName: node
linkType: hard
"defaults@npm:^1.0.3, defaults@npm:^1.0.4":
"defaults@npm:^1.0.3":
version: 1.0.4
resolution: "defaults@npm:1.0.4"
dependencies:
@@ -7976,15 +7995,15 @@ __metadata:
languageName: node
linkType: hard
"eslint-plugin-wc@npm:3.0.2":
version: 3.0.2
resolution: "eslint-plugin-wc@npm:3.0.2"
"eslint-plugin-wc@npm:3.1.0":
version: 3.1.0
resolution: "eslint-plugin-wc@npm:3.1.0"
dependencies:
is-valid-element-name: "npm:^1.0.0"
js-levenshtein-esm: "npm:^2.0.0"
peerDependencies:
eslint: ">=8.40.0"
checksum: 10/488d8cbfb57c8845ff82358a7b5c1b2b6a670f2638ad577cdfb4ebf4270783624b6754c75223f0cec5fe1bf3273b62b1837e1bef1435c4376b14f1ec709b838e
checksum: 10/00797dcbf3f50d88ce1036555bc8940d7796015a77c2a5e9953638ae9d847f8a81027342232909924f46a1b834be957ed5e08168932482b9c21e6a0ef02f7543
languageName: node
linkType: hard
@@ -8019,6 +8038,13 @@ __metadata:
languageName: node
linkType: hard
"eslint-visitor-keys@npm:^5.0.0":
version: 5.0.1
resolution: "eslint-visitor-keys@npm:5.0.1"
checksum: 10/f9cc1a57b75e0ef949545cac33d01e8367e302de4c1483266ed4d8646ee5c306376660196bbb38b004e767b7043d1e661cb4336b49eff634a1bbe75c1db709ec
languageName: node
linkType: hard
"eslint@npm:9.39.3, eslint@npm:^9.39.1":
version: 9.39.3
resolution: "eslint@npm:9.39.3"
@@ -8281,7 +8307,7 @@ __metadata:
languageName: node
linkType: hard
"fancy-log@npm:2.0.0, fancy-log@npm:^2.0.0":
"fancy-log@npm:2.0.0":
version: 2.0.0
resolution: "fancy-log@npm:2.0.0"
dependencies:
@@ -9014,18 +9040,16 @@ __metadata:
languageName: node
linkType: hard
"gulp-zopfli-green@npm:6.0.2":
version: 6.0.2
resolution: "gulp-zopfli-green@npm:6.0.2"
"gulp-zopfli-green@npm:7.0.0":
version: 7.0.0
resolution: "gulp-zopfli-green@npm:7.0.0"
dependencies:
"@gfx/zopfli": "npm:^1.0.15"
bytes: "npm:^3.1.2"
defaults: "npm:^1.0.4"
fancy-log: "npm:^2.0.0"
plugin-error: "npm:^2.0.1"
stream-to-array: "npm:^2.3.0"
through2: "npm:^4.0.2"
checksum: 10/52e899dfb86777ff8f97a23af99c59e203ea485fbf04d0a8f4f1cfbd4d4c496808a3593ae8dac16584fc4b4d81cf127b2eda5355a61bcc213875c95cc86d41da
checksum: 10/25db42b9a8f6395847e3cc06c548c3f3d51c84606166f18de71d91d505e7293176b45b4b78b7e0b1566c26263fe0dc212e56d2b367461c3d712bee9d22d5224f
languageName: node
linkType: hard
@@ -9152,7 +9176,7 @@ __metadata:
"@bundle-stats/plugin-webpack-filter": "npm:4.21.10"
"@codemirror/autocomplete": "npm:6.20.0"
"@codemirror/commands": "npm:6.10.2"
"@codemirror/language": "npm:6.12.1"
"@codemirror/language": "npm:6.12.2"
"@codemirror/legacy-modes": "npm:6.5.2"
"@codemirror/search": "npm:6.6.0"
"@codemirror/state": "npm:6.5.4"
@@ -9174,8 +9198,8 @@ __metadata:
"@fullcalendar/list": "npm:6.1.20"
"@fullcalendar/luxon3": "npm:6.1.20"
"@fullcalendar/timegrid": "npm:6.1.20"
"@home-assistant/webawesome": "npm:3.2.1-ha.2"
"@html-eslint/eslint-plugin": "npm:0.56.0"
"@home-assistant/webawesome": "npm:3.2.1-ha.3"
"@html-eslint/eslint-plugin": "npm:0.57.1"
"@lezer/highlight": "npm:1.2.3"
"@lit-labs/motion": "npm:1.1.0"
"@lit-labs/observers": "npm:2.1.0"
@@ -9213,7 +9237,7 @@ __metadata:
"@rsdoctor/rspack-plugin": "npm:1.5.2"
"@rspack/core": "npm:1.7.6"
"@rspack/dev-server": "npm:1.2.1"
"@swc/helpers": "npm:0.5.18"
"@swc/helpers": "npm:0.5.19"
"@thomasloven/round-slider": "npm:0.6.0"
"@tsparticles/engine": "npm:3.9.1"
"@tsparticles/preset-links": "npm:3.2.0"
@@ -9232,7 +9256,7 @@ __metadata:
"@types/mocha": "npm:10.0.10"
"@types/qrcode": "npm:1.5.6"
"@types/sortablejs": "npm:1.15.9"
"@types/tar": "npm:6.1.13"
"@types/tar": "npm:7.0.87"
"@types/ua-parser-js": "npm:0.7.39"
"@types/webspeechapi": "npm:0.0.29"
"@vibrant/color": "npm:4.0.4"
@@ -9243,7 +9267,7 @@ __metadata:
app-datepicker: "npm:5.1.1"
babel-loader: "npm:10.0.0"
babel-plugin-template-html-minifier: "npm:4.1.0"
barcode-detector: "npm:3.0.8"
barcode-detector: "npm:3.1.0"
browserslist-useragent-regexp: "npm:4.1.3"
color-name: "npm:2.1.0"
comlink: "npm:4.4.2"
@@ -9265,7 +9289,7 @@ __metadata:
eslint-plugin-lit: "npm:2.2.1"
eslint-plugin-lit-a11y: "npm:5.1.1"
eslint-plugin-unused-imports: "npm:4.4.1"
eslint-plugin-wc: "npm:3.0.2"
eslint-plugin-wc: "npm:3.1.0"
fancy-log: "npm:2.0.0"
fs-extra: "npm:11.3.3"
fuse.js: "npm:7.1.0"
@@ -9275,7 +9299,7 @@ __metadata:
gulp-brotli: "npm:3.0.0"
gulp-json-transform: "npm:0.5.0"
gulp-rename: "npm:2.1.0"
gulp-zopfli-green: "npm:6.0.2"
gulp-zopfli-green: "npm:7.0.0"
hls.js: "npm:1.6.15"
home-assistant-js-websocket: "npm:9.6.0"
html-minifier-terser: "npm:7.2.0"
@@ -9283,7 +9307,7 @@ __metadata:
idb-keyval: "npm:6.2.2"
intl-messageformat: "npm:11.1.2"
js-yaml: "npm:4.1.1"
jsdom: "npm:28.0.0"
jsdom: "npm:28.1.0"
jszip: "npm:3.10.1"
leaflet: "npm:1.9.4"
leaflet-draw: "patch:leaflet-draw@npm%3A1.0.4#./.yarn/patches/leaflet-draw-npm-1.0.4-0ca0ebcf65.patch"
@@ -9313,14 +9337,14 @@ __metadata:
sortablejs: "patch:sortablejs@npm%3A1.15.6#~/.yarn/patches/sortablejs-npm-1.15.6-3235a8f83b.patch"
stacktrace-js: "npm:2.0.2"
superstruct: "npm:2.0.2"
tar: "npm:7.5.8"
tar: "npm:7.5.9"
terser-webpack-plugin: "npm:5.3.16"
tinykeys: "npm:3.0.0"
ts-lit-plugin: "npm:2.0.2"
typescript: "npm:5.9.3"
typescript-eslint: "npm:8.54.0"
typescript-eslint: "npm:8.56.1"
ua-parser-js: "npm:2.0.9"
vite-tsconfig-paths: "npm:6.0.5"
vite-tsconfig-paths: "npm:6.1.1"
vitest: "npm:4.0.18"
vue: "npm:2.7.16"
vue2-daterange-picker: "npm:0.6.8"
@@ -10341,14 +10365,15 @@ __metadata:
languageName: node
linkType: hard
"jsdom@npm:28.0.0":
version: 28.0.0
resolution: "jsdom@npm:28.0.0"
"jsdom@npm:28.1.0":
version: 28.1.0
resolution: "jsdom@npm:28.1.0"
dependencies:
"@acemir/cssom": "npm:^0.9.31"
"@asamuzakjp/dom-selector": "npm:^6.7.6"
"@asamuzakjp/dom-selector": "npm:^6.8.1"
"@bramus/specificity": "npm:^2.4.2"
"@exodus/bytes": "npm:^1.11.0"
cssstyle: "npm:^5.3.7"
cssstyle: "npm:^6.0.1"
data-urls: "npm:^7.0.0"
decimal.js: "npm:^10.6.0"
html-encoding-sniffer: "npm:^6.0.0"
@@ -10359,7 +10384,7 @@ __metadata:
saxes: "npm:^6.0.0"
symbol-tree: "npm:^3.2.4"
tough-cookie: "npm:^6.0.0"
undici: "npm:^7.20.0"
undici: "npm:^7.21.0"
w3c-xmlserializer: "npm:^5.0.0"
webidl-conversions: "npm:^8.0.1"
whatwg-mimetype: "npm:^5.0.0"
@@ -10370,7 +10395,7 @@ __metadata:
peerDependenciesMeta:
canvas:
optional: true
checksum: 10/c50461190982834446308bbfdfbbb829c6447b1693b1f0dd90fd717960a1d02c326cc90c9a378831d9bf8166702e57dcbf12691ddd7406c13d0a522c7b8971d9
checksum: 10/700ef06cf3a72998173205e49c7565926c22f51f562400ec033d426fe0a419f4209c3527735b8dd22eddef9798c905810600b89c84c3474447819fa8b37848ab
languageName: node
linkType: hard
@@ -10797,10 +10822,10 @@ __metadata:
languageName: node
linkType: hard
"lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1, lru-cache@npm:^11.2.4":
version: 11.2.4
resolution: "lru-cache@npm:11.2.4"
checksum: 10/3b2da74c0b6653767f8164c38c4c4f4d7f0cc10c62bfa512663d94a830191ae6a5af742a8d88a8b30d5f9974652d3adae53931f32069139ad24fa2a18a199aca
"lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1, lru-cache@npm:^11.2.5, lru-cache@npm:^11.2.6":
version: 11.2.6
resolution: "lru-cache@npm:11.2.6"
checksum: 10/91222bbd59f793a0a0ad57789388f06b34ac9bb1613433c1d1810457d09db5cd3ec8943227ce2e1f5d6a0a15d6f1a9f129cb2c49ae9b6b10e82d4965fddecbef
languageName: node
linkType: hard
@@ -11099,15 +11124,6 @@ __metadata:
languageName: node
linkType: hard
"minimatch@npm:^9.0.5":
version: 9.0.5
resolution: "minimatch@npm:9.0.5"
dependencies:
brace-expansion: "npm:^2.0.1"
checksum: 10/dd6a8927b063aca6d910b119e1f2df6d2ce7d36eab91de83167dd136bb85e1ebff97b0d3de1cb08bd1f7e018ca170b4962479fefab5b2a69e2ae12cb2edc8348
languageName: node
linkType: hard
"minimist@npm:^1.2.0, minimist@npm:^1.2.6":
version: 1.2.8
resolution: "minimist@npm:1.2.8"
@@ -11175,13 +11191,6 @@ __metadata:
languageName: node
linkType: hard
"minipass@npm:^4.0.0":
version: 4.2.8
resolution: "minipass@npm:4.2.8"
checksum: 10/e148eb6dcb85c980234cad889139ef8ddf9d5bdac534f4f0268446c8792dd4c74f4502479be48de3c1cce2f6450f6da4d0d4a86405a8a12be04c1c36b339569a
languageName: node
linkType: hard
"minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2, minipass@npm:^7.1.3":
version: 7.1.3
resolution: "minipass@npm:7.1.3"
@@ -12577,8 +12586,8 @@ __metadata:
linkType: hard
"rollup@npm:^2.43.1":
version: 2.79.2
resolution: "rollup@npm:2.79.2"
version: 2.80.0
resolution: "rollup@npm:2.80.0"
dependencies:
fsevents: "npm:~2.3.2"
dependenciesMeta:
@@ -12586,7 +12595,7 @@ __metadata:
optional: true
bin:
rollup: dist/bin/rollup
checksum: 10/095ba0a82811b1866a76d826987743278db0a87c45092656986bfff490326b66187d5f9ff0c24cf8d5682bc470aa00c36654e0044d6b6335ac0c1201b8280880
checksum: 10/1150ab0f71d59e25a0fe6c0d07e49615ada1e9deba1754073be527c48c558a019fcd31d4d927a9c172593b7dc9c7c3c6871ef07fe1e575371ee24400a7c58213
languageName: node
linkType: hard
@@ -13734,16 +13743,16 @@ __metadata:
languageName: node
linkType: hard
"tar@npm:7.5.8, tar@npm:^7.5.2":
version: 7.5.8
resolution: "tar@npm:7.5.8"
"tar@npm:*, tar@npm:7.5.9, tar@npm:^7.5.2":
version: 7.5.9
resolution: "tar@npm:7.5.9"
dependencies:
"@isaacs/fs-minipass": "npm:^4.0.0"
chownr: "npm:^3.0.0"
minipass: "npm:^7.1.2"
minizlib: "npm:^3.1.0"
yallist: "npm:^5.0.0"
checksum: 10/5fddc22e0fd03e73d5e9e922e71d8681f85443dee4f21403059a757e186ae4004abc9a709cdc7f4143d7d75758a2935f7306b3cc193123d46b6f786dd2b99c2a
checksum: 10/1213cdde9c22d6acf8809ba5d2a025212ce3517bc99c4a4c6981b7dc0489bf3b164db9c826c9517680889194c9ba57448c8ff0da35eca9a60bb7689bf0b3897d
languageName: node
linkType: hard
@@ -14129,12 +14138,12 @@ __metadata:
languageName: node
linkType: hard
"type-fest@npm:^5.2.0":
version: 5.4.1
resolution: "type-fest@npm:5.4.1"
"type-fest@npm:^5.4.4":
version: 5.4.4
resolution: "type-fest@npm:5.4.4"
dependencies:
tagged-tag: "npm:^1.0.0"
checksum: 10/be7d4749e1e5cf2e2c9904fa1aaf9da5eef6c47c130881bf93bfd5a670b2ab59c5502466768e42c521281056a2375b1617176a75cf6c52b575f4bbabbd450b21
checksum: 10/0bbdca645f95740587f389a2d712fe8d5e9ab7d13e74aac97cf396112510abcaab6b75fd90d65172bc13b02fdfc827e6a871322cc9c1c1a5a2754d9ab264c6f5
languageName: node
linkType: hard
@@ -14201,18 +14210,18 @@ __metadata:
languageName: node
linkType: hard
"typescript-eslint@npm:8.54.0":
version: 8.54.0
resolution: "typescript-eslint@npm:8.54.0"
"typescript-eslint@npm:8.56.1":
version: 8.56.1
resolution: "typescript-eslint@npm:8.56.1"
dependencies:
"@typescript-eslint/eslint-plugin": "npm:8.54.0"
"@typescript-eslint/parser": "npm:8.54.0"
"@typescript-eslint/typescript-estree": "npm:8.54.0"
"@typescript-eslint/utils": "npm:8.54.0"
"@typescript-eslint/eslint-plugin": "npm:8.56.1"
"@typescript-eslint/parser": "npm:8.56.1"
"@typescript-eslint/typescript-estree": "npm:8.56.1"
"@typescript-eslint/utils": "npm:8.56.1"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10/21b1a27fd44716df8d2c7bac4ebd0caef196a04375fff7919dc817066017b6b8700f1e242bd065a26ac7ce0505b7a588626099e04a28142504ed4f0aae8bffb1
checksum: 10/e18cd347ddce0f0e5b28121346f27736a418adf68e73d613690ea3a1d0adfe03bc393f77a8872c2cef77ca74bcc0974212d1775c360de33a9987a94cda11a05b
languageName: node
linkType: hard
@@ -14335,10 +14344,10 @@ __metadata:
languageName: node
linkType: hard
"undici@npm:^7.20.0":
version: 7.20.0
resolution: "undici@npm:7.20.0"
checksum: 10/09ca3e1255cf05f3c76e6dff2ae760131ea5bba57290b9b184bd94f5167939548e7ea73292c524c25eb91f5a2152623394d4c6124e222d34fcd53ef733c6b156
"undici@npm:^7.21.0":
version: 7.22.0
resolution: "undici@npm:7.22.0"
checksum: 10/a7a1813ba4b74c0d46cc8dd160386202c05699ffc487c5d882cf40e6d2435c8d6faff3b8f8675d09bd1ef0386e370675c26b59b9a8c8b3f17b9f82a42236a927
languageName: node
linkType: hard
@@ -14593,16 +14602,16 @@ __metadata:
languageName: node
linkType: hard
"vite-tsconfig-paths@npm:6.0.5":
version: 6.0.5
resolution: "vite-tsconfig-paths@npm:6.0.5"
"vite-tsconfig-paths@npm:6.1.1":
version: 6.1.1
resolution: "vite-tsconfig-paths@npm:6.1.1"
dependencies:
debug: "npm:^4.1.1"
globrex: "npm:^0.1.2"
tsconfck: "npm:^3.0.3"
peerDependencies:
vite: "*"
checksum: 10/1c3d38102ed34d057fc602c332bfd059bfedd0b378ee87b1a73eac89e20f6d81ee4bd9639557287e275cae2230f1d9225d2d7d83a2fa355a380cf77568f2cd31
checksum: 10/f752bce4f3c5707f0df7af8a20294b1f325e26f50578b82c8262d851028616ebb1a3e73ab0789c55cf3c8da8d985e843193c0bec2cb31662c567ccdf137f1fd0
languageName: node
linkType: hard
@@ -15693,14 +15702,14 @@ __metadata:
languageName: node
linkType: hard
"zxing-wasm@npm:2.2.4":
version: 2.2.4
resolution: "zxing-wasm@npm:2.2.4"
"zxing-wasm@npm:3.0.0":
version: 3.0.0
resolution: "zxing-wasm@npm:3.0.0"
dependencies:
"@types/emscripten": "npm:^1.41.5"
type-fest: "npm:^5.2.0"
type-fest: "npm:^5.4.4"
peerDependencies:
"@types/emscripten": ">=1.39.6"
checksum: 10/e5928cbb066c854c970cbf724e978e502c3469d69de2469bd37d1f6ab8f5d2a2acdbaa9dea32d35cfc058e2b482e29a9c4f12161d9df3e1e952c30dda3a96d8c
checksum: 10/0acf04829acf8f3987173af011784642792fc877c7765f79222fe33efff8af09fbf95bf5d590d2490ae39ec411e6c4de06ea24e96d4eb48189b9d06f7502eaa2
languageName: node
linkType: hard