Compare commits

..
2 Commits
Author SHA1 Message Date
Simon LamonandPetar Petrov 786bacfa71 Update src/panels/config/helpers/dialog-helper-detail.ts
Co-authored-by: Petar Petrov <[email protected]>
2026-10-29 17:15:15 +01:00
Simon Lamon d085dd2b70 dialog-helper-detail migrate list 2026-10-29 15:29:53 +00:00
33 changed files with 395 additions and 694 deletions

No files matched your search

+3 -5
View File
@@ -51,8 +51,8 @@
- This PR fixes or closes issue: fixes #
- This PR is related to issue or discussion:
- Link to [documentation][docs-repository] pull request:
- Link to [contributors documentation][contributors-repository] pull request:
- Link to documentation pull request:
- Link to developer documentation pull request:
- Link to backend pull request:
## Checklist
@@ -63,8 +63,7 @@
for before merging your code.
AI tools are welcome, but contributors are responsible for *fully*
understanding the code before submitting a PR. Please follow our AI policy:
https://contributors.home-assistant.io/start/ai-policy/
understanding the code before submitting a PR.
-->
- [ ] I understand the code I am submitting and can explain how it works.
@@ -106,5 +105,4 @@ To help with the load of incoming pull requests:
Below, some useful links you could explore:
-->
[docs-repository]: https://github.com/home-assistant/home-assistant.io
[contributors-repository]: https://github.com/home-assistant/contributors.home-assistant.io
[perfect-pr]: https://contributors.home-assistant.io/start/pull-requests/#before-you-open-it
+1 -1
View File
@@ -1 +1 @@
24.22.2
24.22.1
+2 -1
View File
@@ -1,3 +1,4 @@
import type { ActionDetail } from "@material/mwc-list/mwc-list";
import { mdiCast, mdiCastConnected, mdiViewDashboard } from "@mdi/js";
import type { Auth, Connection } from "home-assistant-js-websocket";
import type { TemplateResult, PropertyValues } from "lit";
@@ -214,7 +215,7 @@ class HcCast extends LitElement {
this.castManager.requestSession();
}
private async _handlePickView(ev: CustomEvent<{ index: number }>) {
private async _handlePickView(ev: CustomEvent<ActionDetail>) {
const path = this.lovelaceViews?.[ev.detail.index]?.path ?? ev.detail.index;
await ensureConnectedCastSession(this.castManager!, this.auth!);
castSendShowLovelaceView(this.castManager, this.auth.data.hassUrl, path);
@@ -50,18 +50,6 @@ With no cursor yet, <kbd>↓</kbd> and <kbd>Enter</kbd> start from the `value`
row, or from the top match while searching. With one item in the list,
<kbd>Enter</kbd> picks it whether or not the cursor has moved.
## Screen readers
DOM focus stays in the search field, so screen readers do not hear the list
change. While searching, a visually hidden `role="status"` message says how
many items match the search and names it, so a new search with the same count
is still read out. It is cleared as soon as the list changes and filled in once
typing pauses for half a second, so it doesn't talk over each typed character
or describe the previous search. When nothing matches, it reads a not
found label that takes the search, or says there are no results for it. Section
titles, placeholder rows, "Add custom item", the additional items and rows that
`isSearchResult` rejects are not counted.
## Implementation
Without `sections`, the component filters the items from `getItems` itself as the
@@ -91,7 +79,6 @@ means supplying one.
| allowCustomValue | Boolean | false | Offers the typed string as an item. |
| customValueLabel | String | - | Label for that custom item. |
| notFoundLabel | String/Function | - | Shown when a search matches nothing. |
| isSearchResult | Function | - | Whether a row from `getItems` counts as a match for screen readers. The quick bar leaves out its "Ask Assist" row. |
| emptyLabel | String | - | Shown when there are no items at all. |
| noSort | Boolean | false | Keeps the order `getItems` returned. |
| clearable | Boolean | false | Adjusts search field padding for a clear affordance. |
@@ -1,9 +1,7 @@
import { ContextProvider } from "@lit/context";
import { IntlMessageFormat } from "intl-messageformat";
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators";
import type { LocalizeFunc } from "../../../../src/common/translations/localize";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-picker-combo-box";
import type { PickerComboBoxItem } from "../../../../src/components/ha-picker-combo-box";
@@ -21,26 +19,13 @@ import type {
} from "../../../../src/types";
import { THEME_COMPARISON_PANELS } from "../../components/demo-theme-comparison";
// The English strings, plurals included, so searching a demo announces the
// same count and search as the real picker.
const LOCALIZE_KEYS: Record<string, string> = {
"ui.common.search": "Search",
"ui.components.combo-box.no_match": "No matching items found",
"ui.components.combo-box.no_items": "No items available",
"ui.components.combo-box.result_count":
"{count} {count, plural,\n one {result}\n other {results}\n} for {term}",
"ui.components.combo-box.no_results": "No results for {term}",
};
const localize: LocalizeFunc = (key, values) => {
const message = LOCALIZE_KEYS[key];
if (message === undefined) {
return key;
}
return new IntlMessageFormat(message, "en").format<string>(
values as Record<string, string | number>
) as string;
};
const localize = (key: string) => LOCALIZE_KEYS[key] ?? key;
const DEMO_I18N: HomeAssistantInternationalization = {
localize,
+7 -7
View File
@@ -101,7 +101,7 @@
"fullcalendar": "7.1.3",
"fuse.js": "7.5.0",
"hls.js": "1.7.3",
"home-assistant-js-websocket": "9.8.1",
"home-assistant-js-websocket": "9.8.0",
"idb-keyval": "6.3.0",
"intl-messageformat": "12.1.4",
"js-yaml": "5.5.0",
@@ -110,7 +110,7 @@
"lit": "3.3.3",
"lit-html": "3.3.3",
"maplibre-gl": "6.16.0",
"marked": "18.1.2",
"marked": "18.1.1",
"memoize-one": "6.0.0",
"nanoid": "6.0.2",
"node-vibrant": "4.0.4",
@@ -173,7 +173,7 @@
"@vitest/coverage-v8": "5.0.5",
"babel-loader": "10.1.1",
"babel-plugin-polyfill-corejs3": "1.0.0",
"browserslist": "4.29.5",
"browserslist": "4.29.4",
"browserslist-useragent-regexp": "4.1.4",
"core-js-compat": "3.51.0",
"del": "9.0.1",
@@ -188,7 +188,7 @@
"fancy-log": "2.0.0",
"fs-extra": "11.4.1",
"generate-license-file": "4.2.5",
"glob": "14.0.3",
"glob": "13.0.6",
"globals": "17.13.0",
"gulp": "5.0.1",
"gulp-json-transform": "0.5.0",
@@ -214,7 +214,7 @@
"terser-webpack-plugin": "5.6.1",
"ts-lit-plugin": "2.0.2",
"typescript": "6.0.3",
"typescript-eslint": "8.72.1",
"typescript-eslint": "8.72.0",
"vite": "8.3.5",
"vite-tsconfig-paths": "6.1.1",
"vitest": "5.0.5",
@@ -222,8 +222,8 @@
"webpackbar": "7.0.0",
"workbox-build": "7.4.1"
},
"packageManager": "[email protected]6.1",
"packageManager": "[email protected]5.0",
"volta": {
"node": "24.22.2"
"node": "24.22.1"
}
}
+179 -212
View File
@@ -7,153 +7,153 @@ importers:
configDependencies: {}
packageManagerDependencies:
pnpm:
specifier: 12.16.1
version: 12.16.1
specifier: 12.15.0
version: 12.15.0
packages:
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-PKf78Ew+i0CBYf0Xc+eMcqQiqyBT+u8XCVg1F5roc98/6wWfdYlWhrUMmEBiKWaJ3JqHxrtt8l1NwZ7qfJt2/Q==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-eVCqmscY70LGvgRzu3mi8IBWBFGix+a6mNZoWmXxESsBdeiKEF9xQSuaeel10yn+zI7TXy2jlI63vFLzETk+aQ==}
cpu: [arm64]
os: [android]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-xdu7gMbB98pdvhwMeA6612Of515FDlRUtfA/1f7nWPZfPLnEdSRBO2u+1N0XBtQ/ennhPH/lrxB1gC6gnR/cdg==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-Gx/WbkFcdUFUg8g8AShezcS9EiQxfYvdAm2hfKLO8sfJmJvKOCt5fzlgHWDzmGhoclibgW+tUGZ/KF4F4wOTCA==}
cpu: [x64]
os: [android]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-pVbmIIbhixiLvADLu1WA3TaW8FZy/D72R1De27WbbFx8/2mxvnsTyFVm4fO9kjpjMY7RzJd48CiQ96p8fO3ebQ==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-N0ZykiDWCvqSBJvt71j7cSoBR993FqvYZFtmpCtqvW3pguiI+NAgraLPA5OTwu5mV+/d8hYpVcPktJA3xFDLtA==}
cpu: [arm64]
os: [darwin]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-xZvQBFqcZjO7vFKTK3XsJpqY6lnBL9EWSLCzVUPq3kZ94+D96gwJCa76xxGNK8Cj32f4eeM91Qg+yNRR4sRpDw==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-7Ntr2HlBUxzwWOg7NwDxCbRW/3vXuqKO+hcXm+w3SBi9rrHY53li1wLqWVT7Gjxd+lVEHM1QJZo6WJEGFU8C6A==}
cpu: [x64]
os: [darwin]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-zTtunfi9mBhRXiXEJYfwiJj0tk7MgTSfqDSRh+Az9FZ9THazVIiQiVNS8jpcsftDOqu7LKNffQdjmgwHDThfUg==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-btOiyL7fL7W4uQGH0aqFai2TNC3IoKcZ7gNHBVbEFZt2dWrnrD0SufL3iGs3fLlmb4OtuU35uf4Zpr9V9Jh9mA==}
cpu: [x64]
os: [freebsd]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-BJ3mOmcmQgcUo92Ee/WfEOt1pRiv3y2MMAkhEiYHd85UiPpHTfFhv+SpCbALmfExzXk3UlaRtMYwHlkQymc4VA==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-pNC38k+O+90FOjbPNSnw0E7apq1PKTmz3fFe1amn+lys/U5kL++uzir8bRiho8ONcyA3d9EU7wdqcY0DKkj+JA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-JaRd5gNxwdNGBBkrZFt8bknrK4YmHVJBW0JMhUQ0fJ0dEYp6C2GT9ExaCqOO8EwYEyqM+jpKgJIK+8WFaJy3ew==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-qML/8aCXslh8td/w4U+HJNqUcZ2+m6EfTbWScIzZRmyPsRFN+xB4LP1U/hymxc1iSJiKtG56HJx2fvUErWFIGw==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-FnSV0Jv40S1cMv7vFNWwvu0X567Lec4L4HCRead3CFcD6zQDNbGw81s8N5bcKPahtPD9ApVuhsbmFCx4rw6RMw==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-tjRDUUl7RCJ6T/6eoNPxOqkwU4Mzi5RtTXmSAxujyz37OTwwsMU7Ps087Zk4gHcUvRSeyF40ZFsew3vtE+nmUA==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-C1Sww4FN5IttD4atRRhAKmQtSGWVp04ZAKNxO8pfu2bkRPwOW+7v+2DH1Xs1W+kZYYpO86BYDvUcadefF+AgaQ==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-bF1uBWEfbwaeryz6lIiaJ8AWD082otZfvzGX5l+6LZRpRwUEpJHUsJrORaYP5/cNMv5ZR2p6TvvcJcQzwtDzmw==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-kn2fautsTcxIMODoovQVqZyfpDRdNgGkoeVqNdrKqbeBBvrEl+fXLkmZiq5xDht1LMr4sYiCNcsMfNMT6JPFmg==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-zKMhIzsexYMToeLmqV5jPsvV/f9vwsJb2kUH2NFYzalbxImeBrlA4kL7GwF8gD4pagV6jYYcJb8RjbZIdjHptg==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-PM6ccHCOe/O9SsTflTJTYWfwogJZa6EmUvpnwZgiPguJBddh20wDQKgxUPXf48rDsPm9vMsIij0uHswwwbXL8g==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-A9J0Jg0Rdx+qQU4qXtwyST5tto9IOu1zi4fDk35nbc6DWahggbcKtFvZPKFwL2qgUXGXOX//hXv6z/sp6emO8A==}
cpu: [x64]
os: [linux]
libc: [musl]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-RK//8ZLcXGW8A2k8bQOXZDBN1Qu92zN4dYnG1bzj1zoQ1fkZ6jNzZ1AvXtsfGVma795CJtvoaF5bLXf4l/FIUw==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-yc+QlZR+9+nr29J4fRzhMoapgxTBDndq/+peyoq1XUufnQFnfbXUMFudDIKzHi545linGqmOmXfn0NoufNgcOg==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-Ox3kNNVxtGw6pK7SVejmeOUgHhUTZgAM7NQQ6cU7frPw3ix9+j7d2MGbRg3fyEFAaKWq8ZAZLTQGcDyLnAu+qA==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-fPXZxuY1VclkOga9bc53qNCXcegfeoBR8+Ue+AospDwKzuGGSHll0oDxkLfkmpjyRqpe7bH5DyQPYp/xSMaIVA==}
cpu: [arm64]
os: [win32]
'@pnpm/[email protected]6.1':
resolution: {integrity: sha512-k+FhRJ0ttphFoFIVB1Sk4v76YJAulafmA/Ly57cysesUhhIzVlApeOShUz0jXubKx317TThlEfpQrukldnqORA==}
'@pnpm/[email protected]5.0':
resolution: {integrity: sha512-nrd+Tp1We1DGj4DGG5Bea9lZNh9y1PjlLBdEwdInS4D0h0UIDtM7JaGGGDJhNzIwcHASyihWI7HLV+dtG+fhYg==}
cpu: [x64]
os: [win32]
[email protected]6.1:
resolution: {integrity: sha512-CR0d7nknV1Zhsl2rPCrjHK/BxU1rce1qZgDPDByxBDSkR+rhQBXxsj4ua+3u1535SpMuIWTSgyKA3OP7MvZW0Q==}
[email protected]5.0:
resolution: {integrity: sha512-s5UdbW/0qfE9x89WzSjSuOs328ycaOUuHhGRhz6p+CoBcoerULqtxczElPA2xnwOR+sTYIwvo29HcRth6hKOYQ==}
engines: {node: '>=18'}
hasBin: true
snapshots:
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
'@pnpm/[email protected]6.1':
'@pnpm/[email protected]5.0':
optional: true
[email protected]6.1:
[email protected]5.0:
optionalDependencies:
'@pnpm/exe.android-arm64': 12.16.1
'@pnpm/exe.android-x64': 12.16.1
'@pnpm/exe.darwin-arm64': 12.16.1
'@pnpm/exe.darwin-x64': 12.16.1
'@pnpm/exe.freebsd-x64': 12.16.1
'@pnpm/exe.linux-arm64': 12.16.1
'@pnpm/exe.linux-arm64-musl': 12.16.1
'@pnpm/exe.linux-ppc64': 12.16.1
'@pnpm/exe.linux-riscv64': 12.16.1
'@pnpm/exe.linux-s390x': 12.16.1
'@pnpm/exe.linux-x64': 12.16.1
'@pnpm/exe.linux-x64-musl': 12.16.1
'@pnpm/exe.win32-arm64': 12.16.1
'@pnpm/exe.win32-x64': 12.16.1
'@pnpm/exe.android-arm64': 12.15.0
'@pnpm/exe.android-x64': 12.15.0
'@pnpm/exe.darwin-arm64': 12.15.0
'@pnpm/exe.darwin-x64': 12.15.0
'@pnpm/exe.freebsd-x64': 12.15.0
'@pnpm/exe.linux-arm64': 12.15.0
'@pnpm/exe.linux-arm64-musl': 12.15.0
'@pnpm/exe.linux-ppc64': 12.15.0
'@pnpm/exe.linux-riscv64': 12.15.0
'@pnpm/exe.linux-s390x': 12.15.0
'@pnpm/exe.linux-x64': 12.15.0
'@pnpm/exe.linux-x64-musl': 12.15.0
'@pnpm/exe.win32-arm64': 12.15.0
'@pnpm/exe.win32-x64': 12.15.0
---
lockfileVersion: '9.0'
@@ -364,8 +364,8 @@ importers:
specifier: 1.7.3
version: 1.7.3
home-assistant-js-websocket:
specifier: 9.8.1
version: 9.8.1
specifier: 9.8.0
version: 9.8.0
idb-keyval:
specifier: 6.3.0
version: 6.3.0
@@ -391,8 +391,8 @@ importers:
specifier: 6.16.0
version: 6.16.0
marked:
specifier: 18.1.2
version: 18.1.2
specifier: 18.1.1
version: 18.1.1
memoize-one:
specifier: 6.0.0
version: 6.0.0
@@ -575,11 +575,11 @@ importers:
specifier: 1.0.0
version: 1.0.0(@babel/[email protected])
browserslist:
specifier: 4.29.5
version: 4.29.5
specifier: 4.29.4
version: 4.29.4
browserslist-useragent-regexp:
specifier: 4.1.4
version: 4.1.4([email protected].5)
version: 4.1.4([email protected].4)
core-js-compat:
specifier: 3.51.0
version: 3.51.0
@@ -597,7 +597,7 @@ importers:
version: 0.13.11([email protected])
eslint-plugin-import-x:
specifier: 4.17.1
version: 4.17.1(@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])
version: 4.17.1(@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])
eslint-plugin-lit:
specifier: 2.3.1
version: 2.3.1([email protected]([email protected]))
@@ -606,7 +606,7 @@ importers:
version: 5.1.3([email protected]([email protected]))
eslint-plugin-unused-imports:
specifier: 4.4.1
version: 4.4.1(@typescript-eslint/[email protected].1(@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))
version: 4.4.1(@typescript-eslint/[email protected].0(@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))
eslint-plugin-wc:
specifier: 3.1.0
version: 3.1.0([email protected]([email protected]))
@@ -620,8 +620,8 @@ importers:
specifier: 4.2.5
version: 4.2.5([email protected])
glob:
specifier: 14.0.3
version: 14.0.3
specifier: 13.0.6
version: 13.0.6
globals:
specifier: 17.13.0
version: 17.13.0
@@ -698,8 +698,8 @@ importers:
specifier: 6.0.3
version: 6.0.3
typescript-eslint:
specifier: 8.72.1
version: 8.72.1([email protected]([email protected]))([email protected])([email protected])
specifier: 8.72.0
version: 8.72.0([email protected]([email protected]))([email protected])([email protected])
vite:
specifier: 8.3.5
version: 8.3.5(@types/[email protected])([email protected])([email protected])
@@ -2078,9 +2078,6 @@ packages:
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
engines: {node: '>=18.0.0'}
'@isaacs/[email protected]':
resolution: {integrity: sha512-GJPHIgPPtFl+nLhFHyF0zZoFcOFLsZWbHFFzo+Zr+PWDXJbl9hHxb2w+9SiF2fHmLgKaXIpUzQo3SbBBZ9WObw==}
'@isaacs/[email protected]':
resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==}
@@ -3375,63 +3372,63 @@ packages:
'@types/[email protected]':
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-5CokTWXpmbylfFabsbvHC0CAw3XLaGnoa+nFJX5FR592h/LoZsENUE6p/rg5xvkKrFEXz6pYmgI29AgXc2N3BQ==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-aysKgysPX9XOv/dk95UkvUDe++Q3n3dJPG9CEWT3RUccxfkPJ+Qn6nhKPDhZXU6Ofo9kgwGWwKyQCnZIXTgngg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.72.1
'@typescript-eslint/parser': ^8.72.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-ZGwZP4OCfyA0AQTpEAMWz+rtX01DRhQWW5hB0ucKDEIX5U7jdmPSaMx94rQfaPAQzIYz2BimOgKOJtjfpRFQ9g==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-0O+x3ynciD6zuXb1CKSu165haQV6ey53DKhHHUnujP7U+XlltJG+/keT0Xhd1HXCze+IHf7Tvt39ovyepX/LNw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-fAuVMkwdO/huI8nyo/WKnNKf6Gag93S56Rh3Ts5mGcavwSdaN8tRg1gCeIGX8PF+nzp1BjGfO4gHhGzW1J6jTg==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-bzHngBbmIgzj6TsTjVUCntGx6FFLgE7mPjpO0PzHycOaZHXqS43XnrkFIHRS16LLr/xO6FHSXG3GJFo/F4bSBQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-lC/t6eMCZZQAAKZEYGL6RDVSuFehpdmMT6h+nJIjIa6oylN/PwDgDVtEIbB7O9xFfZYtZAYLoLlDNWKJhtF+uQ==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-JewPyJOYcXBSAS7PIgufscHOwZqhTGyBRiQJhhuDln66tMchxvvt7nJ90JKKIoOelmdHA3kAQbm9cEUHc4JSEA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-e4D5R5vpeAEPBxT2BAzsFQL3sbwyeeeo5+aczgNSRK1V734jE7pTqaGFU+fXapWEQwnZbpFaTn32+Z8DwS6OTg==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-0vbxCf7xLVPSjcOdm6eQbgViH8EDJ8xnl1laLT9yoqSz2YmcSfSg5Vdl0JUvZf6rcuJ0ZivJIuMD4edTg8obaA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-iY2wlmyrXJmx4yxUGP3aYCFF3cA/6ShddOKmLU2dx7LnEykbAM8WThlxZEfd1NddqceF6eJmZUayxx9oKIYNlg==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-gEXxmmbSTSOVTC37IYYvremOM31v+UN2W772bJxmVYPhAOPSUxtacyb7wkm1EhkYKU6KzFJsdU44DCV4to0LWw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-LmE5IhQet1BWOWEXqBrVtBPsMAOQ6Nzk35d+WLh3mk4EUF33sqlfxjio1MdYeSvKSG5skactKKuixBIKXhL4Rw==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-Adfoy59kxNEjT5E5fnyrp7GpHYuWs8ONbdohu4ez6IU46qDq8LltG90tLmkucZB2uhYL8mqBjtXqGd8yhfjXqQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-DAlUoUV93hIvrtIQLwCbmZQYVZwOMhiHJrOVUUIWicFZaIYjTRqlY3I/NZevfkLmSqkNHRu2qYDcq9lrn16oOQ==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-gwLfFgWcw15tN2KXDCJvxEOQjPn+P3j/n3eSqkZ5sX4VpW9Cosodr+tWwBZRvJT3TcKx6HnPRGZMCNAiP1Xhug==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-5v5liypurJBFHCBNqh/RjsymAD+VWcE0djuGY/BUqp5fC3Qn+luWDEksjuTtWjPn6i5zQlUtkZCRG/CYG0yCkA==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-0up3oArJZBYnzOaEXKo8DmI43QvMZyPoFEt9LWzRJcyl/RcJjfKKPebknN1VbTgXBf3M/KggUh5uUMdURLnseg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/[email protected].1':
resolution: {integrity: sha512-SB8xqipSzZHUePCCLNeYxqnxq83X61/qzNhjQGbTfjxGZIeOEP7tBgWYX05Tcd6CgE02WdTJnh5b8kMZJ/+bnQ==}
'@typescript-eslint/[email protected].0':
resolution: {integrity: sha512-E2mroviasaWecDzTGiGMtuEguuLVOeRggnrIn93CJuxYJzQBHbyymlT08aVQydbBal5538o+JkBKXh2sRuCyIA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript/[email protected]':
@@ -4049,8 +4046,8 @@ packages:
resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
engines: {node: ^4.5.0 || >= 5.9}
[email protected].33:
resolution: {integrity: sha512-yiVKDX+qCMRKBE084lXvq9EcwFUhKZ2nU8TK1EQQuOgPNR/lmbGxXOeDdlGUqC2Zz11Cs9rk1d/8NfgBmlkt0w==}
[email protected].29:
resolution: {integrity: sha512-YeesxhUmR4h5y5V8KF8iBCqJb8YFrBJ++XBTeGcWIaQOYXGN19JM0FoiOjAhwuDoln8owMgXcWBmgHtYSkky2w==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -4094,8 +4091,8 @@ packages:
[email protected]:
resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==}
[email protected].12:
resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==}
[email protected].9:
resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
engines: {node: 20 || >=22}
[email protected]:
@@ -4116,8 +4113,8 @@ packages:
peerDependencies:
browserslist: '>=4.0.0'
[email protected].5:
resolution: {integrity: sha512-khTmKu5NGYTotqcYo8Bew2k4RAE9PuXRSFRXG2lQBrCEQHyeQ/vX6gKMxfokwywBsLiXZMnHsmWMG1pnO8J7uQ==}
[email protected].4:
resolution: {integrity: sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
@@ -4175,8 +4172,8 @@ packages:
resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
engines: {node: '>=14.16'}
[email protected]9:
resolution: {integrity: sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==}
[email protected]6:
resolution: {integrity: sha512-+8Yx7BXCoqk6IF8yTicjfUR6D/ldJzdlsodlEOiOSPmhK844WIgk67/zIQaGAOxNkZyyvBlrRFnLvqKIoqbAFw==}
[email protected]:
resolution: {integrity: sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==}
@@ -4608,8 +4605,8 @@ packages:
engines: {node: '>=0.10.0'}
hasBin: true
[email protected]64:
resolution: {integrity: sha512-nRa65aFge40viPAKxMKULIY8tcXKwKboJWNn4RoKwyWXJ6SP7BnrDGKUTzc64818jIciH0PK7LSF8QzZes19GA==}
[email protected]59:
resolution: {integrity: sha512-4SC9HHSFjO/liAhifpdOL5hG9b4BP7/5G3y3UPZVO8trlAXr1CaUEEJL0gWK3kOcYcZrOA5rkwG45Gra/lTIgg==}
[email protected]:
resolution: {integrity: sha512-uB0/Qube3lkwh8SmkTnGIyUgJ9YdqVSzIoHMRCEQjAbD4Y5UzsVbch1tIxjTgUe5k3gy1U0ZMKMJ90A81lqwig==}
@@ -5114,10 +5111,6 @@ packages:
resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
engines: {node: 18 || 20 || >=22}
[email protected]:
resolution: {integrity: sha512-A1vjIwC3qpdCso45Iw127gnp7sPhqgY8lUQhDrArIs+GbmfaaVPFuoyy7WyLT9EPZCRZ7j7aLdwUhQmHWesEow==}
engines: {node: 18 || 20 || >=22}
[email protected]:
resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==}
engines: {node: '>=0.10.0'}
@@ -5212,8 +5205,8 @@ packages:
[email protected]:
resolution: {integrity: sha512-MsPlx6yVW4Qv4C7mEVou4/gk/5cN2dVxOTnrNjPSmyH2f0Ln+/UkG10Ax1PE6OvrmTVPKgQYozTtBaPOuCzq7A==}
[email protected].1:
resolution: {integrity: sha512-WvovbrSoYLTKfh6aY5SxSWPPy50/mLWLCihQL8G2N+2e3mTrg3QTQCAp4R32/LwbkRBDGj0XNs6JFj8e2IYEUw==}
[email protected].0:
resolution: {integrity: sha512-Nl5asoKQJwJ5a8N0U72jkSAUdO+hsY/T+Upp0VaZMUSt6A2gtdyvKfBIEYbpnYK3NP83Q/YGaC5XYkO5c08Img==}
[email protected]:
resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==}
@@ -5914,8 +5907,8 @@ packages:
engines: {node: '>= 18'}
hasBin: true
[email protected].2:
resolution: {integrity: sha512-DfOnvLAQ6WYeWxWO1u4RyFOeqyHup6dks5PPqnoFiooU7ipRvidO/2j8plhAHIiZg574E9ZlzSjUiPMLAzFkgg==}
[email protected].1:
resolution: {integrity: sha512-zEGgrtUG8crk+TrMacJSVABU4DYDDkS8uqgU3ohrn/2fW9C2AEfUrO3m6IhpIpQpl7YcVpiXXC9cSMWDANT3dg==}
engines: {node: '>= 20'}
hasBin: true
@@ -5978,10 +5971,6 @@ packages:
resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==}
engines: {node: 18 || 20 || >=22}
[email protected]:
resolution: {integrity: sha512-pWTgz5CN3tjqyZNSK2tePlSmu9IwM41q8yn8Usdqqwe9TIHh+9dEpLLjF4uApsfPEAZY71qtSiA2B2APEr+1Yw==}
engines: {node: 18 || 20 || >=22}
[email protected]:
resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
@@ -6116,8 +6105,8 @@ packages:
engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0}
hasBin: true
[email protected].60:
resolution: {integrity: sha512-OmO8+GM1JUZqXET720VrJCwkjUCXmCMQm0Z3UDDRbfNLHS4NEAvY60j5jiFv0tkKw2PNNlqOLhahVmwJIOLDIQ==}
[email protected].59:
resolution: {integrity: sha512-5qr2okC4ItAI0hG5SaV0HoYMpnM/Y6+Oqr7AmPYy/2uEoGvS+GbSKLeRxSS1uAdu59yz0ouzcuXievSgg///WA==}
engines: {node: '>=18'}
[email protected]:
@@ -6387,10 +6376,6 @@ packages:
resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
engines: {node: 18 || 20 || >=22}
[email protected]:
resolution: {integrity: sha512-1pTbQqH1wIwMi/eleQ5leFTTCkzFsPcgXNjwOA8YGGW/W4/kHT3dssE7Z6NH+zuqNLOzOB0uaD61yl7cAcVhgg==}
engines: {node: 18 || 20 || >=22}
[email protected]:
resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==}
@@ -7309,8 +7294,8 @@ packages:
resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==}
engines: {node: '>= 0.4'}
[email protected].1:
resolution: {integrity: sha512-3Li9FfPmQp45nxEtFD1ZCrYFI3cYK5kpyNtmm1H7lMagm8u9sy6PTjy3ytwQZs7KNukOyKFHAZ6z6GjYFeaeXw==}
[email protected].0:
resolution: {integrity: sha512-r26Fkc8As+mZvqp7SLsMmNFyYUup/6CjK7/eHBHmhOw6GH6n6YFxHVFrG0jN1c5CMpDzelLPxvgeCOzx7BjN+A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
@@ -7978,7 +7963,7 @@ snapshots:
dependencies:
'@babel/compat-data': 7.29.7
'@babel/helper-validator-option': 7.29.7
browserslist: 4.29.5
browserslist: 4.29.4
lru-cache: 5.1.1
semver: 6.3.1
@@ -7986,7 +7971,7 @@ snapshots:
dependencies:
'@babel/compat-data': 8.0.5
'@babel/helper-validator-option': 8.0.0
browserslist: 4.29.5
browserslist: 4.29.4
flru: 1.0.2
verkit: 0.5.0
@@ -9579,8 +9564,6 @@ snapshots:
dependencies:
minipass: 7.1.3
'@isaacs/[email protected]': {}
'@isaacs/[email protected]': {}
'@jimp/[email protected](@jimp/[email protected])':
@@ -11075,14 +11058,14 @@ snapshots:
dependencies:
'@types/node': 24.19.2
'@typescript-eslint/[email protected].1(@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])':
'@typescript-eslint/[email protected].0(@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.72.1([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/scope-manager': 8.72.1
'@typescript-eslint/type-utils': 8.72.1([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/utils': 8.72.1([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/visitor-keys': 8.72.1
'@typescript-eslint/parser': 8.72.0([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/scope-manager': 8.72.0
'@typescript-eslint/type-utils': 8.72.0([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/utils': 8.72.0([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/visitor-keys': 8.72.0
eslint: 10.13.0([email protected])
ignore: 7.0.6
natural-compare: 1.4.0
@@ -11091,41 +11074,41 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected])':
'@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected])':
dependencies:
'@typescript-eslint/scope-manager': 8.72.1
'@typescript-eslint/types': 8.72.1
'@typescript-eslint/typescript-estree': 8.72.1([email protected])([email protected])
'@typescript-eslint/visitor-keys': 8.72.1
'@typescript-eslint/scope-manager': 8.72.0
'@typescript-eslint/types': 8.72.0
'@typescript-eslint/typescript-estree': 8.72.0([email protected])([email protected])
'@typescript-eslint/visitor-keys': 8.72.0
debug: 4.4.3([email protected])
eslint: 10.13.0([email protected])
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/[email protected].1([email protected])([email protected])':
'@typescript-eslint/[email protected].0([email protected])([email protected])':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.72.1([email protected])
'@typescript-eslint/types': 8.72.1
'@typescript-eslint/tsconfig-utils': 8.72.0([email protected])
'@typescript-eslint/types': 8.72.0
debug: 4.4.3([email protected])
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/[email protected].1':
'@typescript-eslint/[email protected].0':
dependencies:
'@typescript-eslint/types': 8.72.1
'@typescript-eslint/visitor-keys': 8.72.1
'@typescript-eslint/types': 8.72.0
'@typescript-eslint/visitor-keys': 8.72.0
'@typescript-eslint/[email protected].1([email protected])':
'@typescript-eslint/[email protected].0([email protected])':
dependencies:
typescript: 6.0.3
'@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected])':
'@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected])':
dependencies:
'@typescript-eslint/types': 8.72.1
'@typescript-eslint/typescript-estree': 8.72.1([email protected])([email protected])
'@typescript-eslint/utils': 8.72.1([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/types': 8.72.0
'@typescript-eslint/typescript-estree': 8.72.0([email protected])([email protected])
'@typescript-eslint/utils': 8.72.0([email protected]([email protected]))([email protected])([email protected])
debug: 4.4.3([email protected])
eslint: 10.13.0([email protected])
ts-api-utils: 2.5.0([email protected])
@@ -11133,14 +11116,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/[email protected].1': {}
'@typescript-eslint/[email protected].0': {}
'@typescript-eslint/[email protected].1([email protected])([email protected])':
'@typescript-eslint/[email protected].0([email protected])([email protected])':
dependencies:
'@typescript-eslint/project-service': 8.72.1([email protected])([email protected])
'@typescript-eslint/tsconfig-utils': 8.72.1([email protected])
'@typescript-eslint/types': 8.72.1
'@typescript-eslint/visitor-keys': 8.72.1
'@typescript-eslint/project-service': 8.72.0([email protected])([email protected])
'@typescript-eslint/tsconfig-utils': 8.72.0([email protected])
'@typescript-eslint/types': 8.72.0
'@typescript-eslint/visitor-keys': 8.72.0
debug: 4.4.3([email protected])
minimatch: 10.2.6
semver: 7.8.5
@@ -11150,20 +11133,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected])':
'@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected])':
dependencies:
'@eslint-community/eslint-utils': 4.10.1([email protected]([email protected]))
'@typescript-eslint/scope-manager': 8.72.1
'@typescript-eslint/types': 8.72.1
'@typescript-eslint/typescript-estree': 8.72.1([email protected])([email protected])
'@typescript-eslint/scope-manager': 8.72.0
'@typescript-eslint/types': 8.72.0
'@typescript-eslint/typescript-estree': 8.72.0([email protected])([email protected])
eslint: 10.13.0([email protected])
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/[email protected].1':
'@typescript-eslint/[email protected].0':
dependencies:
'@typescript-eslint/types': 8.72.1
'@typescript-eslint/types': 8.72.0
eslint-visitor-keys: 5.0.1
'@typescript/[email protected]':
@@ -11637,7 +11620,7 @@ snapshots:
[email protected]: {}
[email protected].33: {}
[email protected].29: {}
[email protected]: {}
@@ -11699,7 +11682,7 @@ snapshots:
dependencies:
balanced-match: 1.0.2
[email protected].12:
[email protected].9:
dependencies:
balanced-match: 4.0.4
@@ -11711,24 +11694,24 @@ snapshots:
[email protected]:
dependencies:
browserslist: 4.29.5
browserslist: 4.29.4
[email protected]([email protected].5):
[email protected]([email protected].4):
dependencies:
argue-cli: 2.1.0
browserslist: 4.29.5
browserslist: 4.29.4
easy-table: 1.2.0
picocolors: 1.1.1
regexp-tree: 0.1.27
ua-regexes-lite: 1.2.1
[email protected].5:
[email protected].4:
dependencies:
baseline-browser-mapping: 2.11.33
caniuse-lite: 1.0.30001819
electron-to-chromium: 1.5.464
node-releases: 2.0.60
update-browserslist-db: 1.3.4([email protected].5)
baseline-browser-mapping: 2.11.29
caniuse-lite: 1.0.30001816
electron-to-chromium: 1.5.459
node-releases: 2.0.59
update-browserslist-db: 1.3.4([email protected].4)
[email protected]: {}
@@ -11810,7 +11793,7 @@ snapshots:
[email protected]: {}
[email protected]9: {}
[email protected]6: {}
[email protected]: {}
@@ -11978,7 +11961,7 @@ snapshots:
[email protected]:
dependencies:
browserslist: 4.29.5
browserslist: 4.29.4
[email protected]: {}
@@ -12223,7 +12206,7 @@ snapshots:
dependencies:
jake: 10.9.4
[email protected]64: {}
[email protected]59: {}
[email protected]: {}
@@ -12418,9 +12401,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
[email protected](@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected]):
[email protected](@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected]):
dependencies:
'@typescript-eslint/types': 8.72.1
'@typescript-eslint/types': 8.72.0
comment-parser: 1.4.8
debug: 4.4.3([email protected])
eslint: 10.13.0([email protected])
@@ -12431,7 +12414,7 @@ snapshots:
stable-hash-x: 0.2.0
unrs-resolver: 1.12.2
optionalDependencies:
'@typescript-eslint/utils': 8.72.1([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/utils': 8.72.0([email protected]([email protected]))([email protected])([email protected])
transitivePeerDependencies:
- supports-color
@@ -12455,11 +12438,11 @@ snapshots:
parse5: 8.0.1
parse5-htmlparser2-tree-adapter: 8.0.1
[email protected](@typescript-eslint/[email protected].1(@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])):
[email protected](@typescript-eslint/[email protected].0(@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])):
dependencies:
eslint: 10.13.0([email protected])
optionalDependencies:
'@typescript-eslint/eslint-plugin': 8.72.1(@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/eslint-plugin': 8.72.0(@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])
[email protected]([email protected]([email protected])):
dependencies:
@@ -12869,12 +12852,6 @@ snapshots:
minipass: 7.1.3
path-scurry: 2.0.2
[email protected]:
dependencies:
minimatch: 11.0.2
minipass: 7.1.3
path-scurry: 3.0.0
[email protected]:
dependencies:
global-prefix: 1.0.2
@@ -12985,7 +12962,7 @@ snapshots:
[email protected]: {}
[email protected].1: {}
[email protected].0: {}
[email protected]:
dependencies:
@@ -13712,7 +13689,7 @@ snapshots:
[email protected]: {}
[email protected].2: {}
[email protected].1: {}
[email protected]: {}
@@ -13761,12 +13738,7 @@ snapshots:
[email protected]:
dependencies:
brace-expansion: 5.0.12
[email protected]:
dependencies:
'@isaacs/nonrecursive-glob-match': 1.0.2
brace-expansion: 5.0.12
brace-expansion: 5.0.9
[email protected]:
dependencies:
@@ -13896,7 +13868,7 @@ snapshots:
undici: 8.12.1
which: 7.0.0
[email protected].60: {}
[email protected].59: {}
[email protected]:
dependencies:
@@ -14243,11 +14215,6 @@ snapshots:
lru-cache: 11.5.3
minipass: 7.1.3
[email protected]:
dependencies:
lru-cache: 11.5.3
minipass: 7.1.3
[email protected]: {}
[email protected]:
@@ -15243,12 +15210,12 @@ snapshots:
possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10
[email protected].1([email protected]([email protected]))([email protected])([email protected]):
[email protected].0([email protected]([email protected]))([email protected])([email protected]):
dependencies:
'@typescript-eslint/eslint-plugin': 8.72.1(@typescript-eslint/[email protected].1([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/parser': 8.72.1([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/typescript-estree': 8.72.1([email protected])([email protected])
'@typescript-eslint/utils': 8.72.1([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/eslint-plugin': 8.72.0(@typescript-eslint/[email protected].0([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/parser': 8.72.0([email protected]([email protected]))([email protected])([email protected])
'@typescript-eslint/typescript-estree': 8.72.0([email protected])([email protected])
'@typescript-eslint/utils': 8.72.0([email protected]([email protected]))([email protected])([email protected])
eslint: 10.13.0([email protected])
typescript: 6.0.3
transitivePeerDependencies:
@@ -15359,9 +15326,9 @@ snapshots:
[email protected]: {}
[email protected]([email protected].5):
[email protected]([email protected].4):
dependencies:
browserslist: 4.29.5
browserslist: 4.29.4
escalade: 3.2.0
picocolors: 1.1.1
+12 -10
View File
@@ -4,8 +4,8 @@ import { consumeLocalize } from "../common/decorators/consume-context-entry";
import { fireEvent } from "../common/dom/fire_event";
import type { LocalizeFunc } from "../common/translations/localize";
import "../components/ha-icon-next";
import "../components/item/ha-list-item-button";
import "../components/list/ha-list-base";
import "../components/ha-list";
import "../components/ha-list-item";
import type { AuthProvider } from "../data/auth";
declare global {
@@ -32,19 +32,21 @@ export class HaPickAuthProvider extends LitElement {
>${this._localize("ui.panel.page-authorize.pick_auth_provider")}</span
>
</h3>
<ha-list-base>
<ha-list>
${this.authProviders.map(
(provider) => html`
<ha-list-item-button
<ha-list-item
hasMeta
role="button"
.auth_provider=${provider}
@click=${this._handlePick}
>
<span slot="headline">${provider.name}</span>
<ha-icon-next slot="end"></ha-icon-next>
</ha-list-item-button>
${provider.name}
<ha-icon-next slot="meta"></ha-icon-next>
</ha-list-item>
`
)}
</ha-list-base>
</ha-list>
`;
}
@@ -78,9 +80,9 @@ export class HaPickAuthProvider extends LitElement {
background: var(--card-background-color);
padding: 0 15px;
}
ha-list-base {
ha-list {
margin: 16px -16px 0;
--ha-row-item-padding-inline: 24px;
--mdc-list-side-padding: 24px;
}
`;
}
+1 -1
View File
@@ -28,7 +28,7 @@ const RASTER_TILE_URL = `${MAP_TILES_PATH}/raster/{z}/{x}/{y}.png?token={token}`
// policy strips again unless the tiles ask for it back.
const DEMO_RASTER_TILE_URL = "https://tile.openstreetmap.org/{z}/{x}/{y}.png";
const OSM_ATTRIBUTION =
'<a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>';
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
// Browsers keep about 16 live WebGL contexts and drop the oldest, which a
// dashboard full of map cards hits. A transient loss is restored, hence a grace.
+6 -15
View File
@@ -89,8 +89,6 @@ export const DEFAULT_CHART_WIDTH = 500;
// is short enough for a whole screenful; on a desktop that would cover the page.
const VISIBILITY_ROOT_MARGIN_NARROW = "100%";
const VISIBILITY_ROOT_MARGIN = "300px";
export type ZoomSliderMode = "auto" | "always" | "never";
const DEFERRED_PROPS = [
"options",
"data",
@@ -165,10 +163,9 @@ export class HaChartBase extends MobileAwareMixin(LitElement) {
@property({ attribute: "small-controls", type: Boolean })
public smallControls?: boolean;
// "auto" shows the zoom slider once zoomed. "never" hides every zoom
// control, for charts zoomed from outside like the synced History charts.
@property({ attribute: "zoom-slider" })
public zoomSlider: ZoomSliderMode = "auto";
// For charts zoomed from outside, like the synced History charts
@property({ attribute: "hide-zoom-controls", type: Boolean })
public hideZoomControls = false;
// For charts sized to their content, like timelines, which grow to fit the
// zoom slider instead of giving up plot height
@@ -620,7 +617,7 @@ export class HaChartBase extends MobileAwareMixin(LitElement) {
>
${
(this._isZoomed || this._isGraphRoamed) &&
this.zoomSlider !== "never" &&
!this.hideZoomControls &&
!showZoomSlider
? html`<ha-icon-button
class="zoom-reset"
@@ -1067,12 +1064,9 @@ export class HaChartBase extends MobileAwareMixin(LitElement) {
private _showZoomSlider() {
const [start, end] = this._zoomRange;
return (
this.zoomSlider !== "never" &&
!this.hideZoomControls &&
this._hasZoomableXAxis() &&
(this.zoomSlider === "always" ||
this._zoomSliderHeld ||
start !== 0 ||
end !== 100)
(this._zoomSliderHeld || start !== 0 || end !== 100)
);
}
@@ -2312,9 +2306,6 @@ export class HaChartBase extends MobileAwareMixin(LitElement) {
--ha-assist-chip-trailing-space: var(--ha-space-2);
--ha-assist-chip-icon-label-space: var(--ha-space-1);
}
.zoom-reset {
margin-inline-end: var(--ha-space-3);
}
`;
}
+1 -1
View File
@@ -648,7 +648,7 @@ export class HaNetworkGraph extends LitElement {
ha-icon-button,
::slotted(ha-icon-button) {
margin-inline-end: var(--ha-space-3);
margin-right: 12px;
}
`;
}
@@ -24,7 +24,6 @@ import type {
HomeAssistantInternationalization,
} from "../../types";
import { MIN_TIME_BETWEEN_UPDATES } from "./ha-chart-base";
import type { ZoomSliderMode } from "./ha-chart-base";
import { sideTooltipPosition } from "./chart-tooltip-position";
import "./ha-chart-tooltip-marker";
import {
@@ -106,8 +105,8 @@ export class StateHistoryChartLine extends LitElement {
@property({ attribute: "expand-legend", type: Boolean })
public expandLegend?: boolean;
@property({ attribute: "zoom-slider" })
public zoomSlider: ZoomSliderMode = "auto";
@property({ attribute: "hide-zoom-controls", type: Boolean })
public hideZoomControls = false;
@state() private _chartData: LineSeriesOption[] = [];
@@ -160,7 +159,7 @@ export class StateHistoryChartLine extends LitElement {
@dataset-unhidden=${this._datasetUnhidden}
@chart-zoom=${this._handleDataZoom}
.expandLegend=${this.expandLegend}
.zoomSlider=${this.zoomSlider}
.hideZoomControls=${this.hideZoomControls}
.clickLabelForMoreInfo=${this.clickForMoreInfo}
@legend-label-click=${this._handleLegendLabelClick}
></ha-chart-base>
@@ -22,7 +22,6 @@ import type {
HomeAssistantInternationalization,
} from "../../types";
import { DEFAULT_CHART_WIDTH, MIN_TIME_BETWEEN_UPDATES } from "./ha-chart-base";
import type { ZoomSliderMode } from "./ha-chart-base";
import { itemTooltipPosition } from "./chart-tooltip-position";
import "./ha-chart-tooltip-marker";
import type { HaECOption, HaECSeries } from "../../resources/echarts/echarts";
@@ -69,8 +68,8 @@ export class StateHistoryChartTimeline extends LitElement {
@property({ attribute: false }) public chartIndex?;
@property({ attribute: "zoom-slider" })
public zoomSlider: ZoomSliderMode = "auto";
@property({ attribute: "hide-zoom-controls", type: Boolean })
public hideZoomControls = false;
@state() private _chartData: CustomSeriesOption[] = [];
@@ -106,7 +105,7 @@ export class StateHistoryChartTimeline extends LitElement {
grow-for-zoom-slider
@chart-click=${this._handleChartClick}
@chart-zoom=${this._handleDataZoom}
.zoomSlider=${this.zoomSlider}
.hideZoomControls=${this.hideZoomControls}
></ha-chart-base>
`;
}
+2 -2
View File
@@ -218,7 +218,7 @@ export class StateHistoryCharts extends LitElement {
@chart-zoom-with-index=${this._handleTimelineSync}
.height=${this.virtualize ? undefined : this.height}
.expandLegend=${this.expandLegend}
.zoomSlider=${this.syncCharts ? "never" : "auto"}
?hide-zoom-controls=${this.syncCharts}
></state-history-chart-line>
</div> `;
}
@@ -237,7 +237,7 @@ export class StateHistoryCharts extends LitElement {
.clickForMoreInfo=${this.clickForMoreInfo}
@y-width-changed=${this._yWidthChanged}
@chart-zoom-with-index=${this._handleTimelineSync}
.zoomSlider=${this.syncCharts ? "never" : "auto"}
?hide-zoom-controls=${this.syncCharts}
></state-history-chart-timeline>
</div> `;
};
+12 -21
View File
@@ -1,5 +1,6 @@
import { TZDate } from "@date-fns/tz";
import type { ContextType } from "@lit/context";
import type { ActionDetail } from "@material/mwc-list";
import { mdiCalendarToday } from "@mdi/js";
import "cally";
import type { HassConfig } from "home-assistant-js-websocket/dist/types";
@@ -16,7 +17,6 @@ import {
import { transform } from "../../common/decorators/transform";
import { fireEvent } from "../../common/dom/fire_event";
import type {
HASSDomCurrentTargetEvent,
HASSDomEvent,
HASSDomTargetEvent,
} from "../../common/dom/fire_event";
@@ -32,8 +32,8 @@ import type { HaBaseTimeInput } from "../ha-base-time-input";
import "../ha-icon-button";
import "../ha-icon-button-next";
import "../ha-icon-button-prev";
import "../item/ha-list-item-button";
import "../list/ha-list-base";
import "../ha-list";
import "../ha-list-item";
import "../ha-time-input";
import type { HaTimeInput } from "../ha-time-input";
import type { DateRangePickerRanges } from "./ha-date-range-picker";
@@ -166,19 +166,11 @@ export class DateRangePicker extends MobileAwareMixin(LitElement) {
}
return html`
<ha-list-base>
${Object.entries(this.ranges!).map(
([name, range], index) => html`
<ha-list-item-button
.range=${range}
.index=${index}
@click=${this._setDateRange}
>
<span slot="headline">${name}</span>
</ha-list-item-button>
`
<ha-list @action=${this._setDateRange} activatable>
${Object.keys(this.ranges!).map(
(name) => html`<ha-list-item>${name}</ha-list-item>`
)}
</ha-list-base>
</ha-list>
`;
}
@@ -351,12 +343,11 @@ export class DateRangePicker extends MobileAwareMixin(LitElement) {
this._saveDateRangePreset(chip.range, chip.index);
}
private _setDateRange(
ev: HASSDomCurrentTargetEvent<
HTMLElement & { range: [Date, Date]; index: number }
>
) {
this._saveDateRangePreset(ev.currentTarget.range, ev.currentTarget.index);
private _setDateRange(ev: HASSDomEvent<ActionDetail>) {
const dateRange: [Date, Date] = Object.values(this.ranges!)[
ev.detail.index
];
this._saveDateRangePreset(dateRange, ev.detail.index);
}
private _saveDateRangePreset(range: [Date, Date], index: number) {
+21 -78
View File
@@ -15,7 +15,6 @@ import { repeat } from "lit/directives/repeat";
import memoizeOne from "memoize-one";
import { tinykeys } from "tinykeys";
import { findSectionTitle } from "./list/find-section-title";
import { searchResultsStatus } from "./list/search-results-status";
import { consume } from "../common/decorators/consume";
import {
fireEvent,
@@ -24,7 +23,6 @@ import {
} from "../common/dom/fire_event";
import { ignoreRepeatedActivation } from "../common/keyboard/ignore-repeated-activation";
import { caseInsensitiveStringCompare } from "../common/string/compare";
import { debounce } from "../common/util/debounce";
import { internationalizationContext } from "../data/context";
import { ScrollableFadeMixin } from "../mixins/scrollable-fade-mixin";
import {
@@ -166,10 +164,6 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
@property({ attribute: false })
public notFoundLabel?: string | ((search: string) => string);
/** Whether a row from `getItems` counts as a search result for screen readers, so a row offered for any search, like the quick bar's "Ask Assist", can be left out */
@property({ attribute: false })
public isSearchResult?: (item: PickerComboBoxItem) => boolean;
@property({ attribute: "empty-label" })
public emptyLabel?: string;
@@ -230,18 +224,12 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
@state() private _sectionTitle?: string;
@state() private _status?: string;
private _allItems: PickerComboBoxItem[] = [];
// Rows from this index on are added by the combo box itself, like "Add custom
// item", and belong to no section.
private _sectionedItemsCount = 0;
// Rows the combo box offers for any search, like "Add custom item" and the
// additional items, are not search results.
private _actionItems = new WeakSet<PickerComboBoxItem>();
// The virtualized list renders its scroller a moment after it connects, so
// the scroll fades attach once it reports its first visible rows.
private _virtualScrollElement?: HTMLElement;
@@ -263,18 +251,13 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
}
}
public willUpdate(changedProps: PropertyValues) {
public willUpdate() {
if (!this.hasUpdated) {
this._selectedSection = this.selectedSection;
this._allItems = this._getItems();
this._items = this._allItems;
this._updateListMode();
}
// New rows make the last message out of date, so clear it at once. The new
// one is then read out even when its text is the same as before.
if (changedProps.has("_items")) {
this._status = undefined;
}
}
protected updated(changedProps: PropertyValues) {
@@ -284,13 +267,6 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
if (changedProps.has("_items") && this._search) {
this._highlightTopMatch();
}
if (changedProps.has("_items")) {
if (this._search) {
this._updateStatus();
} else {
this._updateStatus.cancel();
}
}
}
// Scroll before the surface animates in, so the list does not jump at the
@@ -327,8 +303,6 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
disconnectedCallback() {
super.disconnectedCallback();
this._removeKeyboardShortcuts?.();
this._updateStatus.cancel();
this._status = undefined;
}
public refreshItems() {
@@ -388,28 +362,9 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
>
${this._plainList ? this._renderPlainList() : this._renderVirtualList()}
${this.renderScrollableFades()}
</div>
<div class="visually-hidden" role="status">
${this._status ?? nothing}
</div>`;
}
// DOM focus stays in the search field, so screen readers hear nothing when
// the list changes. Announce how many items match instead, once typing
// pauses, so the count doesn't compete with each typed character.
private _updateStatus = debounce(() => {
this._status = searchResultsStatus(
this._search,
this._items,
(item) =>
this._isOption(item) &&
!this._actionItems.has(item) &&
(this.isSearchResult?.(item) ?? true),
this.i18n?.localize,
this.notFoundLabel
);
}, 500);
private _renderPlainList() {
return html`
<ha-list-selectable
@@ -499,25 +454,8 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
}
}
private _getAdditionalItems = (searchString?: string) => {
const items = this.getAdditionalItems?.(searchString) || [];
items.forEach((item) => this._actionItems.add(item));
return items;
};
private _getCustomValueItem(search: string): PickerComboBoxItem {
const item = {
id: search,
primary:
this.customValueLabel ??
this.i18n?.localize?.("ui.components.combo-box.add_custom_item") ??
"Add custom item",
secondary: `"${search}"`,
icon_path: mdiPlus,
};
this._actionItems.add(item);
return item;
}
private _getAdditionalItems = (searchString?: string) =>
this.getAdditionalItems?.(searchString) || [];
private _getItems = () => {
let items = [...(this.getItems(this._search, this._selectedSection) || [])];
@@ -559,7 +497,15 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
items.push(...additionalItems);
if (this.allowCustomValue && this._search) {
items.push(this._getCustomValueItem(this._search));
items.push({
id: this._search,
primary:
this.customValueLabel ??
this.i18n?.localize?.("ui.components.combo-box.add_custom_item") ??
"Add custom item",
secondary: `"${this._search}"`,
icon_path: mdiPlus,
});
}
if (this.mode === "dialog") {
@@ -720,7 +666,15 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
}
if (this.allowCustomValue && searchString) {
filteredItems.push(this._getCustomValueItem(searchString));
filteredItems.push({
id: searchString,
primary:
this.customValueLabel ??
this.i18n?.localize?.("ui.components.combo-box.add_custom_item") ??
"Add custom item",
secondary: `"${searchString}"`,
icon_path: mdiPlus,
});
}
this._items = filteredItems;
@@ -1064,17 +1018,6 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
align-items: center;
padding: var(--ha-space-3);
}
.visually-hidden {
position: absolute;
overflow: hidden;
clip: rect(0 0 0 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
}
`,
];
}
+52
View File
@@ -0,0 +1,52 @@
import { css } from "lit";
import { RadioListItemBase } from "@material/mwc-list/mwc-radio-list-item-base";
import { styles as controlStyles } from "@material/mwc-list/mwc-control-list-item.css";
import { styles } from "@material/mwc-list/mwc-list-item.css";
import { customElement } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
@customElement("ha-radio-list-item")
export class HaRadioListItem extends RadioListItemBase {
async onChange(event) {
super.onChange(event);
fireEvent(this, event.type);
}
static override styles = [
styles,
controlStyles,
css`
:host {
--mdc-theme-secondary: var(--primary-color);
}
:host([graphic="avatar"]) .mdc-deprecated-list-item__graphic,
:host([graphic="medium"]) .mdc-deprecated-list-item__graphic,
:host([graphic="large"]) .mdc-deprecated-list-item__graphic,
:host([graphic="control"]) .mdc-deprecated-list-item__graphic {
margin-inline-end: var(--mdc-list-item-graphic-margin, 16px);
margin-inline-start: 0px;
direction: var(--direction);
}
.mdc-deprecated-list-item__meta {
flex-shrink: 0;
direction: var(--direction);
margin-inline-start: auto;
margin-inline-end: 0;
}
.mdc-deprecated-list-item__graphic {
margin-top: var(--radio-list-item-graphic-margin-top);
}
:host([graphic="icon"]) .mdc-deprecated-list-item__graphic {
margin-inline-start: 0;
margin-inline-end: var(--mdc-list-item-graphic-margin, 32px);
}
`,
];
}
declare global {
interface HTMLElementTagNameMap {
"ha-radio-list-item": HaRadioListItem;
}
}
@@ -1,37 +0,0 @@
import type { LocalizeFunc } from "../../common/translations/localize";
/**
* The screen reader message for a list search: how many items match, or that
* nothing does. A live region is only read out when its text changes, so the
* message names the search.
*
* Returns undefined when there is no search.
* @param search - The search text
* @param items - The list rows, with section titles as strings
* @param isResult - Whether a row is a result, so placeholder rows and rows
* offered for any search, like "Add custom item", are not counted
* @param localize - The localize function
* @param notFoundLabel - The not found label; one that takes the search is
* used when nothing matches, as it names the search already
*/
export const searchResultsStatus = <T>(
search: string,
items: readonly (T | string)[],
isResult: (item: T) => boolean,
localize?: LocalizeFunc,
notFoundLabel?: string | ((search: string) => string)
): string | undefined => {
if (!search) {
return undefined;
}
const count = items.filter(
(item): item is T => typeof item !== "string" && isResult(item)
).length;
const term = `‘${search}’`;
if (!count) {
return typeof notFoundLabel === "function"
? notFoundLabel(search)
: localize?.("ui.components.combo-box.no_results", { term });
}
return localize?.("ui.components.combo-box.result_count", { count, term });
};
-5
View File
@@ -282,7 +282,6 @@ export class QuickBar extends LitElement {
)}
.label=${this.hass.localize("ui.dialogs.quick-bar.title")}
.getItems=${this._getItems}
.isSearchResult=${this._isSearchResult}
.rowRenderer=${this._getRowRenderer(this._runningCommandId)}
mode="dialog"
.sections=${sections}
@@ -447,10 +446,6 @@ export class QuickBar extends LitElement {
// #region data
// "Ask Assist" is offered for any search, so it isn't a search result.
private _isSearchResult = (item: PickerComboBoxItem) =>
!("assistPrompt" in item);
private _getItems = (searchString: string, section: string) => {
this._selectedSection = section as QuickBarSection | undefined;
return this._getItemsMemoized(
+1 -7
View File
@@ -180,13 +180,6 @@ export class HomeAssistantMain extends LitElement {
color: var(--primary-text-color);
/* remove the grey tap highlights in iOS on the fullscreen touch targets */
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
/* Keep the negative z-index panel backgrounds (the resolver's ::before
and the Lovelace view background) in this host's stacking context.
Isolating the conditionally rendered partial-panel-resolver instead
can intermittently leave the Android WebView (Chromium 109-124)
accessibility tree with an empty panel subtree while the page paints
normally, which breaks UI automation such as the companion app E2E. */
isolation: isolate;
--ha-sidebar-width: calc(56px + var(--safe-area-inset-left, 0px));
--ha-top-app-bar-width: calc(100% - var(--ha-sidebar-width));
--safe-area-content-inset-left: 0px;
@@ -208,6 +201,7 @@ export class HomeAssistantMain extends LitElement {
partial-panel-resolver {
display: block;
height: 100%;
isolation: isolate;
}
partial-panel-resolver::before {
content: "";
@@ -292,8 +292,8 @@ export class HaConfigAppsInstalled extends LitElement {
}
.content {
padding: var(--ha-space-6) var(--ha-space-4) var(--ha-space-4);
margin: 0 0 var(--ha-space-18);
padding: var(--ha-space-4);
margin-bottom: var(--ha-space-18);
gap: var(--ha-space-4);
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(336px, 100%), 1fr));
@@ -347,22 +347,11 @@ export class HaBackupOverviewProgress extends LitElement {
: nothing
}
</div>
<span class="segment-label" title=${segment.label}
>${segment.label}</span
>
<span class="segment-label">${segment.label}</span>
</div>
`
)}
</div>
${
this.manager.stage
? html`<span class="stage-label"
>${this.hass.localize(
`ui.panel.config.backup.overview.progress.description.create_backup.${this.manager.stage}`
)}</span
>`
: nothing
}
`;
}
@@ -483,7 +472,6 @@ export class HaBackupOverviewProgress extends LitElement {
css`
.progress-content {
padding: var(--ha-space-2) var(--ha-space-4) var(--ha-space-4);
container-type: inline-size;
}
.segmented-progress {
display: flex;
@@ -529,21 +517,6 @@ export class HaBackupOverviewProgress extends LitElement {
overflow: hidden;
text-overflow: ellipsis;
}
.stage-label {
display: none;
margin-top: var(--ha-space-1);
font-size: var(--ha-font-size-xs);
color: var(--secondary-text-color);
}
/* Segment labels don't fit a narrow bar, name the current stage instead */
@container (max-width: 479px) {
.segment-label {
display: none;
}
.stage-label {
display: block;
}
}
@keyframes pulse {
0%,
100% {
@@ -357,19 +357,13 @@ class HaBackupOverviewBackups extends LitElement {
justify-content: flex-end;
border-top: none;
}
ha-list-base {
--ha-list-padding: 0 0 var(--ha-space-2);
}
ha-list-item-base {
--ha-row-item-padding-block: var(--ha-space-2);
--ha-row-item-min-height: 40px;
--ha-row-item-min-height: 40x;
}
ha-list-item-base::part(start) {
color: var(--ha-color-text-secondary);
}
ha-list-item-base::part(headline) {
white-space: wrap;
}
span.skeleton {
position: relative;
display: block;
@@ -5,20 +5,26 @@ import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { dynamicElement } from "../../../common/dom/dynamic-element-directive";
import type { HASSDomTargetEvent } from "../../../common/dom/fire_event";
import type {
HASSDomCurrentTargetEvent,
HASSDomEvent,
HASSDomTargetEvent,
} from "../../../common/dom/fire_event";
import { fireEvent } from "../../../common/dom/fire_event";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { stringCompare } from "../../../common/string/compare";
import "../../../components/ha-button";
import "../../../components/ha-dialog";
import "../../../components/ha-dialog-footer";
import "../../../components/ha-list";
import "../../../components/ha-list-item";
import "../../../components/ha-spinner";
import "../../../components/ha-svg-icon";
import "../../../components/ha-tooltip";
import "../../../components/input/ha-input-search";
import type { HaInputSearch } from "../../../components/input/ha-input-search";
import "../../../components/item/ha-list-item-option";
import type { HaListItemOption } from "../../../components/item/ha-list-item-option";
import "../../../components/list/ha-list-selectable";
import type { HaListSelectable } from "../../../components/list/ha-list-selectable";
import { DirtyStateProviderMixin } from "../../../mixins/dirty-state-provider-mixin";
import { getConfigFlowHandlers } from "../../../data/config_flow";
import { createCounter } from "../../../data/counter";
@@ -244,14 +250,13 @@ export class DialogHelperDetail extends DirtyStateProviderMixin<
"ui.panel.config.integrations.search_helper"
)}
></ha-input-search>
<ha-list
<ha-list-selectable
class="ha-scrollbar"
innerRole="listbox"
itemRoles="option"
innerAriaLabel=${this.hass.localize(
controlled
aria-label=${this.hass.localize(
"ui.panel.config.helpers.dialog.create_helper"
)}
rootTabbable
@ha-list-item-selected=${this._domainPicked}
>
${items.map(([domain, label]) => {
// Only OG helpers need to be loaded prior adding one
@@ -259,14 +264,9 @@ export class DialogHelperDetail extends DirtyStateProviderMixin<
!(domain in HELPERS) ||
isComponentLoaded(this.hass.config, domain);
return html`
<ha-list-item
hasmeta
.domain=${domain}
@request-selected=${this._domainPicked}
graphic="icon"
>
<ha-list-item-option appearance="line" .value=${domain}>
<img
slot="graphic"
slot="start"
loading="lazy"
alt=""
src=${brandsUrl(
@@ -280,12 +280,12 @@ export class DialogHelperDetail extends DirtyStateProviderMixin<
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<span class="item-text"> ${label} </span>
<span slot="headline" class="item-text">${label}</span>
${
isLoaded
? html`<ha-icon-next slot="meta"></ha-icon-next>`
? html`<ha-icon-next slot="end"></ha-icon-next>`
: html`<ha-svg-icon
slot="meta"
slot="end"
.id="icon-${domain}"
path=${mdiAlertOutline}
@click=${stopPropagation}
@@ -297,10 +297,10 @@ export class DialogHelperDetail extends DirtyStateProviderMixin<
)}
</ha-tooltip>`
}
</ha-list-item>
</ha-list-item-option>
`;
})}
</ha-list>
</ha-list-selectable>
`;
}
@@ -409,8 +409,15 @@ export class DialogHelperDetail extends DirtyStateProviderMixin<
}
}
private async _domainPicked(ev): Promise<void> {
const domain = ev.target.closest("ha-list-item").domain;
private async _domainPicked(
ev: HASSDomEvent<number> & HASSDomCurrentTargetEvent<HaListSelectable>
): Promise<void> {
const domain = (
ev.currentTarget.items[ev.detail] as HaListItemOption | undefined
)?.value;
if (!domain) {
return;
}
const isLoaded =
!(domain in HELPERS) || isComponentLoaded(this.hass.config, domain);
if (!isLoaded) {
@@ -472,6 +479,11 @@ export class DialogHelperDetail extends DirtyStateProviderMixin<
ha-icon-next {
width: var(--ha-space-6);
}
ha-list-item-option img {
width: 24px;
height: 24px;
object-fit: contain;
}
ha-tooltip {
pointer-events: auto;
}
@@ -481,11 +493,11 @@ export class DialogHelperDetail extends DirtyStateProviderMixin<
ha-input-search {
margin: 0 var(--ha-space-4) var(--ha-space-3);
}
ha-list {
ha-list-selectable::part(base) {
height: calc(60vh - 184px);
}
@media all and (max-width: 450px), all and (max-height: 500px) {
ha-list {
ha-list-selectable::part(base) {
height: calc(
100vh -
184px - var(--safe-area-inset-top, 0px) - var(
@@ -101,8 +101,6 @@ export class DialogYamlIntegration extends LitElement {
ha-dialog {
/* Place above other dialogs */
--dialog-z-index: 104;
--ha-dialog-header-white-space: normal;
--ha-dialog-header-title-height: auto;
}
`;
}
+16 -16
View File
@@ -5,10 +5,9 @@ import { customElement, property, state } from "lit/decorators";
import { stringCompare } from "../../../common/string/compare";
import "../../../components/ha-button";
import "../../../components/ha-card";
import "../../../components/ha-list";
import "../../../components/ha-list-item";
import "../../../components/ha-svg-icon";
import "../../../components/item/ha-list-item-base";
import "../../../components/item/ha-list-item-button";
import "../../../components/list/ha-list-base";
import "../../../components/user/ha-person-badge";
import type { Person } from "../../../data/person";
import {
@@ -93,22 +92,23 @@ export class HaConfigPerson extends LitElement {
</span>
<ha-card outlined class="storage">
<ha-list-base>
<ha-list>
${this._storageItems.map(
(entry) => html`
<ha-list-item-button
<ha-list-item
graphic="avatar"
@click=${this._openEditEntry}
.entry=${entry}
>
<ha-person-badge
.person=${entry}
slot="start"
slot="graphic"
></ha-person-badge>
<span slot="headline">${entry.name}</span>
</ha-list-item-button>
<span>${entry.name}</span>
</ha-list-item>
`
)}
</ha-list-base>
</ha-list>
${
this._storageItems.length === 0
? html`
@@ -138,19 +138,19 @@ export class HaConfigPerson extends LitElement {
this._configItems.length > 0
? html`
<ha-card outlined header="Configuration.yaml persons">
<ha-list-base>
<ha-list>
${this._configItems.map(
(entry) => html`
<ha-list-item-base>
<ha-list-item graphic="avatar">
<ha-person-badge
.person=${entry}
slot="start"
slot="graphic"
></ha-person-badge>
<span slot="headline">${entry.name}</span>
</ha-list-item-base>
<span>${entry.name}</span>
</ha-list-item>
`
)}
</ha-list-base>
</ha-list>
</ha-card>
`
: nothing
@@ -299,7 +299,7 @@ export class HaConfigPerson extends LitElement {
align-items: center;
justify-content: space-around;
}
ha-list-base:has(+ .empty) {
ha-list:has(+ .empty) {
display: none;
}
`;
@@ -73,10 +73,6 @@ const mountPartitionLabel = ({
return drive ? `${drive} — ${identity}, ${size}` : `${identity}, ${size}`;
};
// Supervisor accepts only ASCII letters, digits and underscores.
const mountNameFromLabel = (label?: string): string =>
(label ?? "").replace(/^\W+|\W+$/g, "").replace(/\W+/g, "_");
const requiredFieldsFilled = (
schema: readonly HaFormSchema[],
data?: MountFormData
@@ -309,8 +305,6 @@ class ViewMountDialog extends DirtyStateProviderMixin<
private _originalType?: SupervisorMountType;
private _suggestedName?: string;
@state() private _diskIdentity?: string;
public connectedCallback(): void {
@@ -535,9 +529,7 @@ class ViewMountDialog extends DirtyStateProviderMixin<
private _valueChanged(ev: CustomEvent) {
this._validationError = {};
this._validationWarning = {};
const previous = this._data;
this._data = ev.detail.value;
this._suggestName(previous);
if (this._data?.name && !/^\w+$/.test(this._data.name)) {
this._validationError.name = "invalid_name";
}
@@ -564,32 +556,6 @@ class ViewMountDialog extends DirtyStateProviderMixin<
);
}
// Name a new disk mount after the partition's volume label, unless the user
// typed a name of their own.
private _suggestName(previous?: MountFormData) {
const data = this._data;
if (data?.name !== previous?.name) {
this._suggestedName = undefined;
}
if (
this._existing ||
data?.type !== SupervisorMountType.DISK ||
(data.device === previous?.device &&
previous?.type === SupervisorMountType.DISK) ||
(data.name && data.name !== this._suggestedName)
) {
return;
}
const name = mountNameFromLabel(
this._partitions?.find((entry) => entry.partition.device === data.device)
?.partition.label
);
if (name !== (data.name ?? "")) {
data.name = name;
}
this._suggestedName = name;
}
private async _connectMount(ev) {
const progressButton = ev.target as HaProgressButton;
this._error = undefined;
@@ -28,7 +28,7 @@ import type { ContextType } from "@lit/context";
import type { HassConfig } from "home-assistant-js-websocket";
import type { PropertyValues } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import {
@@ -78,6 +78,7 @@ import type {
HomeAssistantConfig,
HomeAssistantInternationalization,
} from "../../../types";
import { animationStyles } from "../../../resources/theme/animations.globals";
const RANGE_KEYS: DateRange[] = [
"today",
@@ -150,10 +151,6 @@ export class HuiEnergyPeriodSelector extends LitElement {
@state() private _loading = false;
@state() private _loadingLeaving = false;
@query(".loading-indicator") private _loadingIndicator?: HTMLElement;
private _loadingTimer?: ReturnType<typeof setTimeout>;
private _resizeObserver?: ResizeObserver;
@@ -382,15 +379,10 @@ export class HuiEnergyPeriodSelector extends LitElement {
: nothing
}
${
this._loading || this._loadingLeaving
this._loading
? html`<ha-spinner
class=${classMap({
"loading-indicator": true,
leaving: this._loadingLeaving,
})}
class="loading-indicator"
size="small"
@transitionend=${this._loadingTransitionDone}
@transitioncancel=${this._loadingTransitionDone}
></ha-spinner>`
: nothing
}
@@ -735,10 +727,6 @@ export class HuiEnergyPeriodSelector extends LitElement {
private _updateDates(energyData: EnergyData): void {
clearTimeout(this._loadingTimer);
if (this._loading) {
this._loadingLeaving = true;
this._removeLoadingIndicatorWithoutTransition();
}
this._loading = false;
this._compare = energyData.startCompare !== undefined;
this._startDate = energyData.start;
@@ -771,30 +759,10 @@ export class HuiEnergyPeriodSelector extends LitElement {
// Basically to ensure there's no "flash loading" when data is loaded quickly
clearTimeout(this._loadingTimer);
this._loadingTimer = setTimeout(() => {
this._loadingLeaving = false;
this._loading = true;
}, 200);
}
private async _removeLoadingIndicatorWithoutTransition() {
await this.updateComplete;
// No transition starts when the spinner was still at opacity 0
this._removeIdleLoadingIndicator();
}
private _loadingTransitionDone(ev: TransitionEvent) {
if (ev.propertyName === "opacity") {
this._removeIdleLoadingIndicator();
}
}
private _removeIdleLoadingIndicator() {
// Reversing the fade-in cancels a transition while the fade-out runs
if (!this._loadingIndicator?.getAnimations().length) {
this._loadingLeaving = false;
}
}
private _getDatePickerPlacement = memoizeOne(
(
verticalOpeningDirection: VerticalOpeningDirection | undefined,
@@ -810,6 +778,7 @@ export class HuiEnergyPeriodSelector extends LitElement {
);
static styles = css`
${animationStyles}
:host {
display: block;
}
@@ -874,15 +843,7 @@ export class HuiEnergyPeriodSelector extends LitElement {
position: absolute;
right: var(--ha-space-2);
align-items: center;
transition: opacity var(--ha-animation-duration-normal) ease-in-out;
}
@starting-style {
.loading-indicator {
opacity: 0;
}
}
.loading-indicator.leaving {
opacity: 0;
animation: fade-in var(--ha-animation-duration-normal) ease-in-out;
}
.date-actions .overflow {
display: flex;
@@ -1,10 +0,0 @@
// Install the Intl.PluralRules polyfill together with its locale data.
// FormatJS replaces Intl.PluralRules as soon as polyfill-force runs, and a
// data-less polyfill throws from select(). Keeping both imports in one module
// closes that gap for every caller, including the should-polyfill probes
// that other entry bundles run.
import "@formatjs/intl-pluralrules/polyfill-force";
// Locale data for plural rules breaks current JSON conversions as it includes functions,
// so only import English to avoid huge bundles
// TODO: Setup JS imports instead of JSON fetches
import "@formatjs/intl-pluralrules/locale-data/en";
+15 -10
View File
@@ -14,6 +14,8 @@ import {
polyfillTimeZoneData,
} from "./locale-data-polyfill";
let polyfilled = false;
const _polyfillTimeZoneData = polyfillTimeZoneData;
// The DateTimeFormat and DurationFormat polyfills call BigInt() when formatting
@@ -45,6 +47,10 @@ const setDefaultTimeZone = () => {
};
const polyfillIntl = async () => {
if (polyfilled) {
return;
}
polyfilled = true;
const locale = getLocalLanguage();
const polyfills: Promise<unknown>[] = [];
if (shouldPolyfillGetCanonicalLocales()) {
@@ -73,10 +79,14 @@ const polyfillIntl = async () => {
polyfills.push(import("@formatjs/intl-numberformat/polyfill-force"));
}
if (shouldPolyfillPluralRules(locale)) {
// The polyfill and its English data are one chunk, so Intl.PluralRules
// is never installed without data. Its should-polyfill probe calls
// select(), which throws on a data-less polyfill.
polyfills.push(import("./intl-pluralrules"));
polyfills.push(
import("@formatjs/intl-pluralrules/polyfill-force").then(
// Locale data for plural rules breaks current JSON conversions as it includes functions,
// so only import English to avoid huge bundles
// TODO: Setup JS imports instead of JSON fetches
() => import("@formatjs/intl-pluralrules/locale-data/en")
)
);
}
if (shouldPolyfillRelativeTimeFormat(locale)) {
polyfills.push(import("@formatjs/intl-relativetimeformat/polyfill-force"));
@@ -90,9 +100,4 @@ const polyfillIntl = async () => {
);
};
// Each legacy entry bundle (core, app, authorize, onboarding) carries its own
// copy of this module, and the bundles load in parallel. A module-level flag
// only stops re-runs within one bundle, so a second bundle could probe
// Intl.* while the first was still loading locale data. Share one promise
// per page instead, so every bundle waits for the same run.
await (globalThis.__haIntlPolyfill ??= polyfillIntl());
await polyfillIntl();
+11 -14
View File
@@ -17,7 +17,6 @@
"climate": "Climate",
"home": "Overview",
"maintenance": "Maintenance",
"marketplace": "Marketplace",
"notfound": "Page not found"
},
"state": {
@@ -1663,9 +1662,7 @@
"no_items": "No items available",
"unknown_item": "Unknown item",
"search_or_custom": "Search | Add custom item",
"add_custom_item": "Add custom item",
"result_count": "{count} {count, plural,\n one {result}\n other {results}\n} for {term}",
"no_results": "No results for {term}"
"add_custom_item": "Add custom item"
},
"suggest_with_ai": {
"label": "Suggest",
@@ -3952,15 +3949,15 @@
"addon_repositories": "[%key:ui::panel::config::backup::overview::progress::description::create_backup::app_repositories%]",
"addons": "[%key:ui::panel::config::backup::overview::progress::description::create_backup::apps%]",
"await_addon_restarts": "[%key:ui::panel::config::backup::overview::progress::description::create_backup::await_app_restarts%]",
"app_repositories": "Backing up app repositories...",
"apps": "Backing up apps...",
"await_app_restarts": "Waiting for apps to restart...",
"docker_config": "Backing up Docker configuration...",
"finishing_file": "Finishing backup file...",
"folders": "Backing up folders...",
"home_assistant": "Backing up Home Assistant...",
"upload_to_agents": "Uploading backup...",
"cleaning_up": "Cleaning up..."
"app_repositories": "Backing up app repositories",
"apps": "Backing up apps",
"await_app_restarts": "Waiting for apps to restart",
"docker_config": "Backing up Docker configuration",
"finishing_file": "Finishing backup file",
"folders": "Backing up folders",
"home_assistant": "Backing up Home Assistant",
"upload_to_agents": "Uploading to locations",
"cleaning_up": "Cleaning up"
},
"restore_backup": {
"addon_repositories": "[%key:ui::panel::config::backup::overview::progress::description::restore_backup::app_repositories%]",
@@ -3988,7 +3985,7 @@
"apps": "Apps",
"media": "Media",
"upload": "Uploading backup",
"cleaning_up": "Cleanup"
"cleaning_up": "Cleaning up"
},
"agent_status": {
"uploading": "Uploading...",
-2
View File
@@ -41,8 +41,6 @@ declare global {
var __HASS_URL__: string;
// Read by intl-polyfill before a polyfill replaces Intl.DateTimeFormat
var __haNativeTimeZone: string | undefined;
// Shared by every legacy entry bundle so the Intl polyfills load once
var __haIntlPolyfill: Promise<void> | undefined;
// Handshake between the app entry and the extra modules in index.html
var __haScopedRegistryReady: boolean | undefined;
var __haLoadExtraModules: (() => void) | undefined;
@@ -1,60 +0,0 @@
import { describe, expect, it } from "vitest";
import { searchResultsStatus } from "../../../src/components/list/search-results-status";
import { mockLocalize } from "../../fixtures/hass";
interface Row {
id: string;
// Like "Add custom item" or "Add new area", offered for any search
action?: boolean;
}
const isResult = (row: Row) => !row.action;
describe("searchResultsStatus", () => {
it("counts only the rows that are results", () => {
const rows: (Row | string)[] = [
"Lights",
{ id: "kitchen_light" },
{ id: "bedroom_light" },
{ id: "add_new", action: true },
];
expect(searchResultsStatus("light", rows, isResult, mockLocalize)).toBe(
'ui.components.combo-box.result_count: {"count":2,"term":"‘light’"}'
);
expect(
searchResultsStatus(
"garage",
["Lights", { id: "add_new", action: true }],
isResult,
mockLocalize
)
).toBe('ui.components.combo-box.no_results: {"term":"‘garage’"}');
});
it("uses a not found label that takes the search", () => {
expect(
searchResultsStatus(
"garage",
[],
isResult,
mockLocalize,
(search) => `No areas found for ‘${search}’`
)
).toBe("No areas found for ‘garage’");
});
// A live region is only read out when its text changes.
it("names the search, so a new search with as many results is read out", () => {
expect(
searchResultsStatus("bedroom", [{ id: "a" }], isResult, mockLocalize)
).not.toBe(
searchResultsStatus("fan", [{ id: "b" }], isResult, mockLocalize)
);
});
it("is undefined without a search", () => {
expect(
searchResultsStatus("", [{ id: "a" }], isResult, mockLocalize)
).toBeUndefined();
});
});