Compare commits

..

35 Commits

Author SHA1 Message Date
Paul Bottein
c080ebbf46 Add user selector with multiple and system option 2023-10-31 11:19:16 +01:00
dependabot[bot]
c3d809fcf3 Bump actions/setup-node from 3.8.1 to 4.0.0 (#18468)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 11:18:14 +01:00
renovate[bot]
cbd0c39091 Update formatjs monorepo (#18423) 2023-10-29 22:05:19 -04:00
renovate[bot]
113eb5be24 Update dependency eslint-plugin-lit to v1.10.1 (#18460) 2023-10-28 21:45:57 -04:00
renovate[bot]
c497669fd3 Update dependency ts-lit-plugin to v2.0.0 (#18459) 2023-10-29 01:39:04 +00:00
renovate[bot]
c32ca5885b Update dependency lit-analyzer to v2.0.1 (#18458) 2023-10-28 21:28:01 -04:00
renovate[bot]
3c792c4019 Update dependency @bundle-stats/plugin-webpack-filter to v4.7.8 (#18457) 2023-10-28 21:23:43 -04:00
renovate[bot]
9762e61ee2 Update vaadinWebComponents monorepo to v24.2.1 (#18454)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-28 20:36:52 +00:00
renovate[bot]
c09c39998b Update dependency vue to v2.7.15 (#18424)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-28 16:22:32 -04:00
renovate[bot]
d37e29c247 Update CodeMirror (#18453)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-28 16:20:45 -04:00
renovate[bot]
51f22cd74a Update dependency eslint-import-resolver-webpack to v0.13.8 (#18422)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-28 16:12:52 -04:00
renovate[bot]
b57dc968bd Update dependency eslint-plugin-import to v2.29.0 (#18425)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-28 16:07:23 -04:00
renovate[bot]
e2e8cb785a Update typescript-eslint monorepo to v6.9.0 (#18433)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-28 16:06:02 -04:00
Bram Kragten
9961a4ae3f Bumped version to 20231027.0 2023-10-27 16:33:32 +02:00
Bram Kragten
c25755bfcd Translate todo panel title, update assist title/icon (#18442) 2023-10-27 16:33:02 +02:00
Bram Kragten
40983619d6 Reload when entering safe mode (#18443) 2023-10-27 15:48:01 +02:00
Bram Kragten
54758b5962 Don't override ranges provided by parent (#18444) 2023-10-27 15:47:47 +02:00
Bram Kragten
4f09485b20 Update todo list items when entity changes, only refresh on shopping … (#18445) 2023-10-27 15:47:37 +02:00
Paul Bottein
9207f6c407 Fix unit of measurement not displayed in entity settings (#18440) 2023-10-27 13:29:41 +02:00
Paul Bottein
1a2312460a Disable resource panel in safe mode (#18437) 2023-10-27 13:29:00 +02:00
Simon Lamon
951b88ab4c Fix change entity in dev tools state (#18441) 2023-10-27 13:27:01 +02:00
Bram Kragten
d3cc57d8b4 Don't use lookbehind assertion in slugify (#18438) 2023-10-27 12:53:17 +02:00
karwosts
4e9b118728 Ensure energy card titles always displayed (#18432) 2023-10-27 10:42:01 +02:00
Paul Bottein
f1748e4dd5 Bumped version to 20231026.0 2023-10-26 15:39:36 +02:00
Paul Bottein
d491d8f5ac Quick fix for lovelace resources not loaded (#18430) 2023-10-26 15:37:31 +02:00
Bram Kragten
cf0fde0f3c Change move item todo API (#18410)
* Change move item todo API

* Handle entity unavailable, add link to more info, allow to delete local todo
2023-10-26 15:37:13 +02:00
Paul Bottein
a7dc2cfaa6 Reduce slider handle size (#18427) 2023-10-26 15:25:47 +02:00
Paul Bottein
d8c7db6ebf Add translations to tile state content options (#18428) 2023-10-26 10:32:09 +00:00
J. Nick Koston
c3743b57ea Speed up first load by preloading recorder info (#18412) 2023-10-25 19:29:44 +00:00
Steve Repsher
e16a101de8 Compress service worker (#18407) 2023-10-25 17:17:11 +02:00
Paul Bottein
94ad47c60e Hide reveal icon on edge for text-field (#18408) 2023-10-25 17:15:43 +02:00
Bram Kragten
184ef7b7ff Bar media player fixes (#18402) 2023-10-25 16:04:05 +02:00
karwosts
81053f2e07 Fix an undefined exception in more-info popup for history graph (#18404) 2023-10-25 15:48:05 +02:00
Paul Bottein
e8b4eeec67 Allow any number in above and below numeric condition (#18403) 2023-10-25 13:38:39 +00:00
karwosts
b0b7e77e28 Fix schedule form rendering after disconnect (#18401) 2023-10-25 13:21:05 +00:00
46 changed files with 1003 additions and 527 deletions

View File

@@ -26,7 +26,7 @@ jobs:
ref: dev ref: dev
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn
@@ -62,7 +62,7 @@ jobs:
ref: master ref: master
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn

View File

@@ -26,7 +26,7 @@ jobs:
- name: Check out files from GitHub - name: Check out files from GitHub
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4.1.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn
@@ -57,7 +57,7 @@ jobs:
- name: Check out files from GitHub - name: Check out files from GitHub
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4.1.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn
@@ -75,7 +75,7 @@ jobs:
- name: Check out files from GitHub - name: Check out files from GitHub
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4.1.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn
@@ -99,7 +99,7 @@ jobs:
- name: Check out files from GitHub - name: Check out files from GitHub
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4.1.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn

View File

@@ -27,7 +27,7 @@ jobs:
ref: dev ref: dev
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn
@@ -63,7 +63,7 @@ jobs:
ref: master ref: master
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn

View File

@@ -19,7 +19,7 @@ jobs:
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4.1.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn

View File

@@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4.1.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn

View File

@@ -28,7 +28,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }} python-version: ${{ env.PYTHON_VERSION }}
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn

View File

@@ -34,7 +34,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }} python-version: ${{ env.PYTHON_VERSION }}
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3.8.1 uses: actions/setup-node@v4.0.0
with: with:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
cache: yarn cache: yarn

View File

@@ -45,8 +45,8 @@ gulp.task(
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"), gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
"copy-static-app", "copy-static-app",
env.useRollup() ? "rollup-prod-app" : "webpack-prod-app", env.useRollup() ? "rollup-prod-app" : "webpack-prod-app",
gulp.parallel("gen-pages-app-prod", "gen-service-worker-app-prod"),
// Don't compress running tests // Don't compress running tests
...(env.isTestBuild() ? [] : ["compress-app"]), ...(env.isTestBuild() ? [] : ["compress-app"])
gulp.parallel("gen-pages-app-prod", "gen-service-worker-app-prod")
) )
); );

View File

@@ -29,14 +29,14 @@
"@braintree/sanitize-url": "6.0.4", "@braintree/sanitize-url": "6.0.4",
"@codemirror/autocomplete": "6.10.2", "@codemirror/autocomplete": "6.10.2",
"@codemirror/commands": "6.3.0", "@codemirror/commands": "6.3.0",
"@codemirror/language": "6.9.1", "@codemirror/language": "6.9.2",
"@codemirror/legacy-modes": "6.3.3", "@codemirror/legacy-modes": "6.3.3",
"@codemirror/search": "6.5.4", "@codemirror/search": "6.5.4",
"@codemirror/state": "6.3.1", "@codemirror/state": "6.3.1",
"@codemirror/view": "6.21.3", "@codemirror/view": "6.21.4",
"@egjs/hammerjs": "2.0.17", "@egjs/hammerjs": "2.0.17",
"@formatjs/intl-datetimeformat": "6.11.0", "@formatjs/intl-datetimeformat": "6.11.1",
"@formatjs/intl-displaynames": "6.6.0", "@formatjs/intl-displaynames": "6.6.1",
"@formatjs/intl-getcanonicallocales": "2.3.0", "@formatjs/intl-getcanonicallocales": "2.3.0",
"@formatjs/intl-listformat": "7.5.0", "@formatjs/intl-listformat": "7.5.0",
"@formatjs/intl-locale": "3.4.0", "@formatjs/intl-locale": "3.4.0",
@@ -94,8 +94,8 @@
"@polymer/paper-toast": "3.0.1", "@polymer/paper-toast": "3.0.1",
"@polymer/polymer": "3.5.1", "@polymer/polymer": "3.5.1",
"@thomasloven/round-slider": "0.6.0", "@thomasloven/round-slider": "0.6.0",
"@vaadin/combo-box": "24.2.0", "@vaadin/combo-box": "24.2.1",
"@vaadin/vaadin-themable-mixin": "24.2.0", "@vaadin/vaadin-themable-mixin": "24.2.1",
"@vibrant/color": "3.2.1-alpha.1", "@vibrant/color": "3.2.1-alpha.1",
"@vibrant/core": "3.2.1-alpha.1", "@vibrant/core": "3.2.1-alpha.1",
"@vibrant/quantizer-mmcq": "3.2.1-alpha.1", "@vibrant/quantizer-mmcq": "3.2.1-alpha.1",
@@ -142,7 +142,7 @@
"unfetch": "5.0.0", "unfetch": "5.0.0",
"vis-data": "7.1.7", "vis-data": "7.1.7",
"vis-network": "9.1.8", "vis-network": "9.1.8",
"vue": "2.7.14", "vue": "2.7.15",
"vue2-daterange-picker": "0.6.8", "vue2-daterange-picker": "0.6.8",
"weekstart": "2.0.0", "weekstart": "2.0.0",
"workbox-cacheable-response": "7.0.0", "workbox-cacheable-response": "7.0.0",
@@ -159,7 +159,7 @@
"@babel/plugin-transform-runtime": "7.23.2", "@babel/plugin-transform-runtime": "7.23.2",
"@babel/preset-env": "7.23.2", "@babel/preset-env": "7.23.2",
"@babel/preset-typescript": "7.23.2", "@babel/preset-typescript": "7.23.2",
"@bundle-stats/plugin-webpack-filter": "4.7.7", "@bundle-stats/plugin-webpack-filter": "4.7.8",
"@koa/cors": "4.0.0", "@koa/cors": "4.0.0",
"@lokalise/node-api": "12.0.0", "@lokalise/node-api": "12.0.0",
"@octokit/auth-oauth-device": "6.0.1", "@octokit/auth-oauth-device": "6.0.1",
@@ -188,8 +188,8 @@
"@types/tar": "6.1.7", "@types/tar": "6.1.7",
"@types/ua-parser-js": "0.7.38", "@types/ua-parser-js": "0.7.38",
"@types/webspeechapi": "0.0.29", "@types/webspeechapi": "0.0.29",
"@typescript-eslint/eslint-plugin": "6.8.0", "@typescript-eslint/eslint-plugin": "6.9.0",
"@typescript-eslint/parser": "6.8.0", "@typescript-eslint/parser": "6.9.0",
"@web/dev-server": "0.1.38", "@web/dev-server": "0.1.38",
"@web/dev-server-rollup": "0.4.1", "@web/dev-server-rollup": "0.4.1",
"babel-loader": "9.1.3", "babel-loader": "9.1.3",
@@ -200,10 +200,10 @@
"eslint-config-airbnb-base": "15.0.0", "eslint-config-airbnb-base": "15.0.0",
"eslint-config-airbnb-typescript": "17.1.0", "eslint-config-airbnb-typescript": "17.1.0",
"eslint-config-prettier": "9.0.0", "eslint-config-prettier": "9.0.0",
"eslint-import-resolver-webpack": "0.13.7", "eslint-import-resolver-webpack": "0.13.8",
"eslint-plugin-disable": "2.0.3", "eslint-plugin-disable": "2.0.3",
"eslint-plugin-import": "2.28.1", "eslint-plugin-import": "2.29.0",
"eslint-plugin-lit": "1.9.1", "eslint-plugin-lit": "1.10.1",
"eslint-plugin-lit-a11y": "4.1.0", "eslint-plugin-lit-a11y": "4.1.0",
"eslint-plugin-unused-imports": "3.0.0", "eslint-plugin-unused-imports": "3.0.0",
"eslint-plugin-wc": "2.0.4", "eslint-plugin-wc": "2.0.4",
@@ -222,7 +222,7 @@
"instant-mocha": "1.5.2", "instant-mocha": "1.5.2",
"jszip": "3.10.1", "jszip": "3.10.1",
"lint-staged": "15.0.2", "lint-staged": "15.0.2",
"lit-analyzer": "2.0.0-pre.3", "lit-analyzer": "2.0.1",
"lodash.template": "4.5.0", "lodash.template": "4.5.0",
"magic-string": "0.30.5", "magic-string": "0.30.5",
"map-stream": "0.0.7", "map-stream": "0.0.7",
@@ -241,7 +241,7 @@
"systemjs": "6.14.2", "systemjs": "6.14.2",
"tar": "6.2.0", "tar": "6.2.0",
"terser-webpack-plugin": "5.3.9", "terser-webpack-plugin": "5.3.9",
"ts-lit-plugin": "2.0.0-pre.1", "ts-lit-plugin": "2.0.0",
"typescript": "5.2.2", "typescript": "5.2.2",
"vinyl-buffer": "1.0.1", "vinyl-buffer": "1.0.1",
"vinyl-source-stream": "2.0.0", "vinyl-source-stream": "2.0.0",

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "home-assistant-frontend" name = "home-assistant-frontend"
version = "20231025.1" version = "20231027.0"
license = {text = "Apache-2.0"} license = {text = "Apache-2.0"}
description = "The Home Assistant frontend" description = "The Home Assistant frontend"
readme = "README.md" readme = "README.md"

View File

@@ -14,7 +14,7 @@ export const slugify = (value: string, delimiter = "_") => {
.toString() .toString()
.toLowerCase() .toLowerCase()
.replace(p, (c) => b.charAt(a.indexOf(c))) // Replace special characters .replace(p, (c) => b.charAt(a.indexOf(c))) // Replace special characters
.replace(/(?<=\d),(?=\d)/g, "") // Remove Commas between numbers .replace(/(\d),(?=\d)/g, "$1") // Remove Commas between numbers
.replace(/[^a-z0-9]+/g, delimiter) // Replace all non-word characters .replace(/[^a-z0-9]+/g, delimiter) // Replace all non-word characters
.replace(new RegExp(`(${delimiter})\\1+`, "g"), "$1") // Replace multiple delimiters with single delimiter .replace(new RegExp(`(${delimiter})\\1+`, "g"), "$1") // Replace multiple delimiters with single delimiter
.replace(new RegExp(`^${delimiter}+`), "") // Trim delimiter from start of text .replace(new RegExp(`^${delimiter}+`), "") // Trim delimiter from start of text

View File

@@ -223,7 +223,7 @@ export class StateHistoryCharts extends LitElement {
); );
} else { } else {
this._computedStartTime = new Date( this._computedStartTime = new Date(
this.historyData.timeline.reduce( (this.historyData?.timeline ?? []).reduce(
(minTime, stateInfo) => (minTime, stateInfo) =>
Math.min( Math.min(
minTime, minTime,

View File

@@ -71,7 +71,8 @@ class HaEntitiesPickerLight extends LitElement {
@property({ attribute: "picked-entity-label" }) @property({ attribute: "picked-entity-label" })
public pickedEntityLabel?: string; public pickedEntityLabel?: string;
@property({ attribute: "pick-entity-label" }) public pickEntityLabel?: string; @property({ attribute: "pick-entity-label" })
public pickEntityLabel?: string;
@property() public entityFilter?: HaEntityPickerEntityFilterFunc; @property() public entityFilter?: HaEntityPickerEntityFilterFunc;

View File

@@ -20,6 +20,10 @@ export class HaButton extends Button {
.trailing-icon { .trailing-icon {
display: flex; display: flex;
} }
.slot-container {
width: 100%;
overflow: hidden;
}
`, `,
]; ];
} }

View File

@@ -46,6 +46,8 @@ export class HaDateRangePicker extends LitElement {
@property() public ranges?: DateRangePickerRanges | false; @property() public ranges?: DateRangePickerRanges | false;
@state() private _ranges?: DateRangePickerRanges;
@property() public autoApply = false; @property() public autoApply = false;
@property() public timePicker = true; @property() public timePicker = true;
@@ -93,7 +95,7 @@ export class HaDateRangePicker extends LitElement {
} }
); );
this.ranges = { this._ranges = {
[this.hass.localize("ui.components.date-range-picker.ranges.today")]: [ [this.hass.localize("ui.components.date-range-picker.ranges.today")]: [
calcDate(today, startOfDay, this.hass.locale, this.hass.config, { calcDate(today, startOfDay, this.hass.locale, this.hass.config, {
weekStartsOn, weekStartsOn,
@@ -206,15 +208,15 @@ export class HaDateRangePicker extends LitElement {
.path=${mdiCalendar} .path=${mdiCalendar}
></ha-icon-button>`} ></ha-icon-button>`}
</div> </div>
${this.ranges ${this.ranges !== false && (this.ranges || this._ranges)
? html`<div ? html`<div
slot="ranges" slot="ranges"
class="date-range-ranges" class="date-range-ranges"
.dir=${this._rtlDirection} .dir=${this._rtlDirection}
> >
<mwc-list @action=${this._setDateRange} activatable> <mwc-list @action=${this._setDateRange} activatable>
${Object.keys(this.ranges).map( ${Object.keys(this.ranges || this._ranges!).map(
(name) => html`<mwc-list-item> ${name} </mwc-list-item>` (name) => html`<mwc-list-item>${name}</mwc-list-item>`
)} )}
</mwc-list> </mwc-list>
</div>` </div>`
@@ -234,7 +236,9 @@ export class HaDateRangePicker extends LitElement {
} }
private _setDateRange(ev: CustomEvent<ActionDetail>) { private _setDateRange(ev: CustomEvent<ActionDetail>) {
const dateRange = Object.values(this.ranges!)[ev.detail.index]; const dateRange = Object.values(this.ranges || this._ranges!)[
ev.detail.index
];
const dateRangePicker = this._dateRangePicker; const dateRangePicker = this._dateRangePicker;
dateRangePicker.clickRange(dateRange); dateRangePicker.clickRange(dateRange);
dateRangePicker.clickedApply(); dateRangePicker.clickedApply();

View File

@@ -94,6 +94,8 @@ export class HaDialog extends DialogBase {
} }
.mdc-dialog__title { .mdc-dialog__title {
padding: 24px 24px 0 24px; padding: 24px 24px 0 24px;
text-overflow: ellipsis;
overflow: hidden;
} }
.mdc-dialog__actions { .mdc-dialog__actions {
padding: 12px 24px 12px 24px; padding: 12px 24px 12px 24px;

View File

@@ -0,0 +1,65 @@
import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators";
import type { UserSelector } from "../../data/selector";
import { HomeAssistant } from "../../types";
import "../user/ha-user-picker";
import "../user/ha-users-picker";
@customElement("ha-selector-user")
export class HaUserSelector extends LitElement {
@property() public hass!: HomeAssistant;
@property() public selector!: UserSelector;
@property() public value?: any;
@property() public label?: string;
@property() public helper?: string;
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public required = true;
protected render() {
if (this.selector.user?.multiple) {
return html`
<ha-users-picker
.hass=${this.hass}
.value=${this.value}
.label=${this.label}
.helper=${this.helper}
.disabled=${this.disabled}
.required=${this.required}
.includeSystem=${this.selector.user.include_system}
></ha-users-picker>
`;
}
return html`
<ha-user-picker
.hass=${this.hass}
.value=${this.value}
.label=${this.label}
.helper=${this.helper}
.disabled=${this.disabled}
.required=${this.required}
.includeSystem=${this.selector.user?.include_system}
></ha-user-picker>
`;
}
static get styles() {
return css`
ha-user-picker {
width: 100%;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-selector-user": HaUserSelector;
}
}

View File

@@ -50,6 +50,7 @@ const LOAD_ELEMENTS = {
color_temp: () => import("./ha-selector-color-temp"), color_temp: () => import("./ha-selector-color-temp"),
ui_action: () => import("./ha-selector-ui-action"), ui_action: () => import("./ha-selector-ui-action"),
ui_color: () => import("./ha-selector-ui-color"), ui_color: () => import("./ha-selector-ui-color"),
user: () => import("./ha-selector-user"),
}; };
const LEGACY_UI_SELECTORS = new Set(["ui-action", "ui-color"]); const LEGACY_UI_SELECTORS = new Set(["ui-action", "ui-color"]);

View File

@@ -10,7 +10,8 @@ export class HaSlider extends MdSlider {
:host { :host {
--md-sys-color-primary: var(--primary-color); --md-sys-color-primary: var(--primary-color);
--md-sys-color-outline: var(--outline-color); --md-sys-color-outline: var(--outline-color);
--md-slider-handle-width: 14px;
--md-slider-handle-height: 14px;
min-width: 100px; min-width: 100px;
min-inline-size: 100px; min-inline-size: 100px;
width: 200px; width: 200px;

View File

@@ -136,6 +136,11 @@ export class HaTextField extends TextFieldBase {
text-align: var(--text-field-text-align, start); text-align: var(--text-field-text-align, start);
} }
/* Edge, hide reveal password icon */
::-ms-reveal {
display: none;
}
/* Chrome, Safari, Edge, Opera */ /* Chrome, Safari, Edge, Opera */
:host([no-spinner]) input::-webkit-outer-spin-button, :host([no-spinner]) input::-webkit-outer-spin-button,
:host([no-spinner]) input::-webkit-inner-spin-button { :host([no-spinner]) input::-webkit-inner-spin-button {

View File

@@ -1,68 +1,84 @@
import "@material/mwc-list/mwc-list-item"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import {
import { property } from "lit/decorators"; css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { stringCompare } from "../../common/string/compare"; import { stringCompare } from "../../common/string/compare";
import {
fuzzyFilterSort,
ScorableTextItem,
} from "../../common/string/filter/sequence-matching";
import { fetchUsers, User } from "../../data/user"; import { fetchUsers, User } from "../../data/user";
import { HomeAssistant } from "../../types"; import { HomeAssistant, ValueChangedEvent } from "../../types";
import "../ha-combo-box";
import type { HaComboBox } from "../ha-combo-box";
import "../ha-list-item";
import "../ha-select"; import "../ha-select";
import "./ha-user-badge"; import "./ha-user-badge";
import "../ha-list-item";
type ScorableUser = ScorableTextItem & User;
class HaUserPicker extends LitElement { class HaUserPicker extends LitElement {
public hass?: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public label?: string; @property() public label?: string;
@property() public noUserLabel?: string; @property() public value?: string;
@property() public value = ""; @property() public helper?: string;
@property() public users?: User[]; @property({ attribute: false }) public users?: User[];
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled?: boolean;
private _sortedUsers = memoizeOne((users?: User[]) => { @property({ type: Boolean }) public required?: boolean;
if (!users) {
return []; @state() private _opened?: boolean;
@query("ha-combo-box", true) public comboBox!: HaComboBox;
@property({ type: Boolean, attribute: "include-system" })
public includeSystem?: boolean;
private _init = false;
private _getUserItems = memoizeOne(
(users: User[] | undefined): ScorableUser[] => {
if (!users) {
return [];
}
return users
.sort((a, b) =>
stringCompare(a.name, b.name, this.hass!.locale.language)
)
.map((user) => ({
...user,
strings: [user.name, ...(user.username ? [user.username] : [])],
}));
} }
);
return users private _filteredUsers = memoizeOne(
.filter((user) => !user.system_generated) (users: User[], includeSystem?: boolean) =>
.sort((a, b) => users.filter((user) => includeSystem || !user.system_generated)
stringCompare(a.name, b.name, this.hass!.locale.language) );
);
});
protected render(): TemplateResult { public async open() {
return html` await this.updateComplete;
<ha-select await this.comboBox?.open();
.label=${this.label} }
.disabled=${this.disabled}
.value=${this.value} public async focus() {
@selected=${this._userChanged} await this.updateComplete;
> await this.comboBox?.focus();
${this.users?.length === 0
? html`<mwc-list-item value="">
${this.noUserLabel ||
this.hass?.localize("ui.components.user-picker.no_user")}
</mwc-list-item>`
: ""}
${this._sortedUsers(this.users).map(
(user) => html`
<ha-list-item graphic="avatar" .value=${user.id}>
<ha-user-badge
.hass=${this.hass}
.user=${user}
slot="graphic"
></ha-user-badge>
${user.name}
</ha-list-item>
`
)}
</ha-select>
`;
} }
protected firstUpdated(changedProps) { protected firstUpdated(changedProps) {
@@ -74,25 +90,104 @@ class HaUserPicker extends LitElement {
} }
} }
private _userChanged(ev) { protected updated(changedProps: PropertyValues) {
const newValue = ev.target.value; super.updated(changedProps);
if (
(!this._init && this.users) ||
(this._init && changedProps.has("_opened") && this._opened)
) {
this._init = true;
const filteredUsers = this._filteredUsers(
this.users ?? [],
this.includeSystem
);
const items = this._getUserItems(filteredUsers);
if (newValue !== this.value) { this.comboBox.items = items;
this.value = newValue; this.comboBox.filteredItems = items;
setTimeout(() => {
fireEvent(this, "value-changed", { value: newValue });
fireEvent(this, "change");
}, 0);
} }
} }
private _rowRenderer: ComboBoxLitRenderer<User> = (item) => html`
<ha-list-item
graphic="avatar"
.value=${item.id}
.twoline=${!!item.username}
>
<ha-user-badge
.hass=${this.hass}
.user=${item}
slot="graphic"
></ha-user-badge>
${item.name}
<span slot="secondary">${item.username}</span>
</ha-list-item>
`;
protected render(): TemplateResult {
return html`
<ha-combo-box
.hass=${this.hass}
.label=${this.label === undefined && this.hass
? this.hass.localize("ui.components.user-picker.user")
: this.label}
.value=${this._value}
.helper=${this.helper}
.renderer=${this._rowRenderer}
.disabled=${this.disabled}
.required=${this.required}
item-id-path="id"
item-value-path="id"
item-label-path="name"
@opened-changed=${this._openedChanged}
@value-changed=${this._valueChanged}
@filter-changed=${this._filterChanged}
>
</ha-combo-box>
`;
}
private _filterChanged(ev: CustomEvent): void {
const target = ev.target as HaComboBox;
const filterString = ev.detail.value.toLowerCase();
target.filteredItems = filterString.length
? fuzzyFilterSort<ScorableUser>(filterString, target.items || [])
: target.items;
}
private _valueChanged(ev: ValueChangedEvent<string>) {
ev.stopPropagation();
let newValue = ev.detail.value;
if (newValue === "no_users") {
newValue = "";
}
if (newValue !== this._value) {
this._setValue(newValue);
}
}
private _openedChanged(ev: ValueChangedEvent<boolean>) {
this._opened = ev.detail.value;
}
private get _value() {
return this.value || "";
}
private _setValue(value: string) {
this.value = value;
setTimeout(() => {
fireEvent(this, "value-changed", { value });
fireEvent(this, "change");
}, 0);
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return css` return css`
:host { ha-select {
display: inline-block; width: 100%;
}
mwc-list {
display: block;
} }
`; `;
} }

View File

@@ -1,5 +1,4 @@
import { mdiClose } from "@mdi/js"; import { css, html, LitElement, nothing } from "lit";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { guard } from "lit/directives/guard"; import { guard } from "lit/directives/guard";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
@@ -15,6 +14,10 @@ class HaUsersPickerLight extends LitElement {
@property() public value?: string[]; @property() public value?: string[];
@property({ type: Boolean }) public disabled?: boolean;
@property({ type: Boolean }) public required?: boolean;
@property({ attribute: "picked-user-label" }) @property({ attribute: "picked-user-label" })
public pickedUserLabel?: string; public pickedUserLabel?: string;
@@ -24,6 +27,9 @@ class HaUsersPickerLight extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public users?: User[]; public users?: User[];
@property({ type: Boolean, attribute: "include-system" })
public includeSystem?: boolean;
protected firstUpdated(changedProps) { protected firstUpdated(changedProps) {
super.firstUpdated(changedProps); super.firstUpdated(changedProps);
if (this.users === undefined) { if (this.users === undefined) {
@@ -38,69 +44,80 @@ class HaUsersPickerLight extends LitElement {
return nothing; return nothing;
} }
const notSelectedUsers = this._notSelectedUsers(this.users, this.value); const filteredUsers = this._filteredUsers(this.users, this.includeSystem);
const selectedUsers = this._selectedUsers(filteredUsers, this.value);
const notSelectedUsers = this._notSelectedUsers(filteredUsers, this.value);
return html` return html`
${guard( ${guard([notSelectedUsers], () =>
[notSelectedUsers], selectedUsers.map(
() => (user, idx) => html`
this.value?.map( <div>
(user_id, idx) => html` <ha-user-picker
<div> .label=${this.pickedUserLabel}
<ha-user-picker .index=${idx}
.label=${this.pickedUserLabel} .hass=${this.hass}
.noUserLabel=${this.hass!.localize( .value=${user.id}
"ui.components.user-picker.remove_user" .users=${this._notSelectedUsersAndCurrent(
)} user,
.index=${idx} filteredUsers,
.hass=${this.hass} notSelectedUsers
.value=${user_id} )}
.users=${this._notSelectedUsersAndSelected( @value-changed=${this._userChanged}
user_id, .disabled=${this.disabled}
this.users, .includeSystem=${this.includeSystem}
notSelectedUsers ></ha-user-picker>
)} </div>
@value-changed=${this._userChanged} `
></ha-user-picker> )
<ha-icon-button
.userId=${user_id}
.label=${this.hass!.localize(
"ui.components.user-picker.remove_user"
)}
.path=${mdiClose}
@click=${this._removeUser}
>
></ha-icon-button
>
</div>
`
)
)} )}
<div>${this._renderPicker(notSelectedUsers)}</div>
`;
}
private _renderPicker(users?: User[]) {
return html`
<ha-user-picker <ha-user-picker
.label=${this.pickUserLabel || .label=${this.pickUserLabel}
this.hass!.localize("ui.components.user-picker.add_user")}
.hass=${this.hass} .hass=${this.hass}
.users=${notSelectedUsers} .users=${users}
.disabled=${!notSelectedUsers?.length}
@value-changed=${this._addUser} @value-changed=${this._addUser}
.disabled=${this.disabled || users?.length === 0}
.required=${this.required}
.includeSystem=${this.includeSystem}
></ha-user-picker> ></ha-user-picker>
`; `;
} }
private _notSelectedUsers = memoizeOne( private _filteredUsers = memoizeOne(
(users?: User[], currentUsers?: string[]) => (users: User[], includeSystem?: boolean) =>
currentUsers users.filter((user) => includeSystem || !user.system_generated)
? users?.filter(
(user) => !user.system_generated && !currentUsers.includes(user.id)
)
: users?.filter((user) => !user.system_generated)
); );
private _notSelectedUsersAndSelected = ( private _selectedUsers = memoizeOne(
userId: string, (users: User[], selectedUserIds?: string[]) => {
if (!selectedUserIds) {
return [];
}
return users.filter((user) => selectedUserIds.includes(user.id));
}
);
private _notSelectedUsers = memoizeOne(
(users: User[], selectedUserIds?: string[]) => {
if (!selectedUserIds) {
return users;
}
return users.filter((user) => !selectedUserIds.includes(user.id));
}
);
private _notSelectedUsersAndCurrent = (
currentUser: User,
users?: User[], users?: User[],
notSelected?: User[] notSelected?: User[]
) => { ) => {
const selectedUser = users?.find((user) => user.id === userId); const selectedUser = users?.find((user) => user.id === currentUser.id);
if (selectedUser) { if (selectedUser) {
return notSelected ? [...notSelected, selectedUser] : [selectedUser]; return notSelected ? [...notSelected, selectedUser] : [selectedUser];
} }
@@ -123,7 +140,7 @@ class HaUsersPickerLight extends LitElement {
const index = (event.currentTarget as any).index; const index = (event.currentTarget as any).index;
const newValue = event.detail.value; const newValue = event.detail.value;
const newUsers = [...this._currentUsers]; const newUsers = [...this._currentUsers];
if (newValue === "") { if (newValue === undefined) {
newUsers.splice(index, 1); newUsers.splice(index, 1);
} else { } else {
newUsers.splice(index, 1, newValue); newUsers.splice(index, 1, newValue);
@@ -146,22 +163,11 @@ class HaUsersPickerLight extends LitElement {
this._updateUsers([...currentUsers, toAdd]); this._updateUsers([...currentUsers, toAdd]);
} }
private _removeUser(event) { static override styles = css`
const userId = (event.currentTarget as any).userId; div {
this._updateUsers(this._currentUsers.filter((user) => user !== userId)); margin-top: 8px;
} }
`;
static get styles(): CSSResultGroup {
return css`
:host {
display: block;
}
div {
display: flex;
align-items: center;
}
`;
}
} }
declare global { declare global {

View File

@@ -348,11 +348,6 @@ export const getLegacyLovelaceCollection = (conn: Connection) =>
) )
); );
export interface WindowWithLovelaceProm extends Window {
llConfProm?: Promise<LovelaceConfig>;
llResProm?: Promise<LovelaceResource[]>;
}
export interface ActionHandlerOptions { export interface ActionHandlerOptions {
hasHold?: boolean; hasHold?: boolean;
hasDoubleClick?: boolean; hasDoubleClick?: boolean;

8
src/data/preloads.ts Normal file
View File

@@ -0,0 +1,8 @@
import { LovelaceConfig, LovelaceResource } from "./lovelace";
import { RecorderInfo } from "./recorder";
export interface WindowWithPreloads extends Window {
llConfProm?: Promise<LovelaceConfig>;
llResProm?: Promise<LovelaceResource[]>;
recorderInfoProm?: Promise<RecorderInfo>;
}

View File

@@ -1,3 +1,4 @@
import { Connection } from "home-assistant-js-websocket";
import { computeStateName } from "../common/entity/compute_state_name"; import { computeStateName } from "../common/entity/compute_state_name";
import { HaDurationData } from "../components/ha-duration-input"; import { HaDurationData } from "../components/ha-duration-input";
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
@@ -115,8 +116,8 @@ export interface StatisticsValidationResults {
[statisticId: string]: StatisticsValidationResult[]; [statisticId: string]: StatisticsValidationResult[];
} }
export const getRecorderInfo = (hass: HomeAssistant) => export const getRecorderInfo = (conn: Connection) =>
hass.callWS<RecorderInfo>({ conn.sendMessagePromise<RecorderInfo>({
type: "recorder/info", type: "recorder/info",
}); });

View File

@@ -52,7 +52,8 @@ export type Selector =
| TTSSelector | TTSSelector
| TTSVoiceSelector | TTSVoiceSelector
| UiActionSelector | UiActionSelector
| UiColorSelector; | UiColorSelector
| UserSelector;
export interface ActionSelector { export interface ActionSelector {
action: { action: {
@@ -392,6 +393,13 @@ export interface UiColorSelector {
ui_color: {} | null; ui_color: {} | null;
} }
export interface UserSelector {
user: {
multiple?: boolean;
include_system?: boolean;
} | null;
}
export const expandAreaTarget = ( export const expandAreaTarget = (
hass: HomeAssistant, hass: HomeAssistant,
areaId: string, areaId: string,

View File

@@ -15,7 +15,7 @@ export const enum TodoItemStatus {
} }
export interface TodoItem { export interface TodoItem {
uid?: string; uid: string;
summary: string; summary: string;
status: TodoItemStatus; status: TodoItemStatus;
} }
@@ -95,11 +95,11 @@ export const moveItem = (
hass: HomeAssistant, hass: HomeAssistant,
entity_id: string, entity_id: string,
uid: string, uid: string,
pos: number previous_uid: string | undefined
): Promise<void> => ): Promise<void> =>
hass.callWS({ hass.callWS({
type: "todo/item/move", type: "todo/item/move",
entity_id, entity_id,
uid, uid,
pos, previous_uid,
}); });

View File

@@ -13,12 +13,9 @@ import {
import { loadTokens, saveTokens } from "../common/auth/token_storage"; import { loadTokens, saveTokens } from "../common/auth/token_storage";
import { hassUrl } from "../data/auth"; import { hassUrl } from "../data/auth";
import { isExternal } from "../data/external"; import { isExternal } from "../data/external";
import { getRecorderInfo } from "../data/recorder";
import { subscribeFrontendUserData } from "../data/frontend"; import { subscribeFrontendUserData } from "../data/frontend";
import { import { fetchConfig, fetchResources } from "../data/lovelace";
fetchConfig,
fetchResources,
WindowWithLovelaceProm,
} from "../data/lovelace";
import { subscribePanels } from "../data/ws-panels"; import { subscribePanels } from "../data/ws-panels";
import { subscribeThemes } from "../data/ws-themes"; import { subscribeThemes } from "../data/ws-themes";
import { subscribeRepairsIssueRegistry } from "../data/repairs"; import { subscribeRepairsIssueRegistry } from "../data/repairs";
@@ -27,6 +24,7 @@ import type { ExternalAuth } from "../external_app/external_auth";
import "../resources/array.flat.polyfill"; import "../resources/array.flat.polyfill";
import "../resources/safari-14-attachshadow-patch"; import "../resources/safari-14-attachshadow-patch";
import { MAIN_WINDOW_NAME } from "../data/main_window"; import { MAIN_WINDOW_NAME } from "../data/main_window";
import { WindowWithPreloads } from "../data/preloads";
window.name = MAIN_WINDOW_NAME; window.name = MAIN_WINDOW_NAME;
(window as any).frontendVersion = __VERSION__; (window as any).frontendVersion = __VERSION__;
@@ -124,12 +122,14 @@ window.hassConnection.then(({ conn }) => {
subscribeFrontendUserData(conn, "core", noop); subscribeFrontendUserData(conn, "core", noop);
subscribeRepairsIssueRegistry(conn, noop); subscribeRepairsIssueRegistry(conn, noop);
const preloadWindow = window as WindowWithPreloads;
preloadWindow.recorderInfoProm = getRecorderInfo(conn);
if (location.pathname === "/" || location.pathname.startsWith("/lovelace/")) { if (location.pathname === "/" || location.pathname.startsWith("/lovelace/")) {
const llWindow = window as WindowWithLovelaceProm; preloadWindow.llConfProm = fetchConfig(conn, null, false);
llWindow.llConfProm = fetchConfig(conn, null, false); preloadWindow.llConfProm.catch(() => {
llWindow.llConfProm.catch(() => {
// Ignore it, it is handled by Lovelace panel. // Ignore it, it is handled by Lovelace panel.
}); });
llWindow.llResProm = fetchResources(conn); preloadWindow.llResProm = fetchResources(conn);
} }
}); });

View File

@@ -3,11 +3,12 @@ import { customElement, state } from "lit/decorators";
import { isNavigationClick } from "../common/dom/is-navigation-click"; import { isNavigationClick } from "../common/dom/is-navigation-click";
import { navigate } from "../common/navigate"; import { navigate } from "../common/navigate";
import { getStorageDefaultPanelUrlPath } from "../data/panel"; import { getStorageDefaultPanelUrlPath } from "../data/panel";
import { getRecorderInfo } from "../data/recorder"; import { getRecorderInfo, RecorderInfo } from "../data/recorder";
import "../resources/custom-card-support"; import "../resources/custom-card-support";
import { HassElement } from "../state/hass-element"; import { HassElement } from "../state/hass-element";
import QuickBarMixin from "../state/quick-bar-mixin"; import QuickBarMixin from "../state/quick-bar-mixin";
import { HomeAssistant, Route } from "../types"; import { HomeAssistant, Route } from "../types";
import { WindowWithPreloads } from "../data/preloads";
import { storeState } from "../util/ha-pref-storage"; import { storeState } from "../util/ha-pref-storage";
import { import {
renderLaunchScreenInfoBox, renderLaunchScreenInfoBox,
@@ -204,7 +205,15 @@ export class HomeAssistantAppEl extends QuickBarMixin(HassElement) {
protected async checkDataBaseMigration() { protected async checkDataBaseMigration() {
if (this.hass?.config?.components.includes("recorder")) { if (this.hass?.config?.components.includes("recorder")) {
const info = await getRecorderInfo(this.hass); let recorderInfoProm: Promise<RecorderInfo> | undefined;
const preloadWindow = window as WindowWithPreloads;
// On first load, we speed up loading page by having recorderInfoProm ready
if (preloadWindow.recorderInfoProm) {
recorderInfoProm = preloadWindow.recorderInfoProm;
preloadWindow.recorderInfoProm = undefined;
}
const info = await (recorderInfoProm ||
getRecorderInfo(this.hass.connection));
this._databaseMigration = this._databaseMigration =
info.migration_in_progress && !info.migration_is_live; info.migration_in_progress && !info.migration_is_live;
if (this._databaseMigration) { if (this._databaseMigration) {

View File

@@ -200,6 +200,8 @@ export class EntityRegistrySettingsEditor extends LitElement {
this._name = this.entry.name || ""; this._name = this.entry.name || "";
this._icon = this.entry.icon || ""; this._icon = this.entry.icon || "";
this._deviceClass =
this.entry.device_class || this.entry.original_device_class;
this._origEntityId = this.entry.entity_id; this._origEntityId = this.entry.entity_id;
this._areaId = this.entry.area_id; this._areaId = this.entry.area_id;
this._entityId = this.entry.entity_id; this._entityId = this.entry.entity_id;

View File

@@ -93,6 +93,20 @@ class HaScheduleForm extends LitElement {
} }
} }
public disconnectedCallback(): void {
super.disconnectedCallback();
this.calendar?.destroy();
this.calendar = undefined;
this.renderRoot.querySelector("style[data-fullcalendar]")?.remove();
}
public connectedCallback(): void {
super.connectedCallback();
if (this.hasUpdated && !this.calendar) {
this.setupCalendar();
}
}
public focus() { public focus() {
this.updateComplete.then( this.updateComplete.then(
() => () =>
@@ -165,6 +179,10 @@ class HaScheduleForm extends LitElement {
} }
protected firstUpdated(): void { protected firstUpdated(): void {
this.setupCalendar();
}
private setupCalendar(): void {
const config: CalendarOptions = { const config: CalendarOptions = {
...defaultFullCalendarConfig, ...defaultFullCalendarConfig,
locale: this.hass.language, locale: this.hass.language,

View File

@@ -1,5 +1,12 @@
import { mdiPlus } from "@mdi/js"; import { mdiPlus } from "@mdi/js";
import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoize from "memoize-one"; import memoize from "memoize-one";
import { stringCompare } from "../../../../common/string/compare"; import { stringCompare } from "../../../../common/string/compare";
@@ -7,6 +14,7 @@ import {
DataTableColumnContainer, DataTableColumnContainer,
RowClickedEvent, RowClickedEvent,
} from "../../../../components/data-table/ha-data-table"; } from "../../../../components/data-table/ha-data-table";
import "../../../../components/ha-card";
import "../../../../components/ha-fab"; import "../../../../components/ha-fab";
import "../../../../components/ha-svg-icon"; import "../../../../components/ha-svg-icon";
import { import {
@@ -21,7 +29,9 @@ import {
showConfirmationDialog, showConfirmationDialog,
} from "../../../../dialogs/generic/show-dialog-box"; } from "../../../../dialogs/generic/show-dialog-box";
import "../../../../layouts/hass-loading-screen"; import "../../../../layouts/hass-loading-screen";
import "../../../../layouts/hass-subpage";
import "../../../../layouts/hass-tabs-subpage-data-table"; import "../../../../layouts/hass-tabs-subpage-data-table";
import { haStyle } from "../../../../resources/styles";
import { HomeAssistant, Route } from "../../../../types"; import { HomeAssistant, Route } from "../../../../types";
import { loadLovelaceResources } from "../../../lovelace/common/load-resources"; import { loadLovelaceResources } from "../../../lovelace/common/load-resources";
import { lovelaceTabs } from "../ha-config-lovelace"; import { lovelaceTabs } from "../ha-config-lovelace";
@@ -72,6 +82,36 @@ export class HaConfigLovelaceRescources extends LitElement {
return html` <hass-loading-screen></hass-loading-screen> `; return html` <hass-loading-screen></hass-loading-screen> `;
} }
if (this.hass.config.safe_mode) {
return html`
<hass-subpage
.hass=${this.hass}
.narrow=${this.narrow}
back-path="/config"
.header=${this.hass.localize(
"ui.panel.config.lovelace.resources.caption"
)}
>
<div class="content">
<ha-card outlined>
<div class="card-content">
<h2>
${this.hass.localize(
"ui.panel.config.lovelace.resources.unavailable"
)}
</h2>
<p>
${this.hass.localize(
"ui.panel.config.lovelace.resources.unavailable_safe_mode"
)}
</p>
</div>
</ha-card>
</div>
</hass-subpage>
`;
}
return html` return html`
<hass-tabs-subpage-data-table <hass-tabs-subpage-data-table
.hass=${this.hass} .hass=${this.hass}
@@ -192,4 +232,24 @@ export class HaConfigLovelaceRescources extends LitElement {
}, },
}); });
} }
static get styles(): CSSResultGroup {
return [
haStyle,
css`
.content {
padding: 28px 20px 0;
max-width: 1040px;
margin: 0 auto;
}
h2 {
margin-top: 0;
margin-bottom: 12px;
}
p {
margin: 0;
}
`,
];
}
} }

View File

@@ -125,7 +125,7 @@ class HaPanelDevState extends LitElement {
autofocus autofocus
.hass=${this.hass} .hass=${this.hass}
.value=${this._entityId} .value=${this._entityId}
@change=${this._entityIdChanged} @value-changed=${this._entityIdChanged}
allow-custom-entity allow-custom-entity
item-label-path="entity_id" item-label-path="entity_id"
></ha-entity-picker> ></ha-entity-picker>
@@ -347,7 +347,8 @@ class HaPanelDevState extends LitElement {
ev.preventDefault(); ev.preventDefault();
} }
private _entityIdChanged() { private _entityIdChanged(ev: CustomEvent) {
this._entityId = ev.detail.value;
if (!this._entityId) { if (!this._entityId) {
this._entity = undefined; this._entity = undefined;
this._state = ""; this._state = "";

View File

@@ -48,6 +48,9 @@ class PanelEnergy extends LitElement {
if (oldHass?.locale !== this.hass.locale) { if (oldHass?.locale !== this.hass.locale) {
this._setLovelace(); this._setLovelace();
} }
if (oldHass && oldHass.localize !== this.hass.localize) {
this._reloadView();
}
} }
protected render(): TemplateResult { protected render(): TemplateResult {

View File

@@ -21,6 +21,7 @@ import "../../../components/ha-checkbox";
import "../../../components/ha-list-item"; import "../../../components/ha-list-item";
import "../../../components/ha-select"; import "../../../components/ha-select";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
import "../../../components/ha-icon-button";
import "../../../components/ha-textfield"; import "../../../components/ha-textfield";
import type { HaTextField } from "../../../components/ha-textfield"; import type { HaTextField } from "../../../components/ha-textfield";
import { import {
@@ -37,8 +38,10 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import type { SortableInstance } from "../../../resources/sortable"; import type { SortableInstance } from "../../../resources/sortable";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { findEntities } from "../common/find-entities"; import { findEntities } from "../common/find-entities";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { LovelaceCard, LovelaceCardEditor } from "../types"; import { LovelaceCard, LovelaceCardEditor } from "../types";
import { TodoListCardConfig } from "./types"; import { TodoListCardConfig } from "./types";
import { isUnavailableState } from "../../../data/entity";
@customElement("hui-todo-list-card") @customElement("hui-todo-list-card")
export class HuiTodoListCard export class HuiTodoListCard
@@ -74,7 +77,7 @@ export class HuiTodoListCard
@state() private _entityId?: string; @state() private _entityId?: string;
@state() private _items?: Record<string, TodoItem>; @state() private _items?: TodoItem[];
@state() private _reordering = false; @state() private _reordering = false;
@@ -104,22 +107,16 @@ export class HuiTodoListCard
return undefined; return undefined;
} }
private _getCheckedItems = memoizeOne( private _getCheckedItems = memoizeOne((items?: TodoItem[]): TodoItem[] =>
(items?: Record<string, TodoItem>): TodoItem[] => items
items ? items.filter((item) => item.status === TodoItemStatus.Completed)
? Object.values(items).filter( : []
(item) => item.status === TodoItemStatus.Completed
)
: []
); );
private _getUncheckedItems = memoizeOne( private _getUncheckedItems = memoizeOne((items?: TodoItem[]): TodoItem[] =>
(items?: Record<string, TodoItem>): TodoItem[] => items
items ? items.filter((item) => item.status === TodoItemStatus.NeedsAction)
? Object.values(items).filter( : []
(item) => item.status === TodoItemStatus.NeedsAction
)
: []
); );
public willUpdate( public willUpdate(
@@ -138,10 +135,14 @@ export class HuiTodoListCard
public hassSubscribe(): Promise<UnsubscribeFunc>[] { public hassSubscribe(): Promise<UnsubscribeFunc>[] {
return [ return [
this.hass!.connection.subscribeEvents( this.hass!.connection.subscribeEvents(() => {
() => this._fetchData(), if (
"shopping_list_updated" this._entityId &&
), this.hass!.entities[this._entityId]?.platform === "shopping_list"
) {
this._fetchData();
}
}, "shopping_list_updated"),
]; ];
} }
@@ -162,6 +163,15 @@ export class HuiTodoListCard
) { ) {
applyThemesOnElement(this, this.hass.themes, this._config.theme); applyThemesOnElement(this, this.hass.themes, this._config.theme);
} }
if (
this._entityId &&
oldHass &&
oldHass.states[this._entityId] !== this.hass.states[this._entityId] &&
this.hass.entities[this._entityId]?.platform !== "shopping_list"
) {
this._fetchData();
}
} }
protected render() { protected render() {
@@ -169,6 +179,18 @@ export class HuiTodoListCard
return nothing; return nothing;
} }
const stateObj = this.hass.states[this._entityId];
if (!stateObj) {
return html`
<hui-warning>
${createEntityNotFoundWarning(this.hass, this._entityId)}
</hui-warning>
`;
}
const unavailable = isUnavailableState(stateObj.state);
const checkedItems = this._getCheckedItems(this._items); const checkedItems = this._getCheckedItems(this._items);
const uncheckedItems = this._getUncheckedItems(this._items); const uncheckedItems = this._getUncheckedItems(this._items);
@@ -182,39 +204,44 @@ export class HuiTodoListCard
<div class="addRow"> <div class="addRow">
${this.todoListSupportsFeature(TodoListEntityFeature.CREATE_TODO_ITEM) ${this.todoListSupportsFeature(TodoListEntityFeature.CREATE_TODO_ITEM)
? html` ? html`
<ha-svg-icon <ha-icon-button
class="addButton" class="addButton"
.path=${mdiPlus} .path=${mdiPlus}
.title=${this.hass!.localize( .title=${this.hass!.localize(
"ui.panel.lovelace.cards.todo-list.add_item" "ui.panel.lovelace.cards.todo-list.add_item"
)} )}
.disabled=${unavailable}
@click=${this._addItem} @click=${this._addItem}
> >
</ha-svg-icon> </ha-icon-button>
<ha-textfield <ha-textfield
class="addBox" class="addBox"
.placeholder=${this.hass!.localize( .placeholder=${this.hass!.localize(
"ui.panel.lovelace.cards.todo-list.add_item" "ui.panel.lovelace.cards.todo-list.add_item"
)} )}
@keydown=${this._addKeyPress} @keydown=${this._addKeyPress}
.disabled=${unavailable}
></ha-textfield> ></ha-textfield>
` `
: nothing} : nothing}
${this.todoListSupportsFeature(TodoListEntityFeature.MOVE_TODO_ITEM) ${this.todoListSupportsFeature(TodoListEntityFeature.MOVE_TODO_ITEM)
? html` ? html`
<ha-svg-icon <ha-icon-button
class="reorderButton" class="reorderButton"
.path=${mdiSort} .path=${mdiSort}
.title=${this.hass!.localize( .title=${this.hass!.localize(
"ui.panel.lovelace.cards.todo-list.reorder_items" "ui.panel.lovelace.cards.todo-list.reorder_items"
)} )}
@click=${this._toggleReorder} @click=${this._toggleReorder}
.disabled=${unavailable}
> >
</ha-svg-icon> </ha-icon-button>
` `
: nothing} : nothing}
</div> </div>
<div id="unchecked">${this._renderItems(uncheckedItems)}</div> <div id="unchecked">
${this._renderItems(uncheckedItems, unavailable)}
</div>
${checkedItems.length ${checkedItems.length
? html` ? html`
<div class="divider"></div> <div class="divider"></div>
@@ -235,6 +262,7 @@ export class HuiTodoListCard
"ui.panel.lovelace.cards.todo-list.clear_items" "ui.panel.lovelace.cards.todo-list.clear_items"
)} )}
@click=${this._clearCompletedItems} @click=${this._clearCompletedItems}
.disabled=${unavailable}
> >
</ha-svg-icon>` </ha-svg-icon>`
: nothing} : nothing}
@@ -247,16 +275,18 @@ export class HuiTodoListCard
${this.todoListSupportsFeature( ${this.todoListSupportsFeature(
TodoListEntityFeature.UPDATE_TODO_ITEM TodoListEntityFeature.UPDATE_TODO_ITEM
) )
? html` <ha-checkbox ? html`<ha-checkbox
tabindex="0" tabindex="0"
.checked=${item.status === TodoItemStatus.Completed} .checked=${item.status === TodoItemStatus.Completed}
.itemId=${item.uid} .itemId=${item.uid}
@change=${this._completeItem} @change=${this._completeItem}
.disabled=${unavailable}
></ha-checkbox>` ></ha-checkbox>`
: nothing} : nothing}
<ha-textfield <ha-textfield
class="item" class="item"
.disabled=${!this.todoListSupportsFeature( .disabled=${unavailable ||
!this.todoListSupportsFeature(
TodoListEntityFeature.UPDATE_TODO_ITEM TodoListEntityFeature.UPDATE_TODO_ITEM
)} )}
.value=${item.summary} .value=${item.summary}
@@ -272,7 +302,7 @@ export class HuiTodoListCard
`; `;
} }
private _renderItems(items: TodoItem[]) { private _renderItems(items: TodoItem[], unavailable = false) {
return html` return html`
${repeat( ${repeat(
items, items,
@@ -282,16 +312,18 @@ export class HuiTodoListCard
${this.todoListSupportsFeature( ${this.todoListSupportsFeature(
TodoListEntityFeature.UPDATE_TODO_ITEM TodoListEntityFeature.UPDATE_TODO_ITEM
) )
? html` <ha-checkbox ? html`<ha-checkbox
tabindex="0" tabindex="0"
.checked=${item.status === TodoItemStatus.Completed} .checked=${item.status === TodoItemStatus.Completed}
.itemId=${item.uid} .itemId=${item.uid}
.disabled=${unavailable}
@change=${this._completeItem} @change=${this._completeItem}
></ha-checkbox>` ></ha-checkbox>`
: nothing} : nothing}
<ha-textfield <ha-textfield
class="item" class="item"
.disabled=${!this.todoListSupportsFeature( .disabled=${unavailable ||
!this.todoListSupportsFeature(
TodoListEntityFeature.UPDATE_TODO_ITEM TodoListEntityFeature.UPDATE_TODO_ITEM
)} )}
.value=${item.summary} .value=${item.summary}
@@ -325,16 +357,21 @@ export class HuiTodoListCard
if (!this.hass || !this._entityId) { if (!this.hass || !this._entityId) {
return; return;
} }
const items = await fetchItems(this.hass!, this._entityId!); if (!(this._entityId in this.hass.states)) {
const records: Record<string, TodoItem> = {}; return;
items.forEach((item) => { }
records[item.uid!] = item; this._items = await fetchItems(this.hass!, this._entityId!);
}); }
this._items = records;
private _getItem(itemId: string) {
return this._items?.find((item) => item.uid === itemId);
} }
private _completeItem(ev): void { private _completeItem(ev): void {
const item = this._items![ev.target.itemId]; const item = this._getItem(ev.target.itemId);
if (!item) {
return;
}
updateItem(this.hass!, this._entityId!, { updateItem(this.hass!, this._entityId!, {
...item, ...item,
status: ev.target.checked status: ev.target.checked
@@ -346,7 +383,10 @@ export class HuiTodoListCard
private _saveEdit(ev): void { private _saveEdit(ev): void {
// If name is not empty, update the item otherwise remove it // If name is not empty, update the item otherwise remove it
if (ev.target.value) { if (ev.target.value) {
const item = this._items![ev.target.itemId]; const item = this._getItem(ev.target.itemId);
if (!item) {
return;
}
updateItem(this.hass!, this._entityId!, { updateItem(this.hass!, this._entityId!, {
...item, ...item,
summary: ev.target.value, summary: ev.target.value,
@@ -368,7 +408,7 @@ export class HuiTodoListCard
} }
const deleteActions: Array<Promise<any>> = []; const deleteActions: Array<Promise<any>> = [];
this._getCheckedItems(this._items).forEach((item: TodoItem) => { this._getCheckedItems(this._items).forEach((item: TodoItem) => {
deleteActions.push(deleteItem(this.hass!, this._entityId!, item.uid!)); deleteActions.push(deleteItem(this.hass!, this._entityId!, item.uid));
}); });
await Promise.all(deleteActions).finally(() => this._fetchData()); await Promise.all(deleteActions).finally(() => this._fetchData());
} }
@@ -438,11 +478,37 @@ export class HuiTodoListCard
}); });
} }
private async _moveItem(oldIndex, newIndex) { private async _moveItem(oldIndex: number, newIndex: number) {
const item = this._getUncheckedItems(this._items)[oldIndex]; const uncheckedItems = this._getUncheckedItems(this._items);
await moveItem(this.hass!, this._entityId!, item.uid!, newIndex).finally( const item = uncheckedItems[oldIndex];
() => this._fetchData() let prevItem: TodoItem | undefined;
); if (newIndex > 0) {
if (newIndex < oldIndex) {
prevItem = uncheckedItems[newIndex - 1];
} else {
prevItem = uncheckedItems[newIndex];
}
}
// Optimistic change
const itemIndex = this._items!.findIndex((itm) => itm.uid === item.uid);
this._items!.splice(itemIndex, 1);
if (newIndex === 0) {
this._items!.unshift(item);
} else {
const prevIndex = this._items!.findIndex(
(itm) => itm.uid === prevItem!.uid
);
this._items!.splice(prevIndex + 1, 0, item);
}
this._items = [...this._items!];
await moveItem(
this.hass!,
this._entityId!,
item.uid,
prevItem?.uid
).finally(() => this._fetchData());
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
@@ -470,16 +536,14 @@ export class HuiTodoListCard
} }
.addButton { .addButton {
padding-right: 16px; margin-left: -12px;
padding-inline-end: 16px; margin-inline-start: -12px;
cursor: pointer;
direction: var(--direction); direction: var(--direction);
} }
.reorderButton { .reorderButton {
padding-left: 16px; margin-right: -12px;
padding-inline-start: 16px; margin-inline-end: -12px;
cursor: pointer;
direction: var(--direction); direction: var(--direction);
} }

View File

@@ -10,10 +10,6 @@ export const loadLovelaceResources = (
resources: NonNullable<LovelaceResource[]>, resources: NonNullable<LovelaceResource[]>,
hass: HomeAssistant hass: HomeAssistant
) => { ) => {
// Don't load ressources on safe mode
if (hass.config.safe_mode) {
return;
}
resources.forEach((resource) => { resources.forEach((resource) => {
const normalizedUrl = new URL( const normalizedUrl = new URL(
resource.url, resource.url,

View File

@@ -65,7 +65,7 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) {
@state() _endDate?: Date; @state() _endDate?: Date;
@state() private _ranges?: DateRangePickerRanges; @state() private _ranges: DateRangePickerRanges = {};
@state() private _compare = false; @state() private _compare = false;

View File

@@ -48,6 +48,7 @@ export class HaCardConditionNumericState extends LitElement {
name: "above", name: "above",
selector: { selector: {
number: { number: {
step: "any",
mode: "box", mode: "box",
unit_of_measurement: stateObj?.attributes.unit_of_measurement, unit_of_measurement: stateObj?.attributes.unit_of_measurement,
}, },
@@ -57,6 +58,7 @@ export class HaCardConditionNumericState extends LitElement {
name: "below", name: "below",
selector: { selector: {
number: { number: {
step: "any",
mode: "box", mode: "box",
unit_of_measurement: stateObj?.attributes.unit_of_measurement, unit_of_measurement: stateObj?.attributes.unit_of_measurement,
}, },

View File

@@ -186,11 +186,15 @@ export class HuiTileCardEditor
multiple: true, multiple: true,
options: [ options: [
{ {
label: "State", label: localize(
`ui.panel.lovelace.editor.card.tile.state_content_options.state`
),
value: "state", value: "state",
}, },
{ {
label: "Last changed", label: localize(
`ui.panel.lovelace.editor.card.tile.state_content_options.last-changed`
),
value: "last-changed", value: "last-changed",
}, },
...Object.keys(stateObj?.attributes ?? {}) ...Object.keys(stateObj?.attributes ?? {})

View File

@@ -15,8 +15,8 @@ import {
LovelaceConfig, LovelaceConfig,
saveConfig, saveConfig,
subscribeLovelaceUpdates, subscribeLovelaceUpdates,
WindowWithLovelaceProm,
} from "../../data/lovelace"; } from "../../data/lovelace";
import { WindowWithPreloads } from "../../data/preloads";
import "../../layouts/hass-error-screen"; import "../../layouts/hass-error-screen";
import "../../layouts/hass-loading-screen"; import "../../layouts/hass-loading-screen";
import { HomeAssistant, PanelInfo, Route } from "../../types"; import { HomeAssistant, PanelInfo, Route } from "../../types";
@@ -220,18 +220,18 @@ export class LovelacePanel extends LitElement {
let rawConf: LovelaceConfig | undefined; let rawConf: LovelaceConfig | undefined;
let confMode: Lovelace["mode"] = this.panel!.config.mode; let confMode: Lovelace["mode"] = this.panel!.config.mode;
let confProm: Promise<LovelaceConfig> | undefined; let confProm: Promise<LovelaceConfig> | undefined;
const llWindow = window as WindowWithLovelaceProm; const preloadWindow = window as WindowWithPreloads;
// On first load, we speed up loading page by having LL promise ready // On first load, we speed up loading page by having LL promise ready
if (llWindow.llConfProm) { if (preloadWindow.llConfProm) {
confProm = llWindow.llConfProm; confProm = preloadWindow.llConfProm;
llWindow.llConfProm = undefined; preloadWindow.llConfProm = undefined;
} }
if (!resourcesLoaded) { if (!resourcesLoaded) {
resourcesLoaded = true; resourcesLoaded = true;
const resources = await (llWindow.llResProm || (preloadWindow.llResProm || fetchResources(this.hass!.connection)).then(
fetchResources(this.hass!.connection)); (resources) => loadLovelaceResources(resources, this.hass!)
loadLovelaceResources(resources, this.hass!); );
} }
if (this.urlPath !== null || !confProm) { if (this.urlPath !== null || !confProm) {

View File

@@ -56,6 +56,7 @@ import {
BrowserMediaPlayer, BrowserMediaPlayer,
ERR_UNSUPPORTED_MEDIA, ERR_UNSUPPORTED_MEDIA,
} from "./browser-media-player"; } from "./browser-media-player";
import { debounce } from "../../common/util/debounce";
declare global { declare global {
interface HASSDomEvents { interface HASSDomEvents {
@@ -118,8 +119,14 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
public showResolvingNewMediaPicked() { public showResolvingNewMediaPicked() {
this._tearDownBrowserPlayer(); this._tearDownBrowserPlayer();
this._newMediaExpected = true; this._newMediaExpected = true;
// Sometimes the state does not update when playing media, like with TTS, so we wait max 2 secs and then stop waiting
this._debouncedResetMediaExpected();
} }
private _debouncedResetMediaExpected = debounce(() => {
this._newMediaExpected = false;
}, 2000);
public hideResolvingNewMediaPicked() { public hideResolvingNewMediaPicked() {
this._newMediaExpected = false; this._newMediaExpected = false;
} }
@@ -154,7 +161,7 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
protected render() { protected render() {
if (this._newMediaExpected) { if (this._newMediaExpected) {
return html` return html`
<div class="controls-progress"> <div class="controls-progress buffering">
${until( ${until(
// Only show spinner after 500ms // Only show spinner after 500ms
new Promise((resolve) => { new Promise((resolve) => {
@@ -240,9 +247,13 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
</span> </span>
</div> </div>
</div> </div>
<div class="controls-progress"> <div
class="controls-progress ${stateObj.state === "buffering"
? "buffering"
: ""}"
>
${stateObj.state === "buffering" ${stateObj.state === "buffering"
? html` <ha-circular-progress active></ha-circular-progress> ` ? html`<ha-circular-progress active></ha-circular-progress>`
: html` : html`
<div class="controls"> <div class="controls">
${controls === undefined ${controls === undefined
@@ -541,7 +552,8 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
return css` return css`
:host { :host {
display: flex; display: flex;
min-height: 100px; height: 100px;
box-sizing: border-box;
background: var( background: var(
--ha-card-background, --ha-card-background,
var(--card-background-color, white) var(--card-background-color, white)
@@ -627,12 +639,11 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
} }
img { img {
max-height: 100px; height: 100%;
max-width: 100px;
} }
.app img { .app img {
max-height: 68px; height: 68px;
margin: 16px 0 16px 16px; margin: 16px 0 16px 16px;
} }
@@ -641,8 +652,7 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
} }
:host([narrow]) { :host([narrow]) {
min-height: 56px; height: 57px;
max-height: 56px;
} }
:host([narrow]) .controls-progress { :host([narrow]) .controls-progress {
@@ -650,6 +660,10 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
min-width: 48px; min-width: 48px;
} }
:host([narrow]) .controls-progress.buffering {
flex: 1;
}
:host([narrow]) .media-info { :host([narrow]) .media-info {
padding-left: 8px; padding-left: 8px;
} }
@@ -672,16 +686,6 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
justify-content: flex-end; justify-content: flex-end;
} }
:host([narrow]) img {
max-height: 56px;
max-width: 56px;
}
:host([narrow]) .blank-image {
height: 56px;
width: 56px;
}
:host([narrow]) mwc-linear-progress { :host([narrow]) mwc-linear-progress {
padding: 0; padding: 0;
position: absolute; position: absolute;

View File

@@ -286,7 +286,7 @@ class PanelMediaBrowser extends LitElement {
} }
:host([narrow]) ha-media-player-browse { :host([narrow]) ha-media-player-browse {
height: calc(100vh - (80px + var(--header-height))); height: calc(100vh - (57px + var(--header-height)));
} }
ha-bar-media-player { ha-bar-media-player {

View File

@@ -2,8 +2,10 @@ import { ResizeController } from "@lit-labs/observers/resize-controller";
import "@material/mwc-list"; import "@material/mwc-list";
import { import {
mdiChevronDown, mdiChevronDown,
mdiCommentProcessingOutline,
mdiDelete,
mdiDotsVertical, mdiDotsVertical,
mdiMicrophone, mdiInformationOutline,
mdiPlus, mdiPlus,
} from "@mdi/js"; } from "@mdi/js";
import { import {
@@ -19,6 +21,7 @@ import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../common/config/is_component_loaded";
import { storage } from "../../common/decorators/storage"; import { storage } from "../../common/decorators/storage";
import { fireEvent } from "../../common/dom/fire_event";
import { computeStateName } from "../../common/entity/compute_state_name"; import { computeStateName } from "../../common/entity/compute_state_name";
import "../../components/ha-button"; import "../../components/ha-button";
import "../../components/ha-icon-button"; import "../../components/ha-icon-button";
@@ -27,15 +30,21 @@ import "../../components/ha-menu-button";
import "../../components/ha-state-icon"; import "../../components/ha-state-icon";
import "../../components/ha-svg-icon"; import "../../components/ha-svg-icon";
import "../../components/ha-two-pane-top-app-bar-fixed"; import "../../components/ha-two-pane-top-app-bar-fixed";
import { deleteConfigEntry } from "../../data/config_entries";
import { getExtendedEntityRegistryEntry } from "../../data/entity_registry";
import { fetchIntegrationManifest } from "../../data/integration";
import { getTodoLists } from "../../data/todo"; import { getTodoLists } from "../../data/todo";
import { showConfigFlowDialog } from "../../dialogs/config-flow/show-dialog-config-flow";
import {
showAlertDialog,
showConfirmationDialog,
} from "../../dialogs/generic/show-dialog-box";
import { showVoiceCommandDialog } from "../../dialogs/voice-command-dialog/show-ha-voice-command-dialog"; import { showVoiceCommandDialog } from "../../dialogs/voice-command-dialog/show-ha-voice-command-dialog";
import { haStyle } from "../../resources/styles"; import { haStyle } from "../../resources/styles";
import { HomeAssistant } from "../../types"; import { HomeAssistant } from "../../types";
import { HuiErrorCard } from "../lovelace/cards/hui-error-card"; import { HuiErrorCard } from "../lovelace/cards/hui-error-card";
import { createCardElement } from "../lovelace/create-element/create-card-element"; import { createCardElement } from "../lovelace/create-element/create-card-element";
import { LovelaceCard } from "../lovelace/types"; import { LovelaceCard } from "../lovelace/types";
import { fetchIntegrationManifest } from "../../data/integration";
import { showConfigFlowDialog } from "../../dialogs/config-flow/show-dialog-config-flow";
@customElement("ha-panel-todo") @customElement("ha-panel-todo")
class PanelTodo extends LitElement { class PanelTodo extends LitElement {
@@ -92,6 +101,10 @@ class PanelTodo extends LitElement {
protected willUpdate(changedProperties: PropertyValues): void { protected willUpdate(changedProperties: PropertyValues): void {
super.willUpdate(changedProperties); super.willUpdate(changedProperties);
if (!this.hasUpdated) {
this.hass.loadFragmentTranslation("lovelace");
}
if (!this.hasUpdated && !this._entityId) { if (!this.hasUpdated && !this._entityId) {
this._entityId = getTodoLists(this.hass)[0]?.entity_id; this._entityId = getTodoLists(this.hass)[0]?.entity_id;
} else if (!this.hasUpdated) { } else if (!this.hasUpdated) {
@@ -124,6 +137,9 @@ class PanelTodo extends LitElement {
} }
protected render(): TemplateResult { protected render(): TemplateResult {
const entityRegistryEntry = this._entityId
? this.hass.entities[this._entityId]
: undefined;
const showPane = this._showPaneController.value ?? !this.narrow; const showPane = this._showPaneController.value ?? !this.narrow;
const listItems = getTodoLists(this.hass).map( const listItems = getTodoLists(this.hass).map(
(list) => (list) =>
@@ -157,9 +173,13 @@ class PanelTodo extends LitElement {
.x=${this.mobile ? 0 : undefined} .x=${this.mobile ? 0 : undefined}
> >
<ha-button slot="trigger"> <ha-button slot="trigger">
${this._entityId <div>
? computeStateName(this.hass.states[this._entityId]) ${this._entityId
: ""} ? this._entityId in this.hass.states
? computeStateName(this.hass.states[this._entityId])
: this._entityId
: ""}
</div>
<ha-svg-icon <ha-svg-icon
slot="trailingIcon" slot="trailingIcon"
.path=${mdiChevronDown} .path=${mdiChevronDown}
@@ -172,7 +192,7 @@ class PanelTodo extends LitElement {
${this.hass.localize("ui.panel.todo.create_list")} ${this.hass.localize("ui.panel.todo.create_list")}
</ha-list-item> </ha-list-item>
</ha-button-menu>` </ha-button-menu>`
: "Lists"} : this.hass.localize("panel.todo")}
</div> </div>
<mwc-list slot="pane" activatable>${listItems}</mwc-list> <mwc-list slot="pane" activatable>${listItems}</mwc-list>
<ha-list-item graphic="icon" slot="pane-footer" @click=${this._addList}> <ha-list-item graphic="icon" slot="pane-footer" @click=${this._addList}>
@@ -188,13 +208,37 @@ class PanelTodo extends LitElement {
${this._conversation(this.hass.config.components) ${this._conversation(this.hass.config.components)
? html`<ha-list-item ? html`<ha-list-item
graphic="icon" graphic="icon"
@click=${this._showVoiceCommandDialog} @click=${this._showMoreInfoDialog}
.disabled=${!this._entityId}
> >
<ha-svg-icon .path=${mdiMicrophone} slot="graphic"> <ha-svg-icon .path=${mdiInformationOutline} slot="graphic">
</ha-svg-icon> </ha-svg-icon>
${this.hass.localize("ui.panel.todo.start_conversation")} ${this.hass.localize("ui.panel.todo.information")}
</ha-list-item>` </ha-list-item>`
: nothing} : nothing}
<li divider role="separator"></li>
<ha-list-item graphic="icon" @click=${this._showVoiceCommandDialog}>
<ha-svg-icon .path=${mdiCommentProcessingOutline} slot="graphic">
</ha-svg-icon>
${this.hass.localize("ui.panel.todo.assist")}
</ha-list-item>
${entityRegistryEntry?.platform === "local_todo"
? html` <li divider role="separator"></li>
<ha-list-item
graphic="icon"
@click=${this._deleteList}
class="warning"
.disabled=${!this._entityId}
>
<ha-svg-icon
.path=${mdiDelete}
slot="graphic"
class="warning"
>
</ha-svg-icon>
${this.hass.localize("ui.panel.todo.delete_list")}
</ha-list-item>`
: nothing}
</ha-button-menu> </ha-button-menu>
<div id="columns"> <div id="columns">
<div class="column">${this._card}</div> <div class="column">${this._card}</div>
@@ -215,6 +259,60 @@ class PanelTodo extends LitElement {
}); });
} }
private _showMoreInfoDialog(): void {
if (!this._entityId) {
return;
}
fireEvent(this, "hass-more-info", { entityId: this._entityId });
}
private async _deleteList(): Promise<void> {
if (!this._entityId) {
return;
}
const entityRegistryEntry = await getExtendedEntityRegistryEntry(
this.hass,
this._entityId
);
if (entityRegistryEntry.platform !== "local_todo") {
return;
}
const entryId = entityRegistryEntry.config_entry_id;
if (!entryId) {
return;
}
const confirmed = await showConfirmationDialog(this, {
title: this.hass.localize("ui.panel.todo.delete_confirm_title", {
name:
this._entityId in this.hass.states
? computeStateName(this.hass.states[this._entityId])
: this._entityId,
}),
text: this.hass.localize("ui.panel.todo.delete_confirm_text"),
confirmText: this.hass!.localize("ui.common.delete"),
dismissText: this.hass!.localize("ui.common.cancel"),
destructive: true,
});
if (!confirmed) {
return;
}
const result = await deleteConfigEntry(this.hass, entryId);
this._entityId = getTodoLists(this.hass)[0]?.entity_id;
if (result.require_restart) {
showAlertDialog(this, {
text: this.hass.localize("ui.panel.todo.restart_confirm"),
});
}
}
private _showVoiceCommandDialog(): void { private _showVoiceCommandDialog(): void {
showVoiceCommandDialog(this, this.hass, { pipeline_id: "last_used" }); showVoiceCommandDialog(this, this.hass, { pipeline_id: "last_used" });
} }
@@ -240,11 +338,18 @@ class PanelTodo extends LitElement {
:host([mobile]) .lists { :host([mobile]) .lists {
--mdc-menu-min-width: 100vw; --mdc-menu-min-width: 100vw;
} }
:host(:not([mobile])) .lists ha-list-item {
max-width: calc(100vw - 120px);
}
:host([mobile]) ha-button-menu { :host([mobile]) ha-button-menu {
--mdc-shape-medium: 0 0 var(--mdc-shape-medium) --mdc-shape-medium: 0 0 var(--mdc-shape-medium)
var(--mdc-shape-medium); var(--mdc-shape-medium);
} }
ha-button-menu {
max-width: 100%;
}
ha-button-menu ha-button { ha-button-menu ha-button {
max-width: 100%;
--mdc-theme-primary: currentColor; --mdc-theme-primary: currentColor;
--mdc-typography-button-text-transform: none; --mdc-typography-button-text-transform: none;
--mdc-typography-button-font-size: var( --mdc-typography-button-font-size: var(
@@ -265,6 +370,13 @@ class PanelTodo extends LitElement {
); );
--button-height: 40px; --button-height: 40px;
} }
ha-button-menu ha-button div {
text-overflow: ellipsis;
width: 100%;
overflow: hidden;
white-space: nowrap;
display: block;
}
`, `,
]; ];
} }

View File

@@ -274,6 +274,10 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
// on reconnect always fetch config as we might miss an update while we were disconnected // on reconnect always fetch config as we might miss an update while we were disconnected
// @ts-ignore // @ts-ignore
this.hass!.callWS({ type: "get_config" }).then((config: HassConfig) => { this.hass!.callWS({ type: "get_config" }).then((config: HassConfig) => {
if (config.safe_mode) {
// @ts-ignore Firefox supports forceGet
location.reload(true);
}
this._updateHass({ config }); this._updateHass({ config });
this.checkDataBaseMigration(); this.checkDataBaseMigration();
}); });

View File

@@ -444,9 +444,7 @@
"none": "None" "none": "None"
}, },
"user-picker": { "user-picker": {
"no_user": "No user", "user": "User"
"add_user": "Add user",
"remove_user": "Remove user"
}, },
"blueprint-picker": { "blueprint-picker": {
"select_blueprint": "Select a blueprint" "select_blueprint": "Select a blueprint"
@@ -2140,6 +2138,8 @@
"js": "JavaScript file (deprecated)", "js": "JavaScript file (deprecated)",
"module": "JavaScript module" "module": "JavaScript module"
}, },
"unavailable": "Resources unavailable",
"unavailable_safe_mode": "Resources are not available in safe mode",
"picker": { "picker": {
"headers": { "headers": {
"url": "URL", "url": "URL",
@@ -4520,7 +4520,6 @@
"never_triggered": "Never triggered" "never_triggered": "Never triggered"
}, },
"todo-list": { "todo-list": {
"lists": "To-do Lists",
"checked_items": "Checked items", "checked_items": "Checked items",
"clear_items": "Clear checked items", "clear_items": "Clear checked items",
"add_item": "Add item", "add_item": "Add item",
@@ -5094,7 +5093,7 @@
"description": "The Sensor card gives you a quick overview of your sensors state with an optional graph to visualize change over time." "description": "The Sensor card gives you a quick overview of your sensors state with an optional graph to visualize change over time."
}, },
"todo-list": { "todo-list": {
"name": "Todo list", "name": "To-do list",
"description": "The to-do list card allows you to add, edit, check-off, and clear items from your to-do list.", "description": "The to-do list card allows you to add, edit, check-off, and clear items from your to-do list.",
"integration_not_loaded": "This card requires the `todo` integration to be set up." "integration_not_loaded": "This card requires the `todo` integration to be set up."
}, },
@@ -5114,6 +5113,10 @@
"vertical": "Vertical", "vertical": "Vertical",
"hide_state": "Hide state", "hide_state": "Hide state",
"state_content": "State content", "state_content": "State content",
"state_content_options": {
"state": "State",
"last-changed": "Last changed"
},
"features": { "features": {
"name": "Features", "name": "Features",
"not_compatible": "Not compatible", "not_compatible": "Not compatible",
@@ -5511,8 +5514,13 @@
} }
}, },
"todo": { "todo": {
"start_conversation": "Start conversation", "assist": "[%key:ui::panel::lovelace::menu::assist%]",
"create_list": "Create list" "create_list": "Create list",
"delete_list": "Delete list",
"information": "Information",
"delete_confirm_title": "Remove {name}?",
"delete_confirm_text": "Are you sure you want to remove this list and all of its items?",
"restart_confirm": "Restart Home Assistant to finish removing this to-do list"
}, },
"page-authorize": { "page-authorize": {
"initializing": "Initializing", "initializing": "Initializing",

461
yarn.lock
View File

@@ -1437,12 +1437,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@bundle-stats/plugin-webpack-filter@npm:4.7.7": "@bundle-stats/plugin-webpack-filter@npm:4.7.8":
version: 4.7.7 version: 4.7.8
resolution: "@bundle-stats/plugin-webpack-filter@npm:4.7.7" resolution: "@bundle-stats/plugin-webpack-filter@npm:4.7.8"
peerDependencies: peerDependencies:
core-js: ^3.0.0 core-js: ^3.0.0
checksum: 09ab4c295305043c342db7f0509b551e75d61e6db4e2ca90858e2558e3132ffecb7296ae4a3c049d705eea1fecd2bc70c3ec9f233359e5547a8e60cb79e6cd5e checksum: 35ccdbbe92464890173467dbcad43e5b0658ea7f167d9ef6daa752d48afa0183453271ac37e77ec98f6acb811fc5b57595bb40c310f11ad29111460cda03c4dc
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1475,9 +1475,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@codemirror/language@npm:6.9.1, @codemirror/language@npm:^6.0.0": "@codemirror/language@npm:6.9.2, @codemirror/language@npm:^6.0.0":
version: 6.9.1 version: 6.9.2
resolution: "@codemirror/language@npm:6.9.1" resolution: "@codemirror/language@npm:6.9.2"
dependencies: dependencies:
"@codemirror/state": ^6.0.0 "@codemirror/state": ^6.0.0
"@codemirror/view": ^6.0.0 "@codemirror/view": ^6.0.0
@@ -1485,7 +1485,7 @@ __metadata:
"@lezer/highlight": ^1.0.0 "@lezer/highlight": ^1.0.0
"@lezer/lr": ^1.0.0 "@lezer/lr": ^1.0.0
style-mod: ^4.0.0 style-mod: ^4.0.0
checksum: 62265f1042d2edfd3a091c408d9d0071f23889099b2f6ce8275fa910118bd2c45b8c4b29228c7be6e6d5f0e0812a522de902bc75ba8d8b2e62e42ade1692a49a checksum: eee7b861b5591114cac7502cd532d5b923639740081a4cd7e28696c252af8d759b14686aaf6d5eee7e0969ff647b7aaf03a5eea7235fb6d9858ee19433f1c74d
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1516,14 +1516,14 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@codemirror/view@npm:6.21.3, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0": "@codemirror/view@npm:6.21.4, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0":
version: 6.21.3 version: 6.21.4
resolution: "@codemirror/view@npm:6.21.3" resolution: "@codemirror/view@npm:6.21.4"
dependencies: dependencies:
"@codemirror/state": ^6.1.4 "@codemirror/state": ^6.1.4
style-mod: ^4.1.0 style-mod: ^4.1.0
w3c-keyname: ^2.2.4 w3c-keyname: ^2.2.4
checksum: 7fda5a60e04fe1ac3d22ee478d4a90fc307953b8c900752ef5ca33af06c4e7851356e460f14b05034230b3a1677f36379ea01d85a3ea3b3a3e85e871ed62346a checksum: e320eb46a6556984081c97e0bf5a9f5d45de2a4db5d632e6ee689a32dc081b10bda87aa989c4563981e28bf25bb651d1be57158fc2e753b587e3c6f7e2e486b2
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1634,25 +1634,25 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@formatjs/intl-datetimeformat@npm:6.11.0": "@formatjs/intl-datetimeformat@npm:6.11.1":
version: 6.11.0 version: 6.11.1
resolution: "@formatjs/intl-datetimeformat@npm:6.11.0" resolution: "@formatjs/intl-datetimeformat@npm:6.11.1"
dependencies: dependencies:
"@formatjs/ecma402-abstract": 1.17.2 "@formatjs/ecma402-abstract": 1.17.2
"@formatjs/intl-localematcher": 0.4.2 "@formatjs/intl-localematcher": 0.4.2
tslib: ^2.4.0 tslib: ^2.4.0
checksum: 6a503d0bfc2bcdbf904080bcc7da9531f2491496969b47640dd75b0ac029b0d1b11ea7a380f32153b4a07b275af522945b6bc66e153b47e9ab34754ac710cb8e checksum: 585f33cc292ef509e1716062a83e887914180708452df273032df34e721ddb81b9a7d96bbe66333765f4834bee2ca788fff11acdd71a95bf7df58a9ed5224dec
languageName: node languageName: node
linkType: hard linkType: hard
"@formatjs/intl-displaynames@npm:6.6.0": "@formatjs/intl-displaynames@npm:6.6.1":
version: 6.6.0 version: 6.6.1
resolution: "@formatjs/intl-displaynames@npm:6.6.0" resolution: "@formatjs/intl-displaynames@npm:6.6.1"
dependencies: dependencies:
"@formatjs/ecma402-abstract": 1.17.2 "@formatjs/ecma402-abstract": 1.17.2
"@formatjs/intl-localematcher": 0.4.2 "@formatjs/intl-localematcher": 0.4.2
tslib: ^2.4.0 tslib: ^2.4.0
checksum: d7794fd618499a85ea4a2b9ab47588259325f866f941eadd5047c05934d64504083758c9dfc50ec26665513bdeeb3f44f0bc81c9af919fd4ef68dd5192d114b4 checksum: e70c18f5f6228fbf937434c9168eac4d42c7f115410b42b66785ba43db4604184849d9e55b76ca4ce116359fec645b5e41e06b036dcb0966387c19753970c8e5
languageName: node languageName: node
linkType: hard linkType: hard
@@ -4601,15 +4601,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/eslint-plugin@npm:6.8.0": "@typescript-eslint/eslint-plugin@npm:6.9.0":
version: 6.8.0 version: 6.9.0
resolution: "@typescript-eslint/eslint-plugin@npm:6.8.0" resolution: "@typescript-eslint/eslint-plugin@npm:6.9.0"
dependencies: dependencies:
"@eslint-community/regexpp": ^4.5.1 "@eslint-community/regexpp": ^4.5.1
"@typescript-eslint/scope-manager": 6.8.0 "@typescript-eslint/scope-manager": 6.9.0
"@typescript-eslint/type-utils": 6.8.0 "@typescript-eslint/type-utils": 6.9.0
"@typescript-eslint/utils": 6.8.0 "@typescript-eslint/utils": 6.9.0
"@typescript-eslint/visitor-keys": 6.8.0 "@typescript-eslint/visitor-keys": 6.9.0
debug: ^4.3.4 debug: ^4.3.4
graphemer: ^1.4.0 graphemer: ^1.4.0
ignore: ^5.2.4 ignore: ^5.2.4
@@ -4622,44 +4622,44 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: c36ccf606ebcaff8263c4ffa3b4cda58c6f93474b9eea9906e51be2fef8596977a245cc13770b21c6bfd38ccf45a3cf3613d5f4499429f62ec80afe15ae345bd checksum: 51d7afc18bab711e20147f7163083f05435b6860174169eae56de217ed2cb1b3c08cba01b7d338315c2d8ecb982e83ce8f2ca7d2108c1c7c04faff2001b094d3
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/parser@npm:6.8.0": "@typescript-eslint/parser@npm:6.9.0":
version: 6.8.0 version: 6.9.0
resolution: "@typescript-eslint/parser@npm:6.8.0" resolution: "@typescript-eslint/parser@npm:6.9.0"
dependencies: dependencies:
"@typescript-eslint/scope-manager": 6.8.0 "@typescript-eslint/scope-manager": 6.9.0
"@typescript-eslint/types": 6.8.0 "@typescript-eslint/types": 6.9.0
"@typescript-eslint/typescript-estree": 6.8.0 "@typescript-eslint/typescript-estree": 6.9.0
"@typescript-eslint/visitor-keys": 6.8.0 "@typescript-eslint/visitor-keys": 6.9.0
debug: ^4.3.4 debug: ^4.3.4
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 10d7a3ae383fee5a5cba9541c72e23d6ab01cca6b414a62b44dacb5ebc15c80b80aa6c105b6469d3795f2f8514ae2499c069cd2d9dcac61f3db9ef6c7a75e080 checksum: d8ff69d236d6495474ab93c67e2785cc94bf9c098f25c33f1c5958a4b2b5af2b70edf1cdd0c23ee3436df454a769e80eb47d2d34df8382a826fcdb79bac4382d
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/scope-manager@npm:6.8.0": "@typescript-eslint/scope-manager@npm:6.9.0":
version: 6.8.0 version: 6.9.0
resolution: "@typescript-eslint/scope-manager@npm:6.8.0" resolution: "@typescript-eslint/scope-manager@npm:6.9.0"
dependencies: dependencies:
"@typescript-eslint/types": 6.8.0 "@typescript-eslint/types": 6.9.0
"@typescript-eslint/visitor-keys": 6.8.0 "@typescript-eslint/visitor-keys": 6.9.0
checksum: b6cf2803531d1c14b56c30fd3cd807b80e17fe48d0da8e5aa9ae50915407ed732c7e2a7ac8030b7cf8ed07b8e481a1138d76bf05b727837a0e016280c2f6873b checksum: b7ddcea11bdb95107659800bdf3b33eae22a4dc5c28dc0f8dc5507aa9affaae0e332b6d8c7d5286a7ec75e7c4abd211eb9fdf9647a9a796689cdcc11f6ab40c6
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/type-utils@npm:6.8.0": "@typescript-eslint/type-utils@npm:6.9.0":
version: 6.8.0 version: 6.9.0
resolution: "@typescript-eslint/type-utils@npm:6.8.0" resolution: "@typescript-eslint/type-utils@npm:6.9.0"
dependencies: dependencies:
"@typescript-eslint/typescript-estree": 6.8.0 "@typescript-eslint/typescript-estree": 6.9.0
"@typescript-eslint/utils": 6.8.0 "@typescript-eslint/utils": 6.9.0
debug: ^4.3.4 debug: ^4.3.4
ts-api-utils: ^1.0.1 ts-api-utils: ^1.0.1
peerDependencies: peerDependencies:
@@ -4667,23 +4667,23 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 9b7d56904dc1a5719ef79eb1b7989d6fad10c71fb07ec3e66cf69b8c8dc5383d644ab122d4701bc4960fb7c99cc08aee4e645db3e4675d488d5779197e15dfda checksum: 279b0000cd2fe7ccfbd2f311736b14c8bb9287081f553c9452c95966650c822e67442ba5a62d7fea3ee2f61ccc0fcb218f21e1ee7ccf3984c52e5942d2bbb065
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/types@npm:6.8.0": "@typescript-eslint/types@npm:6.9.0":
version: 6.8.0 version: 6.9.0
resolution: "@typescript-eslint/types@npm:6.8.0" resolution: "@typescript-eslint/types@npm:6.9.0"
checksum: 1fcd85f6d575116d51c6ee757ed37610ae5e7e4296a29f93c9c6949f6cd16d24550eb7fc5bae7a43119cc08e13836f69a7ae7c54ebba6c95aef96b34d3bfb7f7 checksum: e0444afa1f2ebca746c72b3d0bf95982eb1e8b4fb91bcba465c1345c35fa13b36c589bfd91c776b864f223bc50817b2613df5892185c2e34332bf4cc57cc865d
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/typescript-estree@npm:6.8.0": "@typescript-eslint/typescript-estree@npm:6.9.0":
version: 6.8.0 version: 6.9.0
resolution: "@typescript-eslint/typescript-estree@npm:6.8.0" resolution: "@typescript-eslint/typescript-estree@npm:6.9.0"
dependencies: dependencies:
"@typescript-eslint/types": 6.8.0 "@typescript-eslint/types": 6.9.0
"@typescript-eslint/visitor-keys": 6.8.0 "@typescript-eslint/visitor-keys": 6.9.0
debug: ^4.3.4 debug: ^4.3.4
globby: ^11.1.0 globby: ^11.1.0
is-glob: ^4.0.3 is-glob: ^4.0.3
@@ -4692,34 +4692,34 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 388db7f33ef1bc0e7b960c0bce9c744c2e32c66c7ab8dfae73d8533958202ad6f31663b0010f79c45b5ff93159c67f45b00693d73b9da2472b17156dfd26b4a8 checksum: 51088c23cca608a6e5c195b0a2d8a17ad00ca47199ba4df0c1013912a80194bff9f5bd4d035d6ab2596788491e9a3e04bbf6cad6494a3b1bbd59fea442750268
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/utils@npm:6.8.0": "@typescript-eslint/utils@npm:6.9.0":
version: 6.8.0 version: 6.9.0
resolution: "@typescript-eslint/utils@npm:6.8.0" resolution: "@typescript-eslint/utils@npm:6.9.0"
dependencies: dependencies:
"@eslint-community/eslint-utils": ^4.4.0 "@eslint-community/eslint-utils": ^4.4.0
"@types/json-schema": ^7.0.12 "@types/json-schema": ^7.0.12
"@types/semver": ^7.5.0 "@types/semver": ^7.5.0
"@typescript-eslint/scope-manager": 6.8.0 "@typescript-eslint/scope-manager": 6.9.0
"@typescript-eslint/types": 6.8.0 "@typescript-eslint/types": 6.9.0
"@typescript-eslint/typescript-estree": 6.8.0 "@typescript-eslint/typescript-estree": 6.9.0
semver: ^7.5.4 semver: ^7.5.4
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
checksum: 6d9f90db504502a9aa10e834830c3ffa25483757414670acc6141a3ebef9171a57688a3a179febf35a0e1e0b322f37228d9537bf1b279f1af7fc97888b873bc3 checksum: 973c24d7858f224934958ee58c21ff21dfe54dbb1d0e0c5f889298fadcd7ee2dbfd49cf86ccafab74d428c31de66cd9beee7c39d2b64f9edcc9e941573bac175
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/visitor-keys@npm:6.8.0": "@typescript-eslint/visitor-keys@npm:6.9.0":
version: 6.8.0 version: 6.9.0
resolution: "@typescript-eslint/visitor-keys@npm:6.8.0" resolution: "@typescript-eslint/visitor-keys@npm:6.9.0"
dependencies: dependencies:
"@typescript-eslint/types": 6.8.0 "@typescript-eslint/types": 6.9.0
eslint-visitor-keys: ^3.4.1 eslint-visitor-keys: ^3.4.1
checksum: 710d9067b85d7715a400ae625c083c41733abb891d7b35108de083913980f9642e79d27689599fa39915f0fecae16dbfc30367007fccc838ccd917943660de22 checksum: de8e2e363df41e5ae9774a5ebd1c49d29c771ea8b3869917f65a74cd4d14a67417c79916f456ee81ef5b0d947b7b8975385fc6eea3f1812d53a2eaaea832459e
languageName: node languageName: node
linkType: hard linkType: hard
@@ -4730,126 +4730,126 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/a11y-base@npm:~24.2.0": "@vaadin/a11y-base@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/a11y-base@npm:24.2.0" resolution: "@vaadin/a11y-base@npm:24.2.1"
dependencies: dependencies:
"@open-wc/dedupe-mixin": ^1.3.0 "@open-wc/dedupe-mixin": ^1.3.0
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
lit: ^2.0.0 lit: ^2.0.0
checksum: 396e423880a1381b70796710e9dee8c40105ba1b886aaf1a34cd83398cfa83ca9e3b2635a9e0493df7536262d37d7c1abed9f879498a6dcbcf588e96d790441a checksum: f9e70a57f17daa61ccb65fab52faf645683b11df518ccc80f8034e24053a4d039e4f2e9a70f7e7f8768f1d0fab181fd83056f2d30b260d0bc5dd69831619072f
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/combo-box@npm:24.2.0": "@vaadin/combo-box@npm:24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/combo-box@npm:24.2.0" resolution: "@vaadin/combo-box@npm:24.2.1"
dependencies: dependencies:
"@open-wc/dedupe-mixin": ^1.3.0 "@open-wc/dedupe-mixin": ^1.3.0
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/a11y-base": ~24.2.0 "@vaadin/a11y-base": ~24.2.1
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
"@vaadin/field-base": ~24.2.0 "@vaadin/field-base": ~24.2.1
"@vaadin/input-container": ~24.2.0 "@vaadin/input-container": ~24.2.1
"@vaadin/item": ~24.2.0 "@vaadin/item": ~24.2.1
"@vaadin/lit-renderer": ~24.2.0 "@vaadin/lit-renderer": ~24.2.1
"@vaadin/overlay": ~24.2.0 "@vaadin/overlay": ~24.2.1
"@vaadin/vaadin-lumo-styles": ~24.2.0 "@vaadin/vaadin-lumo-styles": ~24.2.1
"@vaadin/vaadin-material-styles": ~24.2.0 "@vaadin/vaadin-material-styles": ~24.2.1
"@vaadin/vaadin-themable-mixin": ~24.2.0 "@vaadin/vaadin-themable-mixin": ~24.2.1
checksum: cc9ff9b166fd2629ca75d24e21c2e87745b1e3aa16f7ffffd91d0bb911d860cd3e70276b6321837fbe889cc6132a5c1e46dfe5f15755feaf6e124b259369fd7e checksum: e8d43fa29553761dcf2d6b1353f2599d112d859f1c85d2a3ad5f8413312e85ab68c200a4bedb49afb5bee08c333b79dbe88c09f8644de815623c1c1f13a50740
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/component-base@npm:~24.2.0": "@vaadin/component-base@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/component-base@npm:24.2.0" resolution: "@vaadin/component-base@npm:24.2.1"
dependencies: dependencies:
"@open-wc/dedupe-mixin": ^1.3.0 "@open-wc/dedupe-mixin": ^1.3.0
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/vaadin-development-mode-detector": ^2.0.0 "@vaadin/vaadin-development-mode-detector": ^2.0.0
"@vaadin/vaadin-usage-statistics": ^2.1.0 "@vaadin/vaadin-usage-statistics": ^2.1.0
lit: ^2.0.0 lit: ^2.0.0
checksum: c4032c579ce22fd904ceda03fab95a818ead4eb471fe00bc8705ea3259fa16d0ab3c2947403daeab995a2ead072fb29bd738731eee329f91cedfaf17bf665395 checksum: c717ab81171958c57f831a5b25bf04fbb908b145fd4311da248db2ce3ba42ca0144f140c31d78e5011d6777047a1d8aa1337a5bd719f63b0b1d3d03dbbe2dacf
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/field-base@npm:~24.2.0": "@vaadin/field-base@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/field-base@npm:24.2.0" resolution: "@vaadin/field-base@npm:24.2.1"
dependencies: dependencies:
"@open-wc/dedupe-mixin": ^1.3.0 "@open-wc/dedupe-mixin": ^1.3.0
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/a11y-base": ~24.2.0 "@vaadin/a11y-base": ~24.2.1
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
lit: ^2.0.0 lit: ^2.0.0
checksum: f2594cee0a71e65b8b809b50ba3044c154ea9444e12bdef807a7ed060d4bbd55666bb35314033e67b54476f7c35072bc1e6f0e4724c1334feef48779529e02d6 checksum: fce85d1baca208dca7b5d939764c85489992fdc02068ec7aeb0ef9c7dc63ddb3b93d308239c9b94167d27f166fb471cac2441935d245f0d78ab9c8450b729fdb
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/icon@npm:~24.2.0": "@vaadin/icon@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/icon@npm:24.2.0" resolution: "@vaadin/icon@npm:24.2.1"
dependencies: dependencies:
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
"@vaadin/vaadin-lumo-styles": ~24.2.0 "@vaadin/vaadin-lumo-styles": ~24.2.1
"@vaadin/vaadin-themable-mixin": ~24.2.0 "@vaadin/vaadin-themable-mixin": ~24.2.1
lit: ^2.0.0 lit: ^2.0.0
checksum: 5a1f2621074026f46dc80d59e2e9d4e831afcc5da1cfb00b73d08f870d0feb6abbd2fd9d0622847d6b1538abd1ca544cb74f31797f2704b99e959f0a72f7cf92 checksum: f63c5ebc14cc7e9594fac3dcb3469328ac81d004ca03665ded32b5a542ae9c9950ed75d9038a1c89348fcefa26d0350311e2bf6877de2c77f83fa17a87c4f6fe
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/input-container@npm:~24.2.0": "@vaadin/input-container@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/input-container@npm:24.2.0" resolution: "@vaadin/input-container@npm:24.2.1"
dependencies: dependencies:
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
"@vaadin/vaadin-lumo-styles": ~24.2.0 "@vaadin/vaadin-lumo-styles": ~24.2.1
"@vaadin/vaadin-material-styles": ~24.2.0 "@vaadin/vaadin-material-styles": ~24.2.1
"@vaadin/vaadin-themable-mixin": ~24.2.0 "@vaadin/vaadin-themable-mixin": ~24.2.1
checksum: 4bc075bcf4ab19b6f7d3eca030db953c064409695862471c43397646e7efb6d70d865dca153d8a6cf8e6d1d9f3f111118e36da510b9667e7d1911ffd8b4f6de5 checksum: 18877e00b75acf6006809c557cb7e694b57bdb09763920a6dea604beb0e3a601f781079f664ac81dc2100670de201a6521bbb1d7e722fc603289f7311d2f0fb7
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/item@npm:~24.2.0": "@vaadin/item@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/item@npm:24.2.0" resolution: "@vaadin/item@npm:24.2.1"
dependencies: dependencies:
"@open-wc/dedupe-mixin": ^1.3.0 "@open-wc/dedupe-mixin": ^1.3.0
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/a11y-base": ~24.2.0 "@vaadin/a11y-base": ~24.2.1
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
"@vaadin/vaadin-lumo-styles": ~24.2.0 "@vaadin/vaadin-lumo-styles": ~24.2.1
"@vaadin/vaadin-material-styles": ~24.2.0 "@vaadin/vaadin-material-styles": ~24.2.1
"@vaadin/vaadin-themable-mixin": ~24.2.0 "@vaadin/vaadin-themable-mixin": ~24.2.1
checksum: 70c885555fc1c3d4310448b3ecf97aee9bdc9ccbc12f0b39da3eff7442054d56bbbe78af4f7c201b93c08fdf64f891493c8e00acb57be57d763db2f61ef3e218 checksum: f9d435971e39f42f24bf7384718828e5e0eeb32a19fbd70de5945e36a1222c1fbb7e025bb0f2513e1dc244510c12986f4e9478302c91de1ad04accf71956f010
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/lit-renderer@npm:~24.2.0": "@vaadin/lit-renderer@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/lit-renderer@npm:24.2.0" resolution: "@vaadin/lit-renderer@npm:24.2.1"
dependencies: dependencies:
lit: ^2.0.0 lit: ^2.0.0
checksum: d6a9c9ea302ef7f1b2559124e5b783f07eeec615f343191c01aa64d1227154b628e82d511e1c36a79fa896904ee00608321e7008b251a7d09fd70584a8e1c7d8 checksum: 230627e64af657fbad8c6c2d987b54eda2856a2bf0f25dce30202346ea107786c34c0ac8436049abbaf201635d33332afd0c547e43ed42581b3d577f8148750a
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/overlay@npm:~24.2.0": "@vaadin/overlay@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/overlay@npm:24.2.0" resolution: "@vaadin/overlay@npm:24.2.1"
dependencies: dependencies:
"@open-wc/dedupe-mixin": ^1.3.0 "@open-wc/dedupe-mixin": ^1.3.0
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/a11y-base": ~24.2.0 "@vaadin/a11y-base": ~24.2.1
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
"@vaadin/vaadin-lumo-styles": ~24.2.0 "@vaadin/vaadin-lumo-styles": ~24.2.1
"@vaadin/vaadin-material-styles": ~24.2.0 "@vaadin/vaadin-material-styles": ~24.2.1
"@vaadin/vaadin-themable-mixin": ~24.2.0 "@vaadin/vaadin-themable-mixin": ~24.2.1
checksum: 16876742a3d85ba19387bf5b1a67e50ec6e003c681072d117974041a95ecad754ae8d522ee7f3e9a1d25f9ed9b831b6c9bca7ffb4748d99437da6f5b954cef6b checksum: 139e81e4190e4431cb73b93a2a878f3658481540ad6ab22490f7b4974aaf2cb5ac88296b11ff0f23d986ccebf8f5ad0987d31bbb12983bba92919393bc96195b
languageName: node languageName: node
linkType: hard linkType: hard
@@ -4860,36 +4860,36 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/vaadin-lumo-styles@npm:~24.2.0": "@vaadin/vaadin-lumo-styles@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/vaadin-lumo-styles@npm:24.2.0" resolution: "@vaadin/vaadin-lumo-styles@npm:24.2.1"
dependencies: dependencies:
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
"@vaadin/icon": ~24.2.0 "@vaadin/icon": ~24.2.1
"@vaadin/vaadin-themable-mixin": ~24.2.0 "@vaadin/vaadin-themable-mixin": ~24.2.1
checksum: 61959e5df9ad5d91f8bcd6dd7fc4588aca03e1625b15d0b8390b8e450e72ac27289cc331f57b8c10525f4f4efe06a05468926303f5b122fecc9fa68fd7444b10 checksum: eb2bd0cbb63798fb089cc517d873c70c36bef434fa7a91c3a8bb420679de79badf68ea9a2fd2127eca118029b445c432659a79b9ee2edb307650e45aadd2c54e
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/vaadin-material-styles@npm:~24.2.0": "@vaadin/vaadin-material-styles@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/vaadin-material-styles@npm:24.2.0" resolution: "@vaadin/vaadin-material-styles@npm:24.2.1"
dependencies: dependencies:
"@polymer/polymer": ^3.0.0 "@polymer/polymer": ^3.0.0
"@vaadin/component-base": ~24.2.0 "@vaadin/component-base": ~24.2.1
"@vaadin/vaadin-themable-mixin": ~24.2.0 "@vaadin/vaadin-themable-mixin": ~24.2.1
checksum: bf19268dd522f026e45414a602fe84d146f418027e9eada8ad4b7dbe2e6f3dc6aedf28feb6b53b89b2c37446425bcb7c5603b2b9869feb35366148ed5d5dfec3 checksum: 06ba93b1726655d52a742928fae91b30f3d2114f350f43043b46c227131393734fff4ab2a86dc2516b636fcbddd3f973bd8db350fbc136e0e8a24a154b87aaac
languageName: node languageName: node
linkType: hard linkType: hard
"@vaadin/vaadin-themable-mixin@npm:24.2.0, @vaadin/vaadin-themable-mixin@npm:~24.2.0": "@vaadin/vaadin-themable-mixin@npm:24.2.1, @vaadin/vaadin-themable-mixin@npm:~24.2.1":
version: 24.2.0 version: 24.2.1
resolution: "@vaadin/vaadin-themable-mixin@npm:24.2.0" resolution: "@vaadin/vaadin-themable-mixin@npm:24.2.1"
dependencies: dependencies:
"@open-wc/dedupe-mixin": ^1.3.0 "@open-wc/dedupe-mixin": ^1.3.0
lit: ^2.0.0 lit: ^2.0.0
checksum: 9d71c7432ea97b29128fe02799b943da80fddce3e256433fb0e9da98ca19f239002e6f66c6a061f98582ed8f7936dbbbf0985e5c58e40113e804e509ba32a55a checksum: 1da248d4c21b8eb0df918cceee3ba264a883a51864d434d78aaef8f79d1f54dadfb7d98becdf8174b1dc43c702023706e3aaccd04c3b3d85e33bb47d1fc0778f
languageName: node languageName: node
linkType: hard linkType: hard
@@ -5019,14 +5019,14 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@vue/compiler-sfc@npm:2.7.14": "@vue/compiler-sfc@npm:2.7.15":
version: 2.7.14 version: 2.7.15
resolution: "@vue/compiler-sfc@npm:2.7.14" resolution: "@vue/compiler-sfc@npm:2.7.15"
dependencies: dependencies:
"@babel/parser": ^7.18.4 "@babel/parser": ^7.18.4
postcss: ^8.4.14 postcss: ^8.4.14
source-map: ^0.6.1 source-map: ^0.6.1
checksum: 25e00abaecb311f1effbf539bc3e4fdeedb39d35f9c2947b2640187a047e6a7400e693fd7da1d3a98977b9078c5bf629ca47f8b9a59dc14a080c0a1e1dd06a49 checksum: 9052c3f08d619021e9f8f0e9762fb1dc72afe9829909cd2045bdad82dacc7867344c457549ba31c94684442931cfb32db8a30c9df6ef4a62bef9346320ea7638
languageName: node languageName: node
linkType: hard linkType: hard
@@ -5799,7 +5799,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"array-includes@npm:^3.1.6": "array-includes@npm:^3.1.7":
version: 3.1.7 version: 3.1.7
resolution: "array-includes@npm:3.1.7" resolution: "array-includes@npm:3.1.7"
dependencies: dependencies:
@@ -5870,7 +5870,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"array.prototype.find@npm:^2.2.1": "array.prototype.find@npm:^2.2.2":
version: 2.2.2 version: 2.2.2
resolution: "array.prototype.find@npm:2.2.2" resolution: "array.prototype.find@npm:2.2.2"
dependencies: dependencies:
@@ -5882,7 +5882,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"array.prototype.findlastindex@npm:^1.2.2": "array.prototype.findlastindex@npm:^1.2.3":
version: 1.2.3 version: 1.2.3
resolution: "array.prototype.findlastindex@npm:1.2.3" resolution: "array.prototype.findlastindex@npm:1.2.3"
dependencies: dependencies:
@@ -5895,7 +5895,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"array.prototype.flat@npm:^1.3.1": "array.prototype.flat@npm:^1.3.2":
version: 1.3.2 version: 1.3.2
resolution: "array.prototype.flat@npm:1.3.2" resolution: "array.prototype.flat@npm:1.3.2"
dependencies: dependencies:
@@ -5907,7 +5907,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"array.prototype.flatmap@npm:^1.3.1": "array.prototype.flatmap@npm:^1.3.2":
version: 1.3.2 version: 1.3.2
resolution: "array.prototype.flatmap@npm:1.3.2" resolution: "array.prototype.flatmap@npm:1.3.2"
dependencies: dependencies:
@@ -7974,7 +7974,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-import-resolver-node@npm:^0.3.7": "eslint-import-resolver-node@npm:^0.3.9":
version: 0.3.9 version: 0.3.9
resolution: "eslint-import-resolver-node@npm:0.3.9" resolution: "eslint-import-resolver-node@npm:0.3.9"
dependencies: dependencies:
@@ -7985,25 +7985,25 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-import-resolver-webpack@npm:0.13.7": "eslint-import-resolver-webpack@npm:0.13.8":
version: 0.13.7 version: 0.13.8
resolution: "eslint-import-resolver-webpack@npm:0.13.7" resolution: "eslint-import-resolver-webpack@npm:0.13.8"
dependencies: dependencies:
array.prototype.find: ^2.2.1 array.prototype.find: ^2.2.2
debug: ^3.2.7 debug: ^3.2.7
enhanced-resolve: ^0.9.1 enhanced-resolve: ^0.9.1
find-root: ^1.1.0 find-root: ^1.1.0
has: ^1.0.3 hasown: ^2.0.0
interpret: ^1.4.0 interpret: ^1.4.0
is-core-module: ^2.13.0 is-core-module: ^2.13.1
is-regex: ^1.1.4 is-regex: ^1.1.4
lodash: ^4.17.21 lodash: ^4.17.21
resolve: ^2.0.0-next.4 resolve: ^2.0.0-next.5
semver: ^5.7.2 semver: ^5.7.2
peerDependencies: peerDependencies:
eslint-plugin-import: ">=1.4.0" eslint-plugin-import: ">=1.4.0"
webpack: ">=1.11.0" webpack: ">=1.11.0"
checksum: 7e7bd7d48c570cb3110b04f9bb7ec6a2f2cfee29471c89a292c5825d3c1209af227310a53e9e9a46d83a8c6eed32bb3ad28f24f5499b25a18d4e21770acfc6fe checksum: 968aaee69d1e0ef789a10746ff50556e10d43c5f887587d4c34e73dd2215f57f0d3266c43fcdee36a36ce19a2b1beb08aebeb10f6c3ee9edb095506eead28eb6
languageName: node languageName: node
linkType: hard linkType: hard
@@ -8030,30 +8030,30 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-plugin-import@npm:2.28.1": "eslint-plugin-import@npm:2.29.0":
version: 2.28.1 version: 2.29.0
resolution: "eslint-plugin-import@npm:2.28.1" resolution: "eslint-plugin-import@npm:2.29.0"
dependencies: dependencies:
array-includes: ^3.1.6 array-includes: ^3.1.7
array.prototype.findlastindex: ^1.2.2 array.prototype.findlastindex: ^1.2.3
array.prototype.flat: ^1.3.1 array.prototype.flat: ^1.3.2
array.prototype.flatmap: ^1.3.1 array.prototype.flatmap: ^1.3.2
debug: ^3.2.7 debug: ^3.2.7
doctrine: ^2.1.0 doctrine: ^2.1.0
eslint-import-resolver-node: ^0.3.7 eslint-import-resolver-node: ^0.3.9
eslint-module-utils: ^2.8.0 eslint-module-utils: ^2.8.0
has: ^1.0.3 hasown: ^2.0.0
is-core-module: ^2.13.0 is-core-module: ^2.13.1
is-glob: ^4.0.3 is-glob: ^4.0.3
minimatch: ^3.1.2 minimatch: ^3.1.2
object.fromentries: ^2.0.6 object.fromentries: ^2.0.7
object.groupby: ^1.0.0 object.groupby: ^1.0.1
object.values: ^1.1.6 object.values: ^1.1.7
semver: ^6.3.1 semver: ^6.3.1
tsconfig-paths: ^3.14.2 tsconfig-paths: ^3.14.2
peerDependencies: peerDependencies:
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
checksum: e8ae6dd8f06d8adf685f9c1cfd46ac9e053e344a05c4090767e83b63a85c8421ada389807a39e73c643b9bff156715c122e89778169110ed68d6428e12607edf checksum: 19ee541fb95eb7a796f3daebe42387b8d8262bbbcc4fd8a6e92f63a12035f3d2c6cb8bc0b6a70864fa14b1b50ed6b8e6eed5833e625e16cb6bb98b665beff269
languageName: node languageName: node
linkType: hard linkType: hard
@@ -8078,16 +8078,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-plugin-lit@npm:1.9.1, eslint-plugin-lit@npm:^1.6.0": "eslint-plugin-lit@npm:1.10.1, eslint-plugin-lit@npm:^1.6.0":
version: 1.9.1 version: 1.10.1
resolution: "eslint-plugin-lit@npm:1.9.1" resolution: "eslint-plugin-lit@npm:1.10.1"
dependencies: dependencies:
parse5: ^6.0.1 parse5: ^6.0.1
parse5-htmlparser2-tree-adapter: ^6.0.1 parse5-htmlparser2-tree-adapter: ^6.0.1
requireindex: ^1.2.0 requireindex: ^1.2.0
peerDependencies: peerDependencies:
eslint: ">= 5" eslint: ">= 5"
checksum: 24f9426b52587b483a5e195a1164cbf23323879a2c5f114673e5fb5413ba56d2a57309f39393fcc5a7486508faa05ba3da40fd3168f3c87f3d41473052cf80be checksum: f0661b17890f8579c413431e7ff29eeaf36a18c3c7fe683ebec9f91c2e55a3b9247370454dcf15c60497a2511e13f81dffb624825c180b8da413319de4c9b007
languageName: node languageName: node
linkType: hard linkType: hard
@@ -9601,13 +9601,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"has@npm:^1.0.3":
version: 1.0.4
resolution: "has@npm:1.0.4"
checksum: 8a11ba062e0627c9578a1d08285401e39f1d071a9692ddf793199070edb5648b21c774dd733e2a181edd635bf6862731885f476f4ccf67c998d7a5ff7cef2550
languageName: node
linkType: hard
"hasown@npm:^2.0.0": "hasown@npm:^2.0.0":
version: 2.0.0 version: 2.0.0
resolution: "hasown@npm:2.0.0" resolution: "hasown@npm:2.0.0"
@@ -9644,17 +9637,17 @@ __metadata:
"@babel/preset-typescript": 7.23.2 "@babel/preset-typescript": 7.23.2
"@babel/runtime": 7.23.2 "@babel/runtime": 7.23.2
"@braintree/sanitize-url": 6.0.4 "@braintree/sanitize-url": 6.0.4
"@bundle-stats/plugin-webpack-filter": 4.7.7 "@bundle-stats/plugin-webpack-filter": 4.7.8
"@codemirror/autocomplete": 6.10.2 "@codemirror/autocomplete": 6.10.2
"@codemirror/commands": 6.3.0 "@codemirror/commands": 6.3.0
"@codemirror/language": 6.9.1 "@codemirror/language": 6.9.2
"@codemirror/legacy-modes": 6.3.3 "@codemirror/legacy-modes": 6.3.3
"@codemirror/search": 6.5.4 "@codemirror/search": 6.5.4
"@codemirror/state": 6.3.1 "@codemirror/state": 6.3.1
"@codemirror/view": 6.21.3 "@codemirror/view": 6.21.4
"@egjs/hammerjs": 2.0.17 "@egjs/hammerjs": 2.0.17
"@formatjs/intl-datetimeformat": 6.11.0 "@formatjs/intl-datetimeformat": 6.11.1
"@formatjs/intl-displaynames": 6.6.0 "@formatjs/intl-displaynames": 6.6.1
"@formatjs/intl-getcanonicallocales": 2.3.0 "@formatjs/intl-getcanonicallocales": 2.3.0
"@formatjs/intl-listformat": 7.5.0 "@formatjs/intl-listformat": 7.5.0
"@formatjs/intl-locale": 3.4.0 "@formatjs/intl-locale": 3.4.0
@@ -9740,10 +9733,10 @@ __metadata:
"@types/tar": 6.1.7 "@types/tar": 6.1.7
"@types/ua-parser-js": 0.7.38 "@types/ua-parser-js": 0.7.38
"@types/webspeechapi": 0.0.29 "@types/webspeechapi": 0.0.29
"@typescript-eslint/eslint-plugin": 6.8.0 "@typescript-eslint/eslint-plugin": 6.9.0
"@typescript-eslint/parser": 6.8.0 "@typescript-eslint/parser": 6.9.0
"@vaadin/combo-box": 24.2.0 "@vaadin/combo-box": 24.2.1
"@vaadin/vaadin-themable-mixin": 24.2.0 "@vaadin/vaadin-themable-mixin": 24.2.1
"@vibrant/color": 3.2.1-alpha.1 "@vibrant/color": 3.2.1-alpha.1
"@vibrant/core": 3.2.1-alpha.1 "@vibrant/core": 3.2.1-alpha.1
"@vibrant/quantizer-mmcq": 3.2.1-alpha.1 "@vibrant/quantizer-mmcq": 3.2.1-alpha.1
@@ -9769,10 +9762,10 @@ __metadata:
eslint-config-airbnb-base: 15.0.0 eslint-config-airbnb-base: 15.0.0
eslint-config-airbnb-typescript: 17.1.0 eslint-config-airbnb-typescript: 17.1.0
eslint-config-prettier: 9.0.0 eslint-config-prettier: 9.0.0
eslint-import-resolver-webpack: 0.13.7 eslint-import-resolver-webpack: 0.13.8
eslint-plugin-disable: 2.0.3 eslint-plugin-disable: 2.0.3
eslint-plugin-import: 2.28.1 eslint-plugin-import: 2.29.0
eslint-plugin-lit: 1.9.1 eslint-plugin-lit: 1.10.1
eslint-plugin-lit-a11y: 4.1.0 eslint-plugin-lit-a11y: 4.1.0
eslint-plugin-unused-imports: 3.0.0 eslint-plugin-unused-imports: 3.0.0
eslint-plugin-wc: 2.0.4 eslint-plugin-wc: 2.0.4
@@ -9801,7 +9794,7 @@ __metadata:
leaflet-draw: 1.0.4 leaflet-draw: 1.0.4
lint-staged: 15.0.2 lint-staged: 15.0.2
lit: 2.8.0 lit: 2.8.0
lit-analyzer: 2.0.0-pre.3 lit-analyzer: 2.0.1
lodash.template: 4.5.0 lodash.template: 4.5.0
luxon: 3.4.3 luxon: 3.4.3
magic-string: 0.30.5 magic-string: 0.30.5
@@ -9835,7 +9828,7 @@ __metadata:
tar: 6.2.0 tar: 6.2.0
terser-webpack-plugin: 5.3.9 terser-webpack-plugin: 5.3.9
tinykeys: 2.1.0 tinykeys: 2.1.0
ts-lit-plugin: 2.0.0-pre.1 ts-lit-plugin: 2.0.0
tsparticles-engine: 2.12.0 tsparticles-engine: 2.12.0
tsparticles-preset-links: 2.12.0 tsparticles-preset-links: 2.12.0
typescript: 5.2.2 typescript: 5.2.2
@@ -9845,7 +9838,7 @@ __metadata:
vinyl-source-stream: 2.0.0 vinyl-source-stream: 2.0.0
vis-data: 7.1.7 vis-data: 7.1.7
vis-network: 9.1.8 vis-network: 9.1.8
vue: 2.7.14 vue: 2.7.15
vue2-daterange-picker: 0.6.8 vue2-daterange-picker: 0.6.8
webpack: 5.89.0 webpack: 5.89.0
webpack-cli: 5.1.4 webpack-cli: 5.1.4
@@ -10430,7 +10423,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"is-core-module@npm:^2.13.0": "is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1":
version: 2.13.1 version: 2.13.1
resolution: "is-core-module@npm:2.13.1" resolution: "is-core-module@npm:2.13.1"
dependencies: dependencies:
@@ -11431,9 +11424,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"lit-analyzer@npm:2.0.0-pre.3, lit-analyzer@npm:^2.0.0-pre.3": "lit-analyzer@npm:2.0.1, lit-analyzer@npm:^2.0.0":
version: 2.0.0-pre.3 version: 2.0.1
resolution: "lit-analyzer@npm:2.0.0-pre.3" resolution: "lit-analyzer@npm:2.0.1"
dependencies: dependencies:
"@vscode/web-custom-data": ^0.4.2 "@vscode/web-custom-data": ^0.4.2
chalk: ^2.4.2 chalk: ^2.4.2
@@ -11443,10 +11436,10 @@ __metadata:
ts-simple-type: ~2.0.0-next.0 ts-simple-type: ~2.0.0-next.0
vscode-css-languageservice: 4.3.0 vscode-css-languageservice: 4.3.0
vscode-html-languageservice: 3.1.0 vscode-html-languageservice: 3.1.0
web-component-analyzer: ^2.0.0-next.5 web-component-analyzer: ^2.0.0
bin: bin:
lit-analyzer: cli.js lit-analyzer: cli.js
checksum: c6dcf657a0030342d183fcd9d550753bd5dd0692b478aff271085a5a0e7e08aff39cc6dde3d547ffca72897975ef07aac7de8a97e0060d2db70a85350412efae checksum: 73ec7a6d20a7b74a6027a7581c48b31c79b33ae10c14629f13604fa01edf9d8434d01ef30f31a8a0f11d9a2c8dce15b8b2d34bcce48d8e4487d16cf8b58d081b
languageName: node languageName: node
linkType: hard linkType: hard
@@ -12552,7 +12545,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"object.fromentries@npm:^2.0.6": "object.fromentries@npm:^2.0.7":
version: 2.0.7 version: 2.0.7
resolution: "object.fromentries@npm:2.0.7" resolution: "object.fromentries@npm:2.0.7"
dependencies: dependencies:
@@ -12563,7 +12556,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"object.groupby@npm:^1.0.0": "object.groupby@npm:^1.0.1":
version: 1.0.1 version: 1.0.1
resolution: "object.groupby@npm:1.0.1" resolution: "object.groupby@npm:1.0.1"
dependencies: dependencies:
@@ -12604,7 +12597,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"object.values@npm:^1.1.6": "object.values@npm:^1.1.7":
version: 1.1.7 version: 1.1.7
resolution: "object.values@npm:1.1.7" resolution: "object.values@npm:1.1.7"
dependencies: dependencies:
@@ -13861,7 +13854,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"resolve@npm:^2.0.0-next.4": "resolve@npm:^2.0.0-next.5":
version: 2.0.0-next.5 version: 2.0.0-next.5
resolution: "resolve@npm:2.0.0-next.5" resolution: "resolve@npm:2.0.0-next.5"
dependencies: dependencies:
@@ -13887,7 +13880,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"resolve@patch:resolve@^2.0.0-next.4#~builtin<compat/resolve>": "resolve@patch:resolve@^2.0.0-next.5#~builtin<compat/resolve>":
version: 2.0.0-next.5 version: 2.0.0-next.5
resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#~builtin<compat/resolve>::version=2.0.0-next.5&hash=c3c19d" resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#~builtin<compat/resolve>::version=2.0.0-next.5&hash=c3c19d"
dependencies: dependencies:
@@ -15392,13 +15385,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ts-lit-plugin@npm:2.0.0-pre.1": "ts-lit-plugin@npm:2.0.0":
version: 2.0.0-pre.1 version: 2.0.0
resolution: "ts-lit-plugin@npm:2.0.0-pre.1" resolution: "ts-lit-plugin@npm:2.0.0"
dependencies: dependencies:
lit-analyzer: ^2.0.0-pre.3 lit-analyzer: ^2.0.0
web-component-analyzer: ^2.0.0-next.5 web-component-analyzer: ^2.0.0
checksum: d9c8b3c0d8867e9564c7a3083accaf9f8b48b04c8f42e32c224806a7a606983abb3b7acb912e57d0d8f90ff650745bb1af18b1e379316b433838e37eddccfe1e checksum: 1dd6ceffb98d03c81de5a7874c81058cfda6be7a4b4cd760acab1776b9bb32143117aca9ff4c922118e83d919e0a09fc4fa21160ff7133a2133ef9d9e7eea2fc
languageName: node languageName: node
linkType: hard linkType: hard
@@ -16141,13 +16134,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"vue@npm:2.7.14, vue@npm:^2.6.10": "vue@npm:2.7.15, vue@npm:^2.6.10":
version: 2.7.14 version: 2.7.15
resolution: "vue@npm:2.7.14" resolution: "vue@npm:2.7.15"
dependencies: dependencies:
"@vue/compiler-sfc": 2.7.14 "@vue/compiler-sfc": 2.7.15
csstype: ^3.1.0 csstype: ^3.1.0
checksum: 8b06da67cc40870c66a30b7a6bc2874950cd4383792c371eb30497dd14fc7b41cf308b1c4517368d8f0e7ac16198c08de19236f6a79fe43f4bdbc4a1d9d4ad07 checksum: b829a42b60a3388c23735390412011c7859226ba6eb43ceda8eabb295e67b00d3db941b8fa8660682f463ed1028a2da8dff6db29a72efd67f0fc0088de1bb334
languageName: node languageName: node
linkType: hard linkType: hard
@@ -16177,7 +16170,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"web-component-analyzer@npm:^2.0.0-next.5": "web-component-analyzer@npm:^2.0.0":
version: 2.0.0 version: 2.0.0
resolution: "web-component-analyzer@npm:2.0.0" resolution: "web-component-analyzer@npm:2.0.0"
dependencies: dependencies: