From cd55eee2fcd2c616b31072826054ba3815b932cb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 15:19:05 -0400 Subject: [PATCH 01/81] Update dependency @babel/core to v7.22.17 (#17899) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 262274bbb5..ae5be484c6 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "xss": "1.0.14" }, "devDependencies": { - "@babel/core": "7.22.15", + "@babel/core": "7.22.17", "@babel/plugin-proposal-decorators": "7.22.15", "@babel/plugin-transform-runtime": "7.22.15", "@babel/preset-env": "7.22.15", diff --git a/yarn.lock b/yarn.lock index 549eddc8a5..9981055942 100644 --- a/yarn.lock +++ b/yarn.lock @@ -62,26 +62,26 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:7.22.15, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": - version: 7.22.15 - resolution: "@babel/core@npm:7.22.15" +"@babel/core@npm:7.22.17, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": + version: 7.22.17 + resolution: "@babel/core@npm:7.22.17" dependencies: "@ampproject/remapping": ^2.2.0 "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.22.15 "@babel/helper-compilation-targets": ^7.22.15 - "@babel/helper-module-transforms": ^7.22.15 + "@babel/helper-module-transforms": ^7.22.17 "@babel/helpers": ^7.22.15 - "@babel/parser": ^7.22.15 + "@babel/parser": ^7.22.16 "@babel/template": ^7.22.15 - "@babel/traverse": ^7.22.15 - "@babel/types": ^7.22.15 + "@babel/traverse": ^7.22.17 + "@babel/types": ^7.22.17 convert-source-map: ^1.7.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: 80b3705f2f809f024ac065d73b9bcde991ac5789c38320e00890862200b1603b68035cba7b13ecd827479c7d9ea9b5998ac0a1b7fd28940bcf587fb1301e994a + checksum: 355216a342d1b3952d7c040dd4c99ecef6b3501ba99a713703c1fec1ae73bc92a48a0c1234562bdbb4fd334b2e452f5a6c3bb282f0e613fa89e1518c91d1aea1 languageName: node linkType: hard @@ -219,9 +219,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.22.15, @babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9": - version: 7.22.15 - resolution: "@babel/helper-module-transforms@npm:7.22.15" +"@babel/helper-module-transforms@npm:^7.22.15, @babel/helper-module-transforms@npm:^7.22.17, @babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9": + version: 7.22.17 + resolution: "@babel/helper-module-transforms@npm:7.22.17" dependencies: "@babel/helper-environment-visitor": ^7.22.5 "@babel/helper-module-imports": ^7.22.15 @@ -230,7 +230,7 @@ __metadata: "@babel/helper-validator-identifier": ^7.22.15 peerDependencies: "@babel/core": ^7.0.0 - checksum: de571fa352331bb5d5d56e95239c2e5dd79a1454e5167f3d80820d4975ee95052f8198e9fc1310015c55a0407b7566f8ca9d86cf262046884847aa24f8139bca + checksum: 458021c74093e66179765fcc9d1c1cb694f7bdf98656f23486901d35636495c38aab4661547fac2142e13d887987d1ea30cc9fe42968376a51a99bcd207b4989 languageName: node linkType: hard @@ -357,7 +357,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.18.4, @babel/parser@npm:^7.22.15": +"@babel/parser@npm:^7.18.4, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.16": version: 7.22.16 resolution: "@babel/parser@npm:7.22.16" bin: @@ -1401,9 +1401,9 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/traverse@npm:7.22.15" +"@babel/traverse@npm:^7.22.15, @babel/traverse@npm:^7.22.17": + version: 7.22.17 + resolution: "@babel/traverse@npm:7.22.17" dependencies: "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.22.15 @@ -1411,22 +1411,22 @@ __metadata: "@babel/helper-function-name": ^7.22.5 "@babel/helper-hoist-variables": ^7.22.5 "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/parser": ^7.22.15 - "@babel/types": ^7.22.15 + "@babel/parser": ^7.22.16 + "@babel/types": ^7.22.17 debug: ^4.1.0 globals: ^11.1.0 - checksum: 12aba7da6fd6109905d5086e1a9d1aea2cdbb0b80533d2d235d5dad2ff97f0315173c063023e601e96086dfeaaeb97f9d3cbaf38a10f04820e47e2848607cef4 + checksum: 1153ca166a0a9b3fddf67f7f7c8c5b4f88aa2c2c00261ff2fc8424a63bc93250ed3fd08b04bd526ad19e797aeb6f22161120646a570cbfe5ff2a5d2f5d28af01 languageName: node linkType: hard -"@babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.22.15 - resolution: "@babel/types@npm:7.22.15" +"@babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.17, @babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.22.17 + resolution: "@babel/types@npm:7.22.17" dependencies: "@babel/helper-string-parser": ^7.22.5 "@babel/helper-validator-identifier": ^7.22.15 to-fast-properties: ^2.0.0 - checksum: a2aa59746dc8500c358a3a9afca2adff49dbade009d616aa8308714485064f2218da04e1823f1243a4992f1424ec6d6719e76a7af9a0ac3647227dca3015eea4 + checksum: 7382220f6eb2548f2c867a98916c3aa8a6063498d5372e5d21d8d184ba354033defb72aeba5858c1b2b42177058b896a34a7dcbae5eccd47fb0104721efa909d languageName: node linkType: hard @@ -9677,7 +9677,7 @@ __metadata: version: 0.0.0-use.local resolution: "home-assistant-frontend@workspace:." dependencies: - "@babel/core": 7.22.15 + "@babel/core": 7.22.17 "@babel/plugin-proposal-decorators": 7.22.15 "@babel/plugin-transform-runtime": 7.22.15 "@babel/preset-env": 7.22.15 From f689eed073df3be5c9b47d08f7fad3f19123ae5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 15:22:18 -0400 Subject: [PATCH 02/81] Bump actions/checkout from 3.6.0 to 4.0.0 (#17891) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.6.0...v4.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/cast_deployment.yaml | 4 ++-- .github/workflows/ci.yaml | 8 ++++---- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/demo_deployment.yaml | 4 ++-- .github/workflows/design_deployment.yaml | 2 +- .github/workflows/design_preview.yaml | 2 +- .github/workflows/nightly.yaml | 2 +- .github/workflows/release.yaml | 2 +- .github/workflows/translations.yaml | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/cast_deployment.yaml b/.github/workflows/cast_deployment.yaml index 02c9685cf9..614e2d7491 100644 --- a/.github/workflows/cast_deployment.yaml +++ b/.github/workflows/cast_deployment.yaml @@ -21,7 +21,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 with: ref: dev @@ -57,7 +57,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 with: ref: master diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8a0bb9007a..7b9697e98c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Setup Node uses: actions/setup-node@v3.8.1 with: @@ -55,7 +55,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Setup Node uses: actions/setup-node@v3.8.1 with: @@ -73,7 +73,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Setup Node uses: actions/setup-node@v3.8.1 with: @@ -91,7 +91,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Setup Node uses: actions/setup-node@v3.8.1 with: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8524377b15..3090afe241 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/demo_deployment.yaml b/.github/workflows/demo_deployment.yaml index 42b11086ba..cc3cd95ec0 100644 --- a/.github/workflows/demo_deployment.yaml +++ b/.github/workflows/demo_deployment.yaml @@ -22,7 +22,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 with: ref: dev @@ -58,7 +58,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 with: ref: master diff --git a/.github/workflows/design_deployment.yaml b/.github/workflows/design_deployment.yaml index b4e977a47c..0c7ff74109 100644 --- a/.github/workflows/design_deployment.yaml +++ b/.github/workflows/design_deployment.yaml @@ -16,7 +16,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Setup Node uses: actions/setup-node@v3.8.1 diff --git a/.github/workflows/design_preview.yaml b/.github/workflows/design_preview.yaml index ddf525bc9d..1a5ccca6aa 100644 --- a/.github/workflows/design_preview.yaml +++ b/.github/workflows/design_preview.yaml @@ -21,7 +21,7 @@ jobs: if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview') steps: - name: Check out files from GitHub - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Setup Node uses: actions/setup-node@v3.8.1 diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index bd00794e73..c960f1cd2a 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -20,7 +20,7 @@ jobs: contents: write steps: - name: Checkout the repository - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v4 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8567348e7c..c28fd2a828 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,7 +23,7 @@ jobs: contents: write # Required to upload release assets steps: - name: Checkout the repository - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Verify version uses: home-assistant/actions/helpers/verify-version@master diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml index f9586f91a5..ecc4810fb9 100644 --- a/.github/workflows/translations.yaml +++ b/.github/workflows/translations.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repository - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Upload Translations run: | From 709a63e6da6e8269c4d2302067fdf8b8bac88948 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Mon, 11 Sep 2023 13:54:45 -0700 Subject: [PATCH 03/81] Fix schedule helper form when resizing or dragging to or past midnight (#17900) --- src/panels/config/helpers/forms/ha-schedule-form.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/panels/config/helpers/forms/ha-schedule-form.ts b/src/panels/config/helpers/forms/ha-schedule-form.ts index d592a5ec93..f697073b59 100644 --- a/src/panels/config/helpers/forms/ha-schedule-form.ts +++ b/src/panels/config/helpers/forms/ha-schedule-form.ts @@ -340,6 +340,7 @@ class HaScheduleForm extends LitElement { }); if (!isSameDay(start, end)) { + this.requestUpdate(`_${day}`); info.revert(); } } @@ -374,6 +375,7 @@ class HaScheduleForm extends LitElement { }); if (!isSameDay(start, end)) { + this.requestUpdate(`_${day}`); info.revert(); } } From c60e5c4c612e94a50c91082e30a356a5c9d54fd7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 20:41:20 -0400 Subject: [PATCH 04/81] Update dependency eslint to v8.49.0 (#17904) --- package.json | 2 +- yarn.lock | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index ae5be484c6..a3c97c1305 100644 --- a/package.json +++ b/package.json @@ -194,7 +194,7 @@ "babel-plugin-template-html-minifier": "4.1.0", "chai": "4.3.8", "del": "7.1.0", - "eslint": "8.48.0", + "eslint": "8.49.0", "eslint-config-airbnb-base": "15.0.0", "eslint-config-airbnb-typescript": "17.1.0", "eslint-config-prettier": "9.0.0", diff --git a/yarn.lock b/yarn.lock index 9981055942..d537670897 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1578,10 +1578,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.48.0": - version: 8.48.0 - resolution: "@eslint/js@npm:8.48.0" - checksum: b2755f9c0ee810c886eba3c50dcacb184ba5a5cd1cbc01988ee506ad7340653cae0bd55f1d95c64b56dfc6d25c2caa7825335ffd2c50165bae9996fe0f396851 +"@eslint/js@npm:8.49.0": + version: 8.49.0 + resolution: "@eslint/js@npm:8.49.0" + checksum: a6601807c8aeeefe866926ad92ed98007c034a735af20ff709009e39ad1337474243d47908500a3bde04e37bfba16bcf1d3452417f962e1345bc8756edd6b830 languageName: node linkType: hard @@ -1796,14 +1796,14 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.10": - version: 0.11.10 - resolution: "@humanwhocodes/config-array@npm:0.11.10" +"@humanwhocodes/config-array@npm:^0.11.11": + version: 0.11.11 + resolution: "@humanwhocodes/config-array@npm:0.11.11" dependencies: "@humanwhocodes/object-schema": ^1.2.1 debug: ^4.1.1 minimatch: ^3.0.5 - checksum: 1b1302e2403d0e35bc43e66d67a2b36b0ad1119efc704b5faff68c41f791a052355b010fb2d27ef022670f550de24cd6d08d5ecf0821c16326b7dcd0ee5d5d8a + checksum: db84507375ab77b8ffdd24f498a5b49ad6b64391d30dd2ac56885501d03964d29637e05b1ed5aefa09d57ac667e28028bc22d2da872bfcd619652fbdb5f4ca19 languageName: node linkType: hard @@ -8206,15 +8206,15 @@ __metadata: languageName: node linkType: hard -"eslint@npm:8.48.0": - version: 8.48.0 - resolution: "eslint@npm:8.48.0" +"eslint@npm:8.49.0": + version: 8.49.0 + resolution: "eslint@npm:8.49.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 "@eslint/eslintrc": ^2.1.2 - "@eslint/js": 8.48.0 - "@humanwhocodes/config-array": ^0.11.10 + "@eslint/js": 8.49.0 + "@humanwhocodes/config-array": ^0.11.11 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 ajv: ^6.12.4 @@ -8249,7 +8249,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: f20b359a4f8123fec5c033577368cc020d42978b1b45303974acd8da7a27063168ee3fe297ab5b35327162f6a93154063e3ce6577102f70f9809aff793db9bd0 + checksum: 4dfe257e1e42da2f9da872b05aaaf99b0f5aa022c1a91eee8f2af1ab72651b596366320c575ccd4e0469f7b4c97aff5bb85ae3323ebd6a293c3faef4028b0d81 languageName: node linkType: hard @@ -9803,7 +9803,7 @@ __metadata: deep-clone-simple: 1.1.1 deep-freeze: 0.0.1 del: 7.1.0 - eslint: 8.48.0 + eslint: 8.49.0 eslint-config-airbnb-base: 15.0.0 eslint-config-airbnb-typescript: 17.1.0 eslint-config-prettier: 9.0.0 From 7b0b4cdfe4838cd0eeba41dc94845bc84dc6db81 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 20:59:49 -0400 Subject: [PATCH 05/81] Update dependency @codemirror/view to v6.18.0 (#17865) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a3c97c1305..eb777ccfda 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@codemirror/legacy-modes": "6.3.3", "@codemirror/search": "6.5.2", "@codemirror/state": "6.2.1", - "@codemirror/view": "6.17.1", + "@codemirror/view": "6.18.0", "@egjs/hammerjs": "2.0.17", "@formatjs/intl-datetimeformat": "6.10.0", "@formatjs/intl-displaynames": "6.5.0", diff --git a/yarn.lock b/yarn.lock index d537670897..12764664b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1507,14 +1507,14 @@ __metadata: languageName: node linkType: hard -"@codemirror/view@npm:6.17.1, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.6.0": - version: 6.17.1 - resolution: "@codemirror/view@npm:6.17.1" +"@codemirror/view@npm:6.18.0, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.6.0": + version: 6.18.0 + resolution: "@codemirror/view@npm:6.18.0" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.1.0 w3c-keyname: ^2.2.4 - checksum: b70a50632817c75b39f60f1a962206e64787fc58fc7b1d6ce883dc2302d4dcfe077003c9c307358791c1150c96ae623140f069537a6b705f1c3526b2e41954a5 + checksum: 275bf5898e884297f16f73e4dff1b520a196a5f7724fbeda634a927e7f4036f6786e816b124505942de99800fb66c538307e8c08e55234ad57483f1a009e3d35 languageName: node linkType: hard @@ -9690,7 +9690,7 @@ __metadata: "@codemirror/legacy-modes": 6.3.3 "@codemirror/search": 6.5.2 "@codemirror/state": 6.2.1 - "@codemirror/view": 6.17.1 + "@codemirror/view": 6.18.0 "@egjs/hammerjs": 2.0.17 "@formatjs/intl-datetimeformat": 6.10.0 "@formatjs/intl-displaynames": 6.5.0 From 50f4b78f2e4e114737d93cb3aa6017aa0efa5f73 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 11:45:17 -0400 Subject: [PATCH 06/81] Update dependency ua-parser-js to v1.0.36 (#17912) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index eb777ccfda..93b477e785 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "tinykeys": "2.1.0", "tsparticles-engine": "2.12.0", "tsparticles-preset-links": "2.12.0", - "ua-parser-js": "1.0.35", + "ua-parser-js": "1.0.36", "unfetch": "5.0.0", "vis-data": "7.1.6", "vis-network": "9.1.6", diff --git a/yarn.lock b/yarn.lock index 12764664b4..0d60b2519c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9877,7 +9877,7 @@ __metadata: tsparticles-engine: 2.12.0 tsparticles-preset-links: 2.12.0 typescript: 5.2.2 - ua-parser-js: 1.0.35 + ua-parser-js: 1.0.36 unfetch: 5.0.0 vinyl-buffer: 1.0.1 vinyl-source-stream: 2.0.0 @@ -15788,10 +15788,10 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:1.0.35": - version: 1.0.35 - resolution: "ua-parser-js@npm:1.0.35" - checksum: 02370d38a0c8b586f2503d1c3bbba5cbc0b97d407282f9023201a99e4c03eae4357a2800fdf50cf80d73ec25c0b0cc5bfbaa03975b0add4043d6e4c86712c9c1 +"ua-parser-js@npm:1.0.36": + version: 1.0.36 + resolution: "ua-parser-js@npm:1.0.36" + checksum: 5b2c8a5e3443dfbba7624421805de946457c26ae167cb2275781a2729d1518f7067c9d5c74c3b0acac4b9ff3278cae4eace08ca6eecb63848bc3b2f6a63cc975 languageName: node linkType: hard From b511e7a37d4254db56a132c95cbf6602bf85ff2d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 20:38:23 -0400 Subject: [PATCH 07/81] Update vaadinWebComponents monorepo to v24.1.7 (#17894) --- package.json | 4 +- yarn.lock | 166 +++++++++++++++++++++++++-------------------------- 2 files changed, 85 insertions(+), 85 deletions(-) diff --git a/package.json b/package.json index 93b477e785..944205d9e1 100644 --- a/package.json +++ b/package.json @@ -93,8 +93,8 @@ "@polymer/paper-toast": "3.0.1", "@polymer/polymer": "3.5.1", "@thomasloven/round-slider": "0.6.0", - "@vaadin/combo-box": "24.1.6", - "@vaadin/vaadin-themable-mixin": "24.1.6", + "@vaadin/combo-box": "24.1.7", + "@vaadin/vaadin-themable-mixin": "24.1.7", "@vibrant/color": "3.2.1-alpha.1", "@vibrant/core": "3.2.1-alpha.1", "@vibrant/quantizer-mmcq": "3.2.1-alpha.1", diff --git a/yarn.lock b/yarn.lock index 0d60b2519c..d48b72a495 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4764,126 +4764,126 @@ __metadata: languageName: node linkType: hard -"@vaadin/a11y-base@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/a11y-base@npm:24.1.6" +"@vaadin/a11y-base@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/a11y-base@npm:24.1.7" dependencies: "@open-wc/dedupe-mixin": ^1.3.0 "@polymer/polymer": ^3.0.0 - "@vaadin/component-base": ~24.1.6 + "@vaadin/component-base": ~24.1.7 lit: ^2.0.0 - checksum: 5f739cba4c950d8a4f0ce9bfdab296241c922389fdf9929e371c11e76f0b33d961d0dacc4bbeae8c04b6fbc68a194db631bb49cf415670fa63fb49007f90d01c + checksum: 98213a16b99de226663e0bf0b723cb557dd1d3efbe2b813447a6de3fba70c1dc7fc68380b17a0baaf461f2bbb811f4a12502d32d4526ae2988d1d9dcac7c203a languageName: node linkType: hard -"@vaadin/combo-box@npm:24.1.6": - version: 24.1.6 - resolution: "@vaadin/combo-box@npm:24.1.6" +"@vaadin/combo-box@npm:24.1.7": + version: 24.1.7 + resolution: "@vaadin/combo-box@npm:24.1.7" dependencies: "@open-wc/dedupe-mixin": ^1.3.0 "@polymer/polymer": ^3.0.0 - "@vaadin/a11y-base": ~24.1.6 - "@vaadin/component-base": ~24.1.6 - "@vaadin/field-base": ~24.1.6 - "@vaadin/input-container": ~24.1.6 - "@vaadin/item": ~24.1.6 - "@vaadin/lit-renderer": ~24.1.6 - "@vaadin/overlay": ~24.1.6 - "@vaadin/vaadin-lumo-styles": ~24.1.6 - "@vaadin/vaadin-material-styles": ~24.1.6 - "@vaadin/vaadin-themable-mixin": ~24.1.6 - checksum: e5c1579af87612acbc66b5d64ab85d674c7be179feec3659e879400021277c2edee8b117d0ae5742e6026bbb5d2631b59a55c4273be8d828a0397b4c682725c7 + "@vaadin/a11y-base": ~24.1.7 + "@vaadin/component-base": ~24.1.7 + "@vaadin/field-base": ~24.1.7 + "@vaadin/input-container": ~24.1.7 + "@vaadin/item": ~24.1.7 + "@vaadin/lit-renderer": ~24.1.7 + "@vaadin/overlay": ~24.1.7 + "@vaadin/vaadin-lumo-styles": ~24.1.7 + "@vaadin/vaadin-material-styles": ~24.1.7 + "@vaadin/vaadin-themable-mixin": ~24.1.7 + checksum: 64988abcf7c7693f0b6c561efd7d6bdb874df010aeba4be9c60aeae840869da4008b33e6b8722b67621320348fa0a8ebf50c4a6f65458d525b0076047c01ac4c languageName: node linkType: hard -"@vaadin/component-base@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/component-base@npm:24.1.6" +"@vaadin/component-base@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/component-base@npm:24.1.7" dependencies: "@open-wc/dedupe-mixin": ^1.3.0 "@polymer/polymer": ^3.0.0 "@vaadin/vaadin-development-mode-detector": ^2.0.0 "@vaadin/vaadin-usage-statistics": ^2.1.0 lit: ^2.0.0 - checksum: 034da5eb6367ca2e6b1f129fee453341390f967a05a8fec15c66316a0f5d6de78c534e6e41bb4a5acbb93075b4405b0018f7f64c6d8d09add0b949174164ec2b + checksum: f98fcb6eb6785431d56c3a1e64ec3e314ef8e6b332fd177f5972a9418a8f39da0fa9a8a916799a89e39f75abd3229885cf8a5387ba1fe1dddd41fd964fec484a languageName: node linkType: hard -"@vaadin/field-base@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/field-base@npm:24.1.6" +"@vaadin/field-base@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/field-base@npm:24.1.7" dependencies: "@open-wc/dedupe-mixin": ^1.3.0 "@polymer/polymer": ^3.0.0 - "@vaadin/a11y-base": ~24.1.6 - "@vaadin/component-base": ~24.1.6 + "@vaadin/a11y-base": ~24.1.7 + "@vaadin/component-base": ~24.1.7 lit: ^2.0.0 - checksum: 547324a7c84781781979eec988740acac8c2eefc4be3fef5953a668ff43b7ebc8bb7373fb3f32b3874ddc1f32965c4c98381a8ff38f1822e39ca5173c8163115 + checksum: 56835ca3702943a2920aeb1e0ad0562cc3aa1473e69bddcc34ba6e54a9fa3f61bec43bc1f350c41d5efd5b28f51f1a972ed301a698c32965c41936d275ac7b6f languageName: node linkType: hard -"@vaadin/icon@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/icon@npm:24.1.6" +"@vaadin/icon@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/icon@npm:24.1.7" dependencies: "@polymer/polymer": ^3.0.0 - "@vaadin/component-base": ~24.1.6 - "@vaadin/vaadin-lumo-styles": ~24.1.6 - "@vaadin/vaadin-themable-mixin": ~24.1.6 + "@vaadin/component-base": ~24.1.7 + "@vaadin/vaadin-lumo-styles": ~24.1.7 + "@vaadin/vaadin-themable-mixin": ~24.1.7 lit: ^2.0.0 - checksum: dfb5c8d586f058c0bc09e17562e469325aef6fffaa3fe27024c6782c787c0a9ab774cdf121ce4a7da4c08418ffc6d4a5a0f101f60064a29d0f2c73973b34c101 + checksum: 7a7e7598da6aa7f8af39f2d05fe1e74878d772556e5b35c96c3500bb6c8e008a90d606e9276fd031bdd046765a22775eced3d18238d9fa039fbc77df8afe4bbe languageName: node linkType: hard -"@vaadin/input-container@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/input-container@npm:24.1.6" +"@vaadin/input-container@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/input-container@npm:24.1.7" dependencies: "@polymer/polymer": ^3.0.0 - "@vaadin/component-base": ~24.1.6 - "@vaadin/vaadin-lumo-styles": ~24.1.6 - "@vaadin/vaadin-material-styles": ~24.1.6 - "@vaadin/vaadin-themable-mixin": ~24.1.6 - checksum: 0f36911a99f76afec7bbbbe36972edb7bebdaea270dbe1457cbe4c29d0ed250616f2dd41bc97f28aa9486151980ffb133293d6cb02547ff496d4986343ea47fb + "@vaadin/component-base": ~24.1.7 + "@vaadin/vaadin-lumo-styles": ~24.1.7 + "@vaadin/vaadin-material-styles": ~24.1.7 + "@vaadin/vaadin-themable-mixin": ~24.1.7 + checksum: b859fed9b35be08140eb7ac83c3750a4e42160bdb14068cbd237f99bed1f06fe1980472b5dc2feea436c22555826ae1d8400ec51c1e278bf49cb12b2bd2e61b4 languageName: node linkType: hard -"@vaadin/item@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/item@npm:24.1.6" +"@vaadin/item@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/item@npm:24.1.7" dependencies: "@open-wc/dedupe-mixin": ^1.3.0 "@polymer/polymer": ^3.0.0 - "@vaadin/a11y-base": ~24.1.6 - "@vaadin/component-base": ~24.1.6 - "@vaadin/vaadin-lumo-styles": ~24.1.6 - "@vaadin/vaadin-material-styles": ~24.1.6 - "@vaadin/vaadin-themable-mixin": ~24.1.6 - checksum: 815b7aa44370c0f1b0166390134868995987c8349a53725b014475eaf2cf0db034c95948424c882b2dc8c5405994b9ffdd897022781243727039bc542ad1bf5e + "@vaadin/a11y-base": ~24.1.7 + "@vaadin/component-base": ~24.1.7 + "@vaadin/vaadin-lumo-styles": ~24.1.7 + "@vaadin/vaadin-material-styles": ~24.1.7 + "@vaadin/vaadin-themable-mixin": ~24.1.7 + checksum: 979c1e4dcd5474851543655a4a9b5873699d1a96ee5b92fdd15692460dfe07ccc8710ec802f5415ca56423b29b5cc01cf912f39d41faa3628b92f67771f71f3b languageName: node linkType: hard -"@vaadin/lit-renderer@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/lit-renderer@npm:24.1.6" +"@vaadin/lit-renderer@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/lit-renderer@npm:24.1.7" dependencies: lit: ^2.0.0 - checksum: 4aee7c9b204db58146fbb1a08d5b9eb6636fdc52c44dc3ca94b37e3f5caa95255a0dcf4ceaf62a6a32a5426a144954e64733d9b4f14fde2d6fe8bbdec9270118 + checksum: 21ef1489376fcab61cd974501b03640e67d58807eec414201a607014d80408329443102e78b198922f68c4c2e99b7154b2e550b4463344f05f8d5830d8212d45 languageName: node linkType: hard -"@vaadin/overlay@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/overlay@npm:24.1.6" +"@vaadin/overlay@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/overlay@npm:24.1.7" dependencies: "@open-wc/dedupe-mixin": ^1.3.0 "@polymer/polymer": ^3.0.0 - "@vaadin/a11y-base": ~24.1.6 - "@vaadin/component-base": ~24.1.6 - "@vaadin/vaadin-lumo-styles": ~24.1.6 - "@vaadin/vaadin-material-styles": ~24.1.6 - "@vaadin/vaadin-themable-mixin": ~24.1.6 - checksum: 34829445869911439222749814783863e603cc4162486016e7bc73b83cc414dab479bc51e6f13d1afab4c1536782d9257cab5af6c3f7f5115d70e11ca0ea04f9 + "@vaadin/a11y-base": ~24.1.7 + "@vaadin/component-base": ~24.1.7 + "@vaadin/vaadin-lumo-styles": ~24.1.7 + "@vaadin/vaadin-material-styles": ~24.1.7 + "@vaadin/vaadin-themable-mixin": ~24.1.7 + checksum: b892b82ca44c90d89657f021e680e1a67caf64a0081efdd9d5977bb4b884b4a71e37e367a417e473c13a38c4f4a58f65788e2f18a11b19214e02fdc81c1e7cdf languageName: node linkType: hard @@ -4894,34 +4894,34 @@ __metadata: languageName: node linkType: hard -"@vaadin/vaadin-lumo-styles@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/vaadin-lumo-styles@npm:24.1.6" +"@vaadin/vaadin-lumo-styles@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/vaadin-lumo-styles@npm:24.1.7" dependencies: "@polymer/polymer": ^3.0.0 - "@vaadin/icon": ~24.1.6 - "@vaadin/vaadin-themable-mixin": ~24.1.6 - checksum: 5cf898c166c9ad369e384b493b0b0b0e0ae98388056fb7b6e5539a05a0be87cd48499f184cbe48be8222092abec8386fe36549d4588bfc2b2150fda8acd09c65 + "@vaadin/icon": ~24.1.7 + "@vaadin/vaadin-themable-mixin": ~24.1.7 + checksum: 69961a8ace622ccdc3c373b4049cad1e8bca70d4c0664150a819001c61c73f72783d376980aa1b25ebd7d008c629586267adaf6c53c8ecb447532f38e0225266 languageName: node linkType: hard -"@vaadin/vaadin-material-styles@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/vaadin-material-styles@npm:24.1.6" +"@vaadin/vaadin-material-styles@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/vaadin-material-styles@npm:24.1.7" dependencies: "@polymer/polymer": ^3.0.0 - "@vaadin/vaadin-themable-mixin": ~24.1.6 - checksum: 27a3bd5651338419e0b3ecc63fc7186c2ae8db0e6029ebb5b0ab935f1abc52ff0d8a7e7134916019b61bb6b156e9e2e051ea175f7b7c568c8164e959a50a75f0 + "@vaadin/vaadin-themable-mixin": ~24.1.7 + checksum: 46af1012b57654c6359d2edae24b52bee52661cae4d8ab5a4dc119c5197cbb5595be5c68ecf907ac9de87500f88ce5ef7bcc15d13a77590178d4fc8ec139861c languageName: node linkType: hard -"@vaadin/vaadin-themable-mixin@npm:24.1.6, @vaadin/vaadin-themable-mixin@npm:~24.1.6": - version: 24.1.6 - resolution: "@vaadin/vaadin-themable-mixin@npm:24.1.6" +"@vaadin/vaadin-themable-mixin@npm:24.1.7, @vaadin/vaadin-themable-mixin@npm:~24.1.7": + version: 24.1.7 + resolution: "@vaadin/vaadin-themable-mixin@npm:24.1.7" dependencies: "@open-wc/dedupe-mixin": ^1.3.0 lit: ^2.0.0 - checksum: b80493fb7445ad6ba5c5bb272b544541625abbb62f06bc4d7c15c1f8d68addba6c4ac2b0c86b433e192b40bb0fd18c439687c0a6cc735dd7dbbdee93408976d1 + checksum: c59177e2f3b3bde695a7a1510c4d1760f6e47aa2e838d64d0213279c4c0fd36abcdb3dcf55d28bfd13610bc3a596108d39e4957e1716dc566935d9846c268560 languageName: node linkType: hard @@ -9780,8 +9780,8 @@ __metadata: "@types/webspeechapi": 0.0.29 "@typescript-eslint/eslint-plugin": 6.6.0 "@typescript-eslint/parser": 6.6.0 - "@vaadin/combo-box": 24.1.6 - "@vaadin/vaadin-themable-mixin": 24.1.6 + "@vaadin/combo-box": 24.1.7 + "@vaadin/vaadin-themable-mixin": 24.1.7 "@vibrant/color": 3.2.1-alpha.1 "@vibrant/core": 3.2.1-alpha.1 "@vibrant/quantizer-mmcq": 3.2.1-alpha.1 From b950f990b4d88504c3a6633022f88860eb8cd727 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 10:11:13 +0200 Subject: [PATCH 08/81] Update dependency @material/web to v1.0.0-pre.17 (#17882) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 944205d9e1..52200ca9d0 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "@material/mwc-top-app-bar": "0.27.0", "@material/mwc-top-app-bar-fixed": "0.27.0", "@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0", - "@material/web": "=1.0.0-pre.16", + "@material/web": "=1.0.0-pre.17", "@mdi/js": "7.2.96", "@mdi/svg": "7.2.96", "@polymer/iron-flex-layout": "3.0.1", diff --git a/yarn.lock b/yarn.lock index d48b72a495..8c220bfb87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3166,13 +3166,13 @@ __metadata: languageName: node linkType: hard -"@material/web@npm:=1.0.0-pre.16": - version: 1.0.0-pre.16 - resolution: "@material/web@npm:1.0.0-pre.16" +"@material/web@npm:=1.0.0-pre.17": + version: 1.0.0-pre.17 + resolution: "@material/web@npm:1.0.0-pre.17" dependencies: - lit: ^2.7.4 + lit: ^2.7.4 || ^3.0.0 tslib: ^2.4.0 - checksum: 387e7ea35aa280b3122bd998345402ec5d5c8e416b376bc1ea52584142ed79b469d2bf74e8a2b10f1dc1782fb7c50318e4aa5aff465e6798974cfbd1abf361ff + checksum: a6443931677d981a0152fe52927b1aa2a9490354c81fbf77f3f9f33accfdc567dc2a431ae0a3cb375dff60a322ff7babd49fb62b186bcf43285e09fecd48a594 languageName: node linkType: hard @@ -9738,7 +9738,7 @@ __metadata: "@material/mwc-top-app-bar": 0.27.0 "@material/mwc-top-app-bar-fixed": 0.27.0 "@material/top-app-bar": =14.0.0-canary.53b3cad2f.0 - "@material/web": =1.0.0-pre.16 + "@material/web": =1.0.0-pre.17 "@mdi/js": 7.2.96 "@mdi/svg": 7.2.96 "@octokit/auth-oauth-device": 6.0.0 @@ -11526,7 +11526,7 @@ __metadata: languageName: node linkType: hard -"lit@npm:2.8.0, lit@npm:^2.0.0, lit@npm:^2.0.0-rc.2, lit@npm:^2.2.1, lit@npm:^2.7.0, lit@npm:^2.7.4, lit@npm:^2.7.6, lit@npm:^2.8.0": +"lit@npm:2.8.0, lit@npm:^2.0.0, lit@npm:^2.0.0-rc.2, lit@npm:^2.2.1, lit@npm:^2.7.0, lit@npm:^2.7.4 || ^3.0.0, lit@npm:^2.7.6, lit@npm:^2.8.0": version: 2.8.0 resolution: "lit@npm:2.8.0" dependencies: From b8f0bb66cdc00a5feeee544e15dd92d858e900c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:11:12 -0400 Subject: [PATCH 09/81] Update dependency @codemirror/view to v6.18.1 (#17922) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 52200ca9d0..9da53eacb2 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@codemirror/legacy-modes": "6.3.3", "@codemirror/search": "6.5.2", "@codemirror/state": "6.2.1", - "@codemirror/view": "6.18.0", + "@codemirror/view": "6.18.1", "@egjs/hammerjs": "2.0.17", "@formatjs/intl-datetimeformat": "6.10.0", "@formatjs/intl-displaynames": "6.5.0", diff --git a/yarn.lock b/yarn.lock index 8c220bfb87..5bd96c32b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1507,14 +1507,14 @@ __metadata: languageName: node linkType: hard -"@codemirror/view@npm:6.18.0, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.6.0": - version: 6.18.0 - resolution: "@codemirror/view@npm:6.18.0" +"@codemirror/view@npm:6.18.1, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.6.0": + version: 6.18.1 + resolution: "@codemirror/view@npm:6.18.1" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.1.0 w3c-keyname: ^2.2.4 - checksum: 275bf5898e884297f16f73e4dff1b520a196a5f7724fbeda634a927e7f4036f6786e816b124505942de99800fb66c538307e8c08e55234ad57483f1a009e3d35 + checksum: 12e350169a12a3cca059712769f81306c95b59accce8ec3c5e6deb1f2fc570baac6f64768aa04f6337bca8448d66520417ec8a4c1c456d40324758695ed9fe90 languageName: node linkType: hard @@ -9690,7 +9690,7 @@ __metadata: "@codemirror/legacy-modes": 6.3.3 "@codemirror/search": 6.5.2 "@codemirror/state": 6.2.1 - "@codemirror/view": 6.18.0 + "@codemirror/view": 6.18.1 "@egjs/hammerjs": 2.0.17 "@formatjs/intl-datetimeformat": 6.10.0 "@formatjs/intl-displaynames": 6.5.0 From 7cce24bcd108bdf5f090bbd164bf37e1fc59aa82 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 20:25:46 -0400 Subject: [PATCH 10/81] Update typescript-eslint monorepo to v6.7.0 (#17923) --- package.json | 4 +- yarn.lock | 104 +++++++++++++++++++++++++-------------------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index 9da53eacb2..766f6c46d6 100644 --- a/package.json +++ b/package.json @@ -186,8 +186,8 @@ "@types/tar": "6.1.5", "@types/ua-parser-js": "0.7.37", "@types/webspeechapi": "0.0.29", - "@typescript-eslint/eslint-plugin": "6.6.0", - "@typescript-eslint/parser": "6.6.0", + "@typescript-eslint/eslint-plugin": "6.7.0", + "@typescript-eslint/parser": "6.7.0", "@web/dev-server": "0.1.38", "@web/dev-server-rollup": "0.4.1", "babel-loader": "9.1.3", diff --git a/yarn.lock b/yarn.lock index 5bd96c32b2..8be0bed518 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4642,15 +4642,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.6.0": - version: 6.6.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.6.0" +"@typescript-eslint/eslint-plugin@npm:6.7.0": + version: 6.7.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.7.0" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.6.0 - "@typescript-eslint/type-utils": 6.6.0 - "@typescript-eslint/utils": 6.6.0 - "@typescript-eslint/visitor-keys": 6.6.0 + "@typescript-eslint/scope-manager": 6.7.0 + "@typescript-eslint/type-utils": 6.7.0 + "@typescript-eslint/utils": 6.7.0 + "@typescript-eslint/visitor-keys": 6.7.0 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -4663,44 +4663,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: ed41c6df87096706777e9c1f53adabd998fd840691b57f5b68b18903e567f16c0a8354ff0ad29229c249f29440ba4a017c9fe966da182a455dde9769232a4344 + checksum: 48393749c5c1f67acf71795551c6065586198530006189c48636e32caea4d1285624c16c047164f9d29055e26c4f90fca964c5a2b5c0e9b6d9ed87acd74ca0d6 languageName: node linkType: hard -"@typescript-eslint/parser@npm:6.6.0": - version: 6.6.0 - resolution: "@typescript-eslint/parser@npm:6.6.0" +"@typescript-eslint/parser@npm:6.7.0": + version: 6.7.0 + resolution: "@typescript-eslint/parser@npm:6.7.0" dependencies: - "@typescript-eslint/scope-manager": 6.6.0 - "@typescript-eslint/types": 6.6.0 - "@typescript-eslint/typescript-estree": 6.6.0 - "@typescript-eslint/visitor-keys": 6.6.0 + "@typescript-eslint/scope-manager": 6.7.0 + "@typescript-eslint/types": 6.7.0 + "@typescript-eslint/typescript-estree": 6.7.0 + "@typescript-eslint/visitor-keys": 6.7.0 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: b2d0082b6acc1a85997ebbb60fc73a43f3fe5e5028cb4130938a2cffddc94872c8e0d00a1742be8f8b755bc1994d43b55b7e4660dc88946744094ff2aca4ffd3 + checksum: 21d52a49abf78a3b037261c01f1f4d2d550919ddc906ebb058db3410a706457ac3a7d082716328ce98a6741d4e77c945b71ff386d9047c5a2e5beef23e14ab45 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.6.0": - version: 6.6.0 - resolution: "@typescript-eslint/scope-manager@npm:6.6.0" +"@typescript-eslint/scope-manager@npm:6.7.0": + version: 6.7.0 + resolution: "@typescript-eslint/scope-manager@npm:6.7.0" dependencies: - "@typescript-eslint/types": 6.6.0 - "@typescript-eslint/visitor-keys": 6.6.0 - checksum: 18b552fee98894c4f35e9f3d71a276f266ad4e2d7c6b9bb32a9b25caa36cc3768928676972b4e78308098ad53fa8dc6626a82810f17d51c667ce959da3ac11bc + "@typescript-eslint/types": 6.7.0 + "@typescript-eslint/visitor-keys": 6.7.0 + checksum: f6ea33c647783d53d98938bd5d3fc94c9a5ebc83bd64cf379215863921dd1c57e66c33af7948d6ac1884623e1917a3b42565e6d02e1fd7adfbce4b3424a2382e languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.6.0": - version: 6.6.0 - resolution: "@typescript-eslint/type-utils@npm:6.6.0" +"@typescript-eslint/type-utils@npm:6.7.0": + version: 6.7.0 + resolution: "@typescript-eslint/type-utils@npm:6.7.0" dependencies: - "@typescript-eslint/typescript-estree": 6.6.0 - "@typescript-eslint/utils": 6.6.0 + "@typescript-eslint/typescript-estree": 6.7.0 + "@typescript-eslint/utils": 6.7.0 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -4708,23 +4708,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: be68ebc1d8da9d4db48933cfd5c8f22382fdf1faf4116b0eb929c65eaeaf00ef224f38b03e7f6ea2de4496d046380876dd5db514c65d078ebc7a25e771a61265 + checksum: 15ae33a6981721f83b2ac612a7597a4fcb2d9d9bfedce54707e5228bec2774fd99ba54ffce89924ae36b61488c7b6c0c2165a6d361be5cd4cefebefad8b02a01 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.6.0": - version: 6.6.0 - resolution: "@typescript-eslint/types@npm:6.6.0" - checksum: d0642ad52e904062a4ac75ac4e6cc51d81ec6030f8830e230df476e69786d3232d45ca0c9ce011add9ede13f0eba4ab7f1eaf679954c6602cf4f43e1ba002be9 +"@typescript-eslint/types@npm:6.7.0": + version: 6.7.0 + resolution: "@typescript-eslint/types@npm:6.7.0" + checksum: fb76031432a009813d559b1cc63091eb5434279012cdb98de62fcd556910663c6a1b506e0a77c4f86e223a5e2c00e76a2d1d2170802c75168008d19a52a51fca languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.6.0": - version: 6.6.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.6.0" +"@typescript-eslint/typescript-estree@npm:6.7.0": + version: 6.7.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.7.0" dependencies: - "@typescript-eslint/types": 6.6.0 - "@typescript-eslint/visitor-keys": 6.6.0 + "@typescript-eslint/types": 6.7.0 + "@typescript-eslint/visitor-keys": 6.7.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -4733,34 +4733,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 100620bc5865dc9d2551c6be520a34b931bc70eca144c5ab0e275b81e57aa92f24a9d3a57f332d98b96e4581cf7e87211c3196d964f4951c7a2508105e3bd3f5 + checksum: 9bd57910085f0dd97d7083e0468c34e0753d20d36d3ffaa4ba111f13cc4986743374f5aed928e645ea982cf2ed9a8141598bee41393cad0abee001f0842ad117 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.6.0": - version: 6.6.0 - resolution: "@typescript-eslint/utils@npm:6.6.0" +"@typescript-eslint/utils@npm:6.7.0": + version: 6.7.0 + resolution: "@typescript-eslint/utils@npm:6.7.0" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.6.0 - "@typescript-eslint/types": 6.6.0 - "@typescript-eslint/typescript-estree": 6.6.0 + "@typescript-eslint/scope-manager": 6.7.0 + "@typescript-eslint/types": 6.7.0 + "@typescript-eslint/typescript-estree": 6.7.0 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: da02305703569549eb7deebb7512940cd40426eccec684680087a5b8c8e08052e2ff0ff6951a2ca64740e86e4b5b390903d0b13ad51efc374d9ae54f70c6a046 + checksum: b2a2857ec856d1752e77c2a274a12513372311c300f9ec57ed7bf7411eb9ea34b85a8e7810a5c48fff0e3966b71d63d77e38c5c7bca1d5c004bede5638619a00 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.6.0": - version: 6.6.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.6.0" +"@typescript-eslint/visitor-keys@npm:6.7.0": + version: 6.7.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.7.0" dependencies: - "@typescript-eslint/types": 6.6.0 + "@typescript-eslint/types": 6.7.0 eslint-visitor-keys: ^3.4.1 - checksum: 28171124c5c7d5d10c04c204530508f1488214f2af5eb7e64a5f1cc410c64f02676c04be087adcfd0deb5566f5bb7337b208afcb249719614634c38bcc3da897 + checksum: cd85722d26ccfa23a76e5cb5aa0229f89eb3c4f1ed87d71a0f902db15f420f3f3e94cbd16dc711039f611ac60b1e7d0fee9ee78c48c88310a5f1926a2bc8778e languageName: node linkType: hard @@ -9778,8 +9778,8 @@ __metadata: "@types/tar": 6.1.5 "@types/ua-parser-js": 0.7.37 "@types/webspeechapi": 0.0.29 - "@typescript-eslint/eslint-plugin": 6.6.0 - "@typescript-eslint/parser": 6.6.0 + "@typescript-eslint/eslint-plugin": 6.7.0 + "@typescript-eslint/parser": 6.7.0 "@vaadin/combo-box": 24.1.7 "@vaadin/vaadin-themable-mixin": 24.1.7 "@vibrant/color": 3.2.1-alpha.1 From 22efe141490522af91e196a61e7d77503da39b93 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 18:57:25 -0400 Subject: [PATCH 11/81] Update dependency @types/tar to v6.1.6 (#17931) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 766f6c46d6..6e4437ab48 100644 --- a/package.json +++ b/package.json @@ -183,7 +183,7 @@ "@types/qrcode": "1.5.2", "@types/serve-handler": "6.1.1", "@types/sortablejs": "1.15.2", - "@types/tar": "6.1.5", + "@types/tar": "6.1.6", "@types/ua-parser-js": "0.7.37", "@types/webspeechapi": "0.0.29", "@typescript-eslint/eslint-plugin": "6.7.0", diff --git a/yarn.lock b/yarn.lock index 8be0bed518..ad81e14742 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4593,13 +4593,13 @@ __metadata: languageName: node linkType: hard -"@types/tar@npm:6.1.5": - version: 6.1.5 - resolution: "@types/tar@npm:6.1.5" +"@types/tar@npm:6.1.6": + version: 6.1.6 + resolution: "@types/tar@npm:6.1.6" dependencies: "@types/node": "*" minipass: ^4.0.0 - checksum: 1efa71c8d72f2b02d16ffecb65c4a96be9dacce000c4207532a686477386524dd99b6e26904319354be3ac9ac4d41296a0cb9cf87d05f8f21ae31c68fe446348 + checksum: d4bcb5a06d8e4b6eac564f22274d72f6a14c614eaf5f6c6c270f3a43c197da2797a7c707bc0377cd2e6d8c429f277e1ca446121546c86021e9782034a306eafb languageName: node linkType: hard @@ -9775,7 +9775,7 @@ __metadata: "@types/qrcode": 1.5.2 "@types/serve-handler": 6.1.1 "@types/sortablejs": 1.15.2 - "@types/tar": 6.1.5 + "@types/tar": 6.1.6 "@types/ua-parser-js": 0.7.37 "@types/webspeechapi": 0.0.29 "@typescript-eslint/eslint-plugin": 6.7.0 From 2a7403b6fdc68c9f1bcd4ec57f6085acf0823b54 Mon Sep 17 00:00:00 2001 From: Madelena Mak Date: Sun, 17 Sep 2023 16:29:53 -0400 Subject: [PATCH 12/81] Added new logo design guidelines (#17951) Co-authored-by: Franck Nijhof --- gallery/public/images/brand/README.md | 4 + .../images/brand/logo-exclusion-zone.png | Bin 0 -> 40869 bytes .../images/brand/logo-layout-variants.png | Bin 0 -> 57637 bytes gallery/public/images/brand/logo.png | Bin 0 -> 26028 bytes gallery/public/images/logo.png | Bin 22017 -> 0 bytes gallery/src/pages/brand/logo.markdown | 82 +++++++++++++++--- 6 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 gallery/public/images/brand/README.md create mode 100644 gallery/public/images/brand/logo-exclusion-zone.png create mode 100644 gallery/public/images/brand/logo-layout-variants.png create mode 100644 gallery/public/images/brand/logo.png delete mode 100644 gallery/public/images/logo.png diff --git a/gallery/public/images/brand/README.md b/gallery/public/images/brand/README.md new file mode 100644 index 0000000000..818cc08039 --- /dev/null +++ b/gallery/public/images/brand/README.md @@ -0,0 +1,4 @@ +# Note! + +Note, the assets in this folder, are not part of the CC license this repository is shipped in. +All rights reserved. diff --git a/gallery/public/images/brand/logo-exclusion-zone.png b/gallery/public/images/brand/logo-exclusion-zone.png new file mode 100644 index 0000000000000000000000000000000000000000..6a8bb93a4918a8598341472881804119fd4d2d66 GIT binary patch literal 40869 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 literal 0 HcmV?d00001 diff --git a/gallery/public/images/brand/logo-layout-variants.png b/gallery/public/images/brand/logo-layout-variants.png new file mode 100644 index 0000000000000000000000000000000000000000..567fd8862021d39341ecf5ae512c8ff4bdcd49de GIT binary patch literal 57637 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̐|_AD$+pxe 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 iJqIyx7d-D`<}mnHU+wYZ&$hFO&xia`yNh9IMu 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 z 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 HT`=R{?RU%` diff --git a/gallery/src/pages/brand/logo.markdown b/gallery/src/pages/brand/logo.markdown index 9cd8722f7c..e66cd398ef 100644 --- a/gallery/src/pages/brand/logo.markdown +++ b/gallery/src/pages/brand/logo.markdown @@ -2,30 +2,86 @@ title: "Logo" --- -# Using our logo +# Our logo -As a community, we are proud of our logo. Follow these guidelines to ensure it always looks its best. Our logo follows Google's material design spec and uses the blue interface color. +As a community, we are proud of our logo. Follow these guidelines to ensure it always represents the identity of the Home Assistant project and community the best way possible. [Download Logo](https://github.com/home-assistant/assets/tree/master/logo) -![Logo](/images/logo.png) +![Logo](/images/brand/logo.png) -## Using the icon +Please note that this logo is not released under the CC license. All rights reserved. -Our icon is a shorter and most used version of our logo. The icon can exist without the wordmark, the wordmark should never exist without the icon. +# Design -![Logo variants](/images/logo-variants.png) +At the core of the Home Assistant logomark is the Blue House with Antenna, the three most recognizable and distinct features of the previous logo throughout the past decade. -## Using the right variant +### Blue -The pretty blue logo with a background shadow, pictured top left, is our primary logo. It should only be used with black, white, and non-duotone photography. +Blue feels stable and essential. A bright sky blue is joyful, clear, and free of clouds. -When needed you can use our logo without a shadow, as seen as the second variant. +### House -The outlined logo should only be used on packaging. +Of all possible combinations of shapes, a home is best abstracted in the shape of a structure with a pitched roof. With the vast amount of logos based on this shape, the best we can do is to make it more iconic. The house is further simplified - there is no gable and there is no chimney - to an orthogonal shape with an elegant and deliberate proportion. -## Exclusion zone +### Antenna -The logo needs some personal space. It's exclusion zone is equal to a quarter the height of the icon. +Call it a tree, a set of nodes, a PCB, or an antenna. The antenna is the most recognizable and memorable part of the previous Home Assistant logo, and is an easily understandable symbol that conveys technologies that are smart, connected, and growing evergreen. -![Clearspace](/images/clearspace.png) +# Usage + +The default variation is the static colored wordmark in horizontal layout and dark text on a light background. + +## Layout variations + +![Logo layout variants](/images/brand/logo-layout-variants.png) + +The default layout is the wordmark in horizontal layout. It provides the clearest context to the brand identity of Home Assistant. + +Use the logomark variant when the context is clear that the logo is about Home Assistant. For example, inside the Home Assistant app where users are already aware of where they are at, the logomark variant without the wordmark can be used. The logomark can exist without the wordmark, however, the wordmark should never exist without the icon. + +Use the wordmark in vertical layout when the space available has an aspect ratio less than 4:3. For example, in a square space on a t-shirt where a logo is needed, since there is no established context of Home Assistant, the wordmark in vertical layout should be used. + +Lastly, use the wordmark in vertical layout with small logomark when Home Assistant is displayed in context of other Home Assistant-related projects. For example, in a flowchart showing the voice pipeline, use this layout for Home Assistant and its other related projects. + +## Color variations, backgrounds, and placement + +The default color is the colored version on light background with dark text. + +For backgrounds that are dark, for example, when it is used on a page in a dark theme, use the colored version on dark background with light text. + +In printed materials where color is unavailable, use the monochrome color variations. + +On background that are dark or photographic, use the light monochrome color on dark background variation. + +On backgrounds that are light or photographic, use the colored version. Do not use the monochrome variations. + +Do not enclose the logmark in a square or color or any confined backgrounds, except in specific situations enforced by another company's marketplace guidelines, for example, an iOS app icon. + +Do not add drop shadow to the logomark or the wordmark. If legibility is compromised due to the background, change the background to provide more contrast, or in last resort, add a heavily blurred drop shadaow. + +It should only be used with black, white, and non-duotone photography. + +Unlike the previous version of our logo, no outlined variants are available. Use the monochrome variants in those spaces. + +### Exclusion zone + +The logo needs some personal space. Its exclusion zone is equal to a quarter the height of the icon. + +![Space clearance for the wordmark](/images/brand/logo-exclusion-zone.png) + +## Animation + +The default is the static variant. + +Use the animated variant only for introductory purposes, for example, in the beginning of a video or on a loading screen. + +Use the animated with sound variant only when sound is warranted in the user's context. For example, use it in the beginning of a video since sounds are expected in a video, but do not use it on a loading screen since sounds are not expected in a user interface. + +Do not repeat the logo animation. + +## Sizes and app icon variants + +Special variants are created for specific contexts. + +Use the tiny variants when the logomark is used in a very small space (16x16 dp), for example, the favicon of the Home Assistant website, a notification on Android, or the menubar of macOS. From 8797142cca77b7fb3382396bcff9030b6c0d52d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 08:15:40 -0400 Subject: [PATCH 13/81] Update dependency sinon to v16 (#17940) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 6e4437ab48..53cd421e90 100644 --- a/package.json +++ b/package.json @@ -234,7 +234,7 @@ "rollup-plugin-terser": "7.0.2", "rollup-plugin-visualizer": "5.9.2", "serve-handler": "6.1.5", - "sinon": "15.2.0", + "sinon": "16.0.0", "source-map-url": "0.4.1", "systemjs": "6.14.2", "tar": "6.2.0", diff --git a/yarn.lock b/yarn.lock index ad81e14742..b8ca6ce6ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9864,7 +9864,7 @@ __metadata: rollup-plugin-visualizer: 5.9.2 rrule: 2.7.2 serve-handler: 6.1.5 - sinon: 15.2.0 + sinon: 16.0.0 sortablejs: 1.15.0 source-map-url: 0.4.1 stacktrace-js: 2.0.2 @@ -14492,9 +14492,9 @@ __metadata: languageName: node linkType: hard -"sinon@npm:15.2.0": - version: 15.2.0 - resolution: "sinon@npm:15.2.0" +"sinon@npm:16.0.0": + version: 16.0.0 + resolution: "sinon@npm:16.0.0" dependencies: "@sinonjs/commons": ^3.0.0 "@sinonjs/fake-timers": ^10.3.0 @@ -14502,7 +14502,7 @@ __metadata: diff: ^5.1.0 nise: ^5.1.4 supports-color: ^7.2.0 - checksum: 1641b9af8a73ba57c73c9b6fd955a2d062a5d78cce719887869eca45faf33b0fd20cabfeffdfd856bb35bfbd3d49debb2d954ff6ae5e9825a3da5ff4f604ab6c + checksum: fbcad39d1610c669bb37ce2d325f2ac666ff5187935d09d1e757e11c50d07b8556b7dfa322eb38ad6ace8a18912224cc502e990779bc3d0954244a1ae8391984 languageName: node linkType: hard From a19633e2d47a500049a98bd415e1afba393b9fca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 08:21:31 -0400 Subject: [PATCH 14/81] Update CodeMirror (#17944) --- package.json | 6 +++--- yarn.lock | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 53cd421e90..d439436472 100644 --- a/package.json +++ b/package.json @@ -27,13 +27,13 @@ "dependencies": { "@babel/runtime": "7.22.15", "@braintree/sanitize-url": "6.0.4", - "@codemirror/autocomplete": "6.9.0", + "@codemirror/autocomplete": "6.9.1", "@codemirror/commands": "6.2.5", "@codemirror/language": "6.9.0", "@codemirror/legacy-modes": "6.3.3", - "@codemirror/search": "6.5.2", + "@codemirror/search": "6.5.3", "@codemirror/state": "6.2.1", - "@codemirror/view": "6.18.1", + "@codemirror/view": "6.19.0", "@egjs/hammerjs": "2.0.17", "@formatjs/intl-datetimeformat": "6.10.0", "@formatjs/intl-displaynames": "6.5.0", diff --git a/yarn.lock b/yarn.lock index b8ca6ce6ab..d63982d17d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1437,20 +1437,20 @@ __metadata: languageName: node linkType: hard -"@codemirror/autocomplete@npm:6.9.0": - version: 6.9.0 - resolution: "@codemirror/autocomplete@npm:6.9.0" +"@codemirror/autocomplete@npm:6.9.1": + version: 6.9.1 + resolution: "@codemirror/autocomplete@npm:6.9.1" dependencies: "@codemirror/language": ^6.0.0 "@codemirror/state": ^6.0.0 - "@codemirror/view": ^6.6.0 + "@codemirror/view": ^6.17.0 "@lezer/common": ^1.0.0 peerDependencies: "@codemirror/language": ^6.0.0 "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 "@lezer/common": ^1.0.0 - checksum: a5f661944c75f40b02c90a193c9a459c0fd7e335c0ac5973420c19157dfb46010f573c2b70731591fe477e7a2ad10121ff3ae394a72d450946d7b886c28b0368 + checksum: 96dad7a12429bf61e6f1bf75da731bf0dcbfeb56c33400b60a0de22049226e0926a53a174e84701812a235f8f144595ce53f0928054481bdf9cdc2ed3b8be20f languageName: node linkType: hard @@ -1489,14 +1489,14 @@ __metadata: languageName: node linkType: hard -"@codemirror/search@npm:6.5.2": - version: 6.5.2 - resolution: "@codemirror/search@npm:6.5.2" +"@codemirror/search@npm:6.5.3": + version: 6.5.3 + resolution: "@codemirror/search@npm:6.5.3" dependencies: "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 crelt: ^1.0.5 - checksum: bc535151277fda0a370ac496b9b0d5751fd91bd8e3eb29dafbfe6bf3125dc450a7e361ebc302f0ebc4193ac337bdf555ab3d5ec753dbb44452225618a5630dd3 + checksum: 970fbbafac1d469c2d94889603161f6ef0c075b5d01228157381b0c7189389ae7649e41a8ca829ab50b0bb4f03d5e043cfb641ad0c0bc426a05034181710d2ad languageName: node linkType: hard @@ -1507,14 +1507,14 @@ __metadata: languageName: node linkType: hard -"@codemirror/view@npm:6.18.1, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.6.0": - version: 6.18.1 - resolution: "@codemirror/view@npm:6.18.1" +"@codemirror/view@npm:6.19.0, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0": + version: 6.19.0 + resolution: "@codemirror/view@npm:6.19.0" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.1.0 w3c-keyname: ^2.2.4 - checksum: 12e350169a12a3cca059712769f81306c95b59accce8ec3c5e6deb1f2fc570baac6f64768aa04f6337bca8448d66520417ec8a4c1c456d40324758695ed9fe90 + checksum: 58b909c45c7b02758860953f65ce7952e0d89b9e4db35bd5a382ad90a9a1d7e9ed9bf4d60e5a38b9538375427372b9ddf1d4d161d21448691b851db92af7f71f languageName: node linkType: hard @@ -9684,13 +9684,13 @@ __metadata: "@babel/preset-typescript": 7.22.15 "@babel/runtime": 7.22.15 "@braintree/sanitize-url": 6.0.4 - "@codemirror/autocomplete": 6.9.0 + "@codemirror/autocomplete": 6.9.1 "@codemirror/commands": 6.2.5 "@codemirror/language": 6.9.0 "@codemirror/legacy-modes": 6.3.3 - "@codemirror/search": 6.5.2 + "@codemirror/search": 6.5.3 "@codemirror/state": 6.2.1 - "@codemirror/view": 6.18.1 + "@codemirror/view": 6.19.0 "@egjs/hammerjs": 2.0.17 "@formatjs/intl-datetimeformat": 6.10.0 "@formatjs/intl-displaynames": 6.5.0 From e6884178634c7e560708d02f6b8f7e92a511701d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 08:27:41 -0400 Subject: [PATCH 15/81] Update dependency @babel/core to v7.22.19 (#17948) --- package.json | 2 +- yarn.lock | 66 ++++++++++++++++++++++++++-------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index d439436472..78c3982d92 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "xss": "1.0.14" }, "devDependencies": { - "@babel/core": "7.22.17", + "@babel/core": "7.22.19", "@babel/plugin-proposal-decorators": "7.22.15", "@babel/plugin-transform-runtime": "7.22.15", "@babel/preset-env": "7.22.15", diff --git a/yarn.lock b/yarn.lock index d63982d17d..9a97fadfd9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -62,26 +62,26 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:7.22.17, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": - version: 7.22.17 - resolution: "@babel/core@npm:7.22.17" +"@babel/core@npm:7.22.19, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": + version: 7.22.19 + resolution: "@babel/core@npm:7.22.19" dependencies: "@ampproject/remapping": ^2.2.0 "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.22.15 "@babel/helper-compilation-targets": ^7.22.15 - "@babel/helper-module-transforms": ^7.22.17 + "@babel/helper-module-transforms": ^7.22.19 "@babel/helpers": ^7.22.15 "@babel/parser": ^7.22.16 "@babel/template": ^7.22.15 - "@babel/traverse": ^7.22.17 - "@babel/types": ^7.22.17 + "@babel/traverse": ^7.22.19 + "@babel/types": ^7.22.19 convert-source-map: ^1.7.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: 355216a342d1b3952d7c040dd4c99ecef6b3501ba99a713703c1fec1ae73bc92a48a0c1234562bdbb4fd334b2e452f5a6c3bb282f0e613fa89e1518c91d1aea1 + checksum: d603f6f00b20c1edff6a6c9d32c559d4d09ee873380317271b57322bfb9da4349e59df53a21c65e9e5a1136f52bf612389d798640454e6fd9246a5c6d76b0c5c languageName: node linkType: hard @@ -175,10 +175,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-environment-visitor@npm:7.22.5" - checksum: 248532077d732a34cd0844eb7b078ff917c3a8ec81a7f133593f71a860a582f05b60f818dc5049c2212e5baa12289c27889a4b81d56ef409b4863db49646c4b1 +"@babel/helper-environment-visitor@npm:^7.22.20, @babel/helper-environment-visitor@npm:^7.22.5": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 languageName: node linkType: hard @@ -219,18 +219,18 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.22.15, @babel/helper-module-transforms@npm:^7.22.17, @babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9": - version: 7.22.17 - resolution: "@babel/helper-module-transforms@npm:7.22.17" +"@babel/helper-module-transforms@npm:^7.22.15, @babel/helper-module-transforms@npm:^7.22.19, @babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9": + version: 7.22.20 + resolution: "@babel/helper-module-transforms@npm:7.22.20" dependencies: - "@babel/helper-environment-visitor": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 "@babel/helper-module-imports": ^7.22.15 "@babel/helper-simple-access": ^7.22.5 "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/helper-validator-identifier": ^7.22.15 + "@babel/helper-validator-identifier": ^7.22.20 peerDependencies: "@babel/core": ^7.0.0 - checksum: 458021c74093e66179765fcc9d1c1cb694f7bdf98656f23486901d35636495c38aab4661547fac2142e13d887987d1ea30cc9fe42968376a51a99bcd207b4989 + checksum: 8fce25362df8711bd4620f41c5c18769edfeafe7f8f1dae9691966ef368e57f9da68dfa1707cd63c834c89dc4eaa82c26f12ea33e88fd262ac62844b11dcc389 languageName: node linkType: hard @@ -310,10 +310,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.15, @babel/helper-validator-identifier@npm:^7.22.5": - version: 7.22.15 - resolution: "@babel/helper-validator-identifier@npm:7.22.15" - checksum: eb0bee4bda664c0959924bc1ad5611eacfce806f46612202dd164fef1df8fef1a11682a1e7615288987100e9fb304982b6e2a4ff07ffe842ab8765b95ed1118c +"@babel/helper-validator-identifier@npm:^7.22.19, @babel/helper-validator-identifier@npm:^7.22.20, @babel/helper-validator-identifier@npm:^7.22.5": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc languageName: node linkType: hard @@ -1401,32 +1401,32 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.22.15, @babel/traverse@npm:^7.22.17": - version: 7.22.17 - resolution: "@babel/traverse@npm:7.22.17" +"@babel/traverse@npm:^7.22.15, @babel/traverse@npm:^7.22.19": + version: 7.22.20 + resolution: "@babel/traverse@npm:7.22.20" dependencies: "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.22.15 - "@babel/helper-environment-visitor": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 "@babel/helper-function-name": ^7.22.5 "@babel/helper-hoist-variables": ^7.22.5 "@babel/helper-split-export-declaration": ^7.22.6 "@babel/parser": ^7.22.16 - "@babel/types": ^7.22.17 + "@babel/types": ^7.22.19 debug: ^4.1.0 globals: ^11.1.0 - checksum: 1153ca166a0a9b3fddf67f7f7c8c5b4f88aa2c2c00261ff2fc8424a63bc93250ed3fd08b04bd526ad19e797aeb6f22161120646a570cbfe5ff2a5d2f5d28af01 + checksum: 97da9afa7f8f505ce52c36ac2531129bc4a0e250880aaf9b467dc044f30a5bce2b756c1af4d961958bc225659546e811a7d536ab3d920fd60921087989b841b9 languageName: node linkType: hard -"@babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.17, @babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.22.17 - resolution: "@babel/types@npm:7.22.17" +"@babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.22.19 + resolution: "@babel/types@npm:7.22.19" dependencies: "@babel/helper-string-parser": ^7.22.5 - "@babel/helper-validator-identifier": ^7.22.15 + "@babel/helper-validator-identifier": ^7.22.19 to-fast-properties: ^2.0.0 - checksum: 7382220f6eb2548f2c867a98916c3aa8a6063498d5372e5d21d8d184ba354033defb72aeba5858c1b2b42177058b896a34a7dcbae5eccd47fb0104721efa909d + checksum: 2d69740e69b55ba36ece0c17d5afb7b7213b34297157df39ef9ba24965aff677c56f014413052ecc5b2fbbf26910c63e5bb24a969df84d7a17153750cf75915e languageName: node linkType: hard @@ -9677,7 +9677,7 @@ __metadata: version: 0.0.0-use.local resolution: "home-assistant-frontend@workspace:." dependencies: - "@babel/core": 7.22.17 + "@babel/core": 7.22.19 "@babel/plugin-proposal-decorators": 7.22.15 "@babel/plugin-transform-runtime": 7.22.15 "@babel/preset-env": 7.22.15 From 63f0b469cc602f823c4f95132204378ed07378b5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:25:23 -0400 Subject: [PATCH 16/81] Update dependency vis-data to v7.1.7 (#17939) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 78c3982d92..29940b53ea 100644 --- a/package.json +++ b/package.json @@ -139,7 +139,7 @@ "tsparticles-preset-links": "2.12.0", "ua-parser-js": "1.0.36", "unfetch": "5.0.0", - "vis-data": "7.1.6", + "vis-data": "7.1.7", "vis-network": "9.1.6", "vue": "2.7.14", "vue2-daterange-picker": "0.6.8", diff --git a/yarn.lock b/yarn.lock index 9a97fadfd9..2c297dbe49 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9881,7 +9881,7 @@ __metadata: unfetch: 5.0.0 vinyl-buffer: 1.0.1 vinyl-source-stream: 2.0.0 - vis-data: 7.1.6 + vis-data: 7.1.7 vis-network: 9.1.6 vue: 2.7.14 vue2-daterange-picker: 0.6.8 @@ -16157,13 +16157,13 @@ __metadata: languageName: node linkType: hard -"vis-data@npm:7.1.6": - version: 7.1.6 - resolution: "vis-data@npm:7.1.6" +"vis-data@npm:7.1.7": + version: 7.1.7 + resolution: "vis-data@npm:7.1.7" peerDependencies: uuid: ^3.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 vis-util: ^5.0.1 - checksum: ef461d13e0c340c29aef38b70247c0722d293b9aab029fdbffe6802e473c47ea83e2c3c9563cd03e092d1e579b5f98326ce704eb1b3d51eee8f0eadaf6618f99 + checksum: ecb92cc440bf8440097e8b64668c77eb93a7b7e36c6faf82fe2e807849099619a69770c894ca3cb8708d8cd023990e5dd6c26451360149d7c8ce0d82d807110d languageName: node linkType: hard From 577c1d852237b06348d5a6ee5e7b94d0ece2a675 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:35:46 -0400 Subject: [PATCH 17/81] Update dependency @lit-labs/context to v0.4.1 (#17935) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 29940b53ea..dec5654fbf 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "@fullcalendar/luxon3": "6.1.8", "@fullcalendar/timegrid": "6.1.8", "@lezer/highlight": "1.1.6", - "@lit-labs/context": "0.4.0", + "@lit-labs/context": "0.4.1", "@lit-labs/motion": "1.0.4", "@lit-labs/virtualizer": "2.0.7", "@lrnwebcomponents/simple-tooltip": "7.0.16", diff --git a/yarn.lock b/yarn.lock index 2c297dbe49..40d7fa8c75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2078,13 +2078,13 @@ __metadata: languageName: node linkType: hard -"@lit-labs/context@npm:0.4.0": - version: 0.4.0 - resolution: "@lit-labs/context@npm:0.4.0" +"@lit-labs/context@npm:0.4.1": + version: 0.4.1 + resolution: "@lit-labs/context@npm:0.4.1" dependencies: "@lit/reactive-element": ^1.5.0 lit: ^2.7.0 - checksum: 5d97a75e79c7e3069bdf1fd7be9a7c703398658a3702fdbbac34938220247a237b2839b568e7b979dc1a3a07eba1836418f51e40a950fbde6314cc8cbc9d0546 + checksum: 0f5bf4bd0beb4ff97c0df990997f0d56872682d8597e39f43cb5171aa3b7a53c7a0fc2e16f710282d7abe93c5d6ff6dd52b096d1682df277439cec47291b8023 languageName: node linkType: hard @@ -9708,7 +9708,7 @@ __metadata: "@fullcalendar/timegrid": 6.1.8 "@koa/cors": 4.0.0 "@lezer/highlight": 1.1.6 - "@lit-labs/context": 0.4.0 + "@lit-labs/context": 0.4.1 "@lit-labs/motion": 1.0.4 "@lit-labs/virtualizer": 2.0.7 "@lokalise/node-api": 11.0.1 From 1019ccfd26958a011497fb975c740d0c37e3dff7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:41:29 -0400 Subject: [PATCH 18/81] Update dependency @lrnwebcomponents/simple-tooltip to v7.0.18 (#17905) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index dec5654fbf..e84df66aac 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@lit-labs/context": "0.4.1", "@lit-labs/motion": "1.0.4", "@lit-labs/virtualizer": "2.0.7", - "@lrnwebcomponents/simple-tooltip": "7.0.16", + "@lrnwebcomponents/simple-tooltip": "7.0.18", "@material/chips": "=14.0.0-canary.53b3cad2f.0", "@material/data-table": "=14.0.0-canary.53b3cad2f.0", "@material/mwc-button": "0.27.0", diff --git a/yarn.lock b/yarn.lock index 40d7fa8c75..79e87f8cb4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2132,12 +2132,12 @@ __metadata: languageName: node linkType: hard -"@lrnwebcomponents/simple-tooltip@npm:7.0.16": - version: 7.0.16 - resolution: "@lrnwebcomponents/simple-tooltip@npm:7.0.16" +"@lrnwebcomponents/simple-tooltip@npm:7.0.18": + version: 7.0.18 + resolution: "@lrnwebcomponents/simple-tooltip@npm:7.0.18" dependencies: - lit: ^2.7.6 - checksum: 0cb42c19c9f41945b4f9b28ee9e1a90b0ebc25a3fb84d5acd791af2de7243eb80eab830a9e2c6059381cdca27d05ce02e0c2ebb6c1b777fb2f657075cddc0999 + lit: ^2.8.0 + checksum: 6b35d7c517b9eeaaad0e4f6941d46e480bb4660d0326161a2dc6c57513a5ddc88a87b903986553844601f566dab485d9fc98a16045300b5848b4960c3a352fc4 languageName: node linkType: hard @@ -9712,7 +9712,7 @@ __metadata: "@lit-labs/motion": 1.0.4 "@lit-labs/virtualizer": 2.0.7 "@lokalise/node-api": 11.0.1 - "@lrnwebcomponents/simple-tooltip": 7.0.16 + "@lrnwebcomponents/simple-tooltip": 7.0.18 "@material/chips": =14.0.0-canary.53b3cad2f.0 "@material/data-table": =14.0.0-canary.53b3cad2f.0 "@material/mwc-button": 0.27.0 @@ -11526,7 +11526,7 @@ __metadata: languageName: node linkType: hard -"lit@npm:2.8.0, lit@npm:^2.0.0, lit@npm:^2.0.0-rc.2, lit@npm:^2.2.1, lit@npm:^2.7.0, lit@npm:^2.7.4 || ^3.0.0, lit@npm:^2.7.6, lit@npm:^2.8.0": +"lit@npm:2.8.0, lit@npm:^2.0.0, lit@npm:^2.0.0-rc.2, lit@npm:^2.2.1, lit@npm:^2.7.0, lit@npm:^2.7.4 || ^3.0.0, lit@npm:^2.8.0": version: 2.8.0 resolution: "lit@npm:2.8.0" dependencies: From 71cd71dfd5419a173dc6469a2547c896a624aeb5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:50:43 -0400 Subject: [PATCH 19/81] Update formatjs monorepo (#17890) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 16 +++--- yarn.lock | 160 +++++++++++++++++++++++++-------------------------- 2 files changed, 88 insertions(+), 88 deletions(-) diff --git a/package.json b/package.json index e84df66aac..b8344a0663 100644 --- a/package.json +++ b/package.json @@ -35,14 +35,14 @@ "@codemirror/state": "6.2.1", "@codemirror/view": "6.19.0", "@egjs/hammerjs": "2.0.17", - "@formatjs/intl-datetimeformat": "6.10.0", - "@formatjs/intl-displaynames": "6.5.0", + "@formatjs/intl-datetimeformat": "6.10.2", + "@formatjs/intl-displaynames": "6.5.2", "@formatjs/intl-getcanonicallocales": "2.2.1", - "@formatjs/intl-listformat": "7.4.0", - "@formatjs/intl-locale": "3.3.2", - "@formatjs/intl-numberformat": "8.7.0", - "@formatjs/intl-pluralrules": "5.2.4", - "@formatjs/intl-relativetimeformat": "11.2.4", + "@formatjs/intl-listformat": "7.4.2", + "@formatjs/intl-locale": "3.3.4", + "@formatjs/intl-numberformat": "8.7.2", + "@formatjs/intl-pluralrules": "5.2.6", + "@formatjs/intl-relativetimeformat": "11.2.6", "@fullcalendar/core": "6.1.8", "@fullcalendar/daygrid": "6.1.8", "@fullcalendar/interaction": "6.1.8", @@ -115,7 +115,7 @@ "hls.js": "1.4.12", "home-assistant-js-websocket": "8.2.0", "idb-keyval": "6.2.1", - "intl-messageformat": "10.5.0", + "intl-messageformat": "10.5.2", "js-yaml": "4.1.0", "leaflet": "1.9.4", "leaflet-draw": "1.0.4", diff --git a/yarn.lock b/yarn.lock index 79e87f8cb4..aa5f4b2be9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1585,13 +1585,13 @@ __metadata: languageName: node linkType: hard -"@formatjs/ecma402-abstract@npm:1.17.0": - version: 1.17.0 - resolution: "@formatjs/ecma402-abstract@npm:1.17.0" +"@formatjs/ecma402-abstract@npm:1.17.2": + version: 1.17.2 + resolution: "@formatjs/ecma402-abstract@npm:1.17.2" dependencies: - "@formatjs/intl-localematcher": 0.4.0 + "@formatjs/intl-localematcher": 0.4.2 tslib: ^2.4.0 - checksum: cc45d238e541076cb27b9cf02d8b97f789d1744b60218da6d31793204850c159e85f5b2557de3905a365eefd52a1c2e7f1febb9e1f009bad23d5eca17b3de6c8 + checksum: 026382b1fb295cef4387b2f2a34dace107b12fb7607793093b26595b0d639a30e5f4539665730897eb77eefabee2bb35c156896c63925b0ec03b746751e3fb00 languageName: node linkType: hard @@ -1604,55 +1604,55 @@ __metadata: languageName: node linkType: hard -"@formatjs/icu-messageformat-parser@npm:2.6.0": - version: 2.6.0 - resolution: "@formatjs/icu-messageformat-parser@npm:2.6.0" +"@formatjs/icu-messageformat-parser@npm:2.6.2": + version: 2.6.2 + resolution: "@formatjs/icu-messageformat-parser@npm:2.6.2" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 - "@formatjs/icu-skeleton-parser": 1.6.0 + "@formatjs/ecma402-abstract": 1.17.2 + "@formatjs/icu-skeleton-parser": 1.6.2 tslib: ^2.4.0 - checksum: 67e76416a381663f62cb7ceaa699b3dc4505b9bfd8dda31950b8fa159e9abc1aae85d2ffa08760448083f113bdabca1653796e988b7a12eef891260726e56ed7 + checksum: c339a712497deaa14e84610afb6c09377a5641b18fb0ae3d42999354cf2b557c84d7c7fead0d06d38a04f8e63e8002ae51c820a8a3e98b82805e84e7878e9d90 languageName: node linkType: hard -"@formatjs/icu-skeleton-parser@npm:1.6.0": - version: 1.6.0 - resolution: "@formatjs/icu-skeleton-parser@npm:1.6.0" +"@formatjs/icu-skeleton-parser@npm:1.6.2": + version: 1.6.2 + resolution: "@formatjs/icu-skeleton-parser@npm:1.6.2" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 + "@formatjs/ecma402-abstract": 1.17.2 tslib: ^2.4.0 - checksum: e0a2e251358fb62cc45ad4783f57ed63db361334634557d5dcf3992b98c2c5409146d890b465321f91d2255eda5d8fdbfc9962e9f2e3fa7b10a738abfbe8ebc0 + checksum: f51658d0b086579a2173b91beb692822f08db1180c81fa41e62bef4236a0de98f9d6e46087d77c5e46fa4286f77b4b52a2467f3d8b81a4cf8dd817edb138d68b languageName: node linkType: hard -"@formatjs/intl-datetimeformat@npm:6.10.0": - version: 6.10.0 - resolution: "@formatjs/intl-datetimeformat@npm:6.10.0" +"@formatjs/intl-datetimeformat@npm:6.10.2": + version: 6.10.2 + resolution: "@formatjs/intl-datetimeformat@npm:6.10.2" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 - "@formatjs/intl-localematcher": 0.4.0 + "@formatjs/ecma402-abstract": 1.17.2 + "@formatjs/intl-localematcher": 0.4.2 tslib: ^2.4.0 - checksum: a0f915dd0d179dfeb0dfa585c7e939ef4b51a90cf04b9522d14de8acc9fb18e7af30898cc215c134955f31aa244d1f59ca677b9769fa9ee539148f6f52ceaa1d + checksum: f0aef855d9f53afcd1c39eb537339eb416bdc726c3379114eeac14692459210ad0e463fb8dffbe1aca6a53db9248efcb18a9e7d5b62616552b4040634c185449 languageName: node linkType: hard -"@formatjs/intl-displaynames@npm:6.5.0": - version: 6.5.0 - resolution: "@formatjs/intl-displaynames@npm:6.5.0" +"@formatjs/intl-displaynames@npm:6.5.2": + version: 6.5.2 + resolution: "@formatjs/intl-displaynames@npm:6.5.2" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 - "@formatjs/intl-localematcher": 0.4.0 + "@formatjs/ecma402-abstract": 1.17.2 + "@formatjs/intl-localematcher": 0.4.2 tslib: ^2.4.0 - checksum: d071f8459796240575e9911052b7116a6e2e43687607b0a5d1ac8ceddbaa85324af78694226c37c8172c0f3e7d6b793f506c5758b6bc50b2110516902b532e12 + checksum: e48718c00fc2392aac49bbc6971f44d6e56f3626aaebae9ecf61fe8787b7e11b5b0be9f7be5d8bcd43ea6fbaa7ea4aa1453b042e076f982fa0d24d7744088ccf languageName: node linkType: hard -"@formatjs/intl-enumerator@npm:1.3.2": - version: 1.3.2 - resolution: "@formatjs/intl-enumerator@npm:1.3.2" +"@formatjs/intl-enumerator@npm:1.3.4": + version: 1.3.4 + resolution: "@formatjs/intl-enumerator@npm:1.3.4" dependencies: tslib: ^2.4.0 - checksum: 37435354fcab9f69390402b1bcc917e83d0e35869cd5a06b584ca84ef62b179a4b94b9ee94febb59ab503a9d1587babcdcbebc2d4ece146fbc02bef41f722314 + checksum: ea7ba1433e9f0fef1eee79564041ac09452440f93bfad4f31cb036928f5668685b9b5c97ed794737fd8ab1be469a11597d5838a6f468ab76770b6f5e806bc104 languageName: node linkType: hard @@ -1665,68 +1665,68 @@ __metadata: languageName: node linkType: hard -"@formatjs/intl-listformat@npm:7.4.0": - version: 7.4.0 - resolution: "@formatjs/intl-listformat@npm:7.4.0" +"@formatjs/intl-listformat@npm:7.4.2": + version: 7.4.2 + resolution: "@formatjs/intl-listformat@npm:7.4.2" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 - "@formatjs/intl-localematcher": 0.4.0 + "@formatjs/ecma402-abstract": 1.17.2 + "@formatjs/intl-localematcher": 0.4.2 tslib: ^2.4.0 - checksum: a2deed31cce57f249e470f54675286c36edc2f5ec1d63a2f36e6315a0154ca06404fa5c00aaefc2c52af57d3d471b17c217e885cc9565e5f54c36509af37fe12 + checksum: e31c0f8cf91c23c22c725db6fee51f5a54399a04d7dc1834a7a83e2d7069e26b92f7276a10c4f35d4ffa82f482c1fcf1240571f2e04e10ef072f2edcd2f69a09 languageName: node linkType: hard -"@formatjs/intl-locale@npm:3.3.2": - version: 3.3.2 - resolution: "@formatjs/intl-locale@npm:3.3.2" +"@formatjs/intl-locale@npm:3.3.4": + version: 3.3.4 + resolution: "@formatjs/intl-locale@npm:3.3.4" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 - "@formatjs/intl-enumerator": 1.3.2 + "@formatjs/ecma402-abstract": 1.17.2 + "@formatjs/intl-enumerator": 1.3.4 "@formatjs/intl-getcanonicallocales": 2.2.1 tslib: ^2.4.0 - checksum: 41d2ab272ba759671cfa1720b2c43f8e261694f68d114ff976f2b9749ac3afad2181aa1b16799740082aa05bedd6f23b0ab67c65f48bfa0097b42582789e9a4d + checksum: 9d9a1932db3e43668557c7605703a71881cee07241233a9433f2526b9d9a9ea8f04cd7dc8421eb558cd94bd24ba4b0ee5a0ee0ffad4fddb005d7dd6c2020f9dc languageName: node linkType: hard -"@formatjs/intl-localematcher@npm:0.4.0": - version: 0.4.0 - resolution: "@formatjs/intl-localematcher@npm:0.4.0" +"@formatjs/intl-localematcher@npm:0.4.2": + version: 0.4.2 + resolution: "@formatjs/intl-localematcher@npm:0.4.2" dependencies: tslib: ^2.4.0 - checksum: c65108e9a81c3733d2b6240ceedc846d0ae59c3606041cb5cc71c13453cdabe295b0dc8559dc4a8acaafdc45876807bd5e9ef37a3ec1cb864e78db655d434b66 + checksum: df579d8c453a11eed1ec55604f8dda121d728fc5109ed885892347a126089caef95a0edf71f1f6db3134bb9e73787062995baf7746a2577e8ca2980dcd6590cb languageName: node linkType: hard -"@formatjs/intl-numberformat@npm:8.7.0": - version: 8.7.0 - resolution: "@formatjs/intl-numberformat@npm:8.7.0" +"@formatjs/intl-numberformat@npm:8.7.2": + version: 8.7.2 + resolution: "@formatjs/intl-numberformat@npm:8.7.2" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 - "@formatjs/intl-localematcher": 0.4.0 + "@formatjs/ecma402-abstract": 1.17.2 + "@formatjs/intl-localematcher": 0.4.2 tslib: ^2.4.0 - checksum: 987bd3e6a48e6efa054d9f526b3cba01675a6c96ffc6d652f6053f3dd1cbae5e56ac784718d135a2e2cd6c7afab4f89c0a592a28e2ff93134baeddc1fa1aff30 + checksum: 5d2247ebc4e64cf57feb510674874acefd171459e314345e3b1b00c4f74dbe7b15572b57419905964000093460f04f5611ad2550cac5250d8958dbd1e7dbab1d languageName: node linkType: hard -"@formatjs/intl-pluralrules@npm:5.2.4": - version: 5.2.4 - resolution: "@formatjs/intl-pluralrules@npm:5.2.4" +"@formatjs/intl-pluralrules@npm:5.2.6": + version: 5.2.6 + resolution: "@formatjs/intl-pluralrules@npm:5.2.6" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 - "@formatjs/intl-localematcher": 0.4.0 + "@formatjs/ecma402-abstract": 1.17.2 + "@formatjs/intl-localematcher": 0.4.2 tslib: ^2.4.0 - checksum: a55445724a65c7c82896792babb2522a03774f3dd370bda2c8a76103528f71e101be84636ae4b161f68fc68afb63f1e61a3bf7489c07ffa722c8213199113814 + checksum: 35805d07c21d1f759f9b49a1cc745d989b0884a265133518740512e86c6ebcadf1532074e11deae2e1a2e672bb8883f036e2d8a47fb3b04f86ccb9a3ba8429e5 languageName: node linkType: hard -"@formatjs/intl-relativetimeformat@npm:11.2.4": - version: 11.2.4 - resolution: "@formatjs/intl-relativetimeformat@npm:11.2.4" +"@formatjs/intl-relativetimeformat@npm:11.2.6": + version: 11.2.6 + resolution: "@formatjs/intl-relativetimeformat@npm:11.2.6" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 - "@formatjs/intl-localematcher": 0.4.0 + "@formatjs/ecma402-abstract": 1.17.2 + "@formatjs/intl-localematcher": 0.4.2 tslib: ^2.4.0 - checksum: 8a99abd4fa7a4dec6d46140940709d83c094f4dce5e331f0556e72d75f375f6758d3fcfaee9e78cd313dcded17fd6788814a4a0bee542e83ec74cef71d35e2bf + checksum: 6e568251e231946afd06fa8415036d9fe1b8a89a88af725ad779ad9a07158c2d1fac2c46dffd6fd4b66eefcd4a022f7db68cebaec5516caeccc70bf2e37967bd languageName: node linkType: hard @@ -9692,14 +9692,14 @@ __metadata: "@codemirror/state": 6.2.1 "@codemirror/view": 6.19.0 "@egjs/hammerjs": 2.0.17 - "@formatjs/intl-datetimeformat": 6.10.0 - "@formatjs/intl-displaynames": 6.5.0 + "@formatjs/intl-datetimeformat": 6.10.2 + "@formatjs/intl-displaynames": 6.5.2 "@formatjs/intl-getcanonicallocales": 2.2.1 - "@formatjs/intl-listformat": 7.4.0 - "@formatjs/intl-locale": 3.3.2 - "@formatjs/intl-numberformat": 8.7.0 - "@formatjs/intl-pluralrules": 5.2.4 - "@formatjs/intl-relativetimeformat": 11.2.4 + "@formatjs/intl-listformat": 7.4.2 + "@formatjs/intl-locale": 3.3.4 + "@formatjs/intl-numberformat": 8.7.2 + "@formatjs/intl-pluralrules": 5.2.6 + "@formatjs/intl-relativetimeformat": 11.2.6 "@fullcalendar/core": 6.1.8 "@fullcalendar/daygrid": 6.1.8 "@fullcalendar/interaction": 6.1.8 @@ -9832,7 +9832,7 @@ __metadata: husky: 8.0.3 idb-keyval: 6.2.1 instant-mocha: 1.5.2 - intl-messageformat: 10.5.0 + intl-messageformat: 10.5.2 js-yaml: 4.1.0 jszip: 3.10.1 leaflet: 1.9.4 @@ -10317,15 +10317,15 @@ __metadata: languageName: node linkType: hard -"intl-messageformat@npm:10.5.0": - version: 10.5.0 - resolution: "intl-messageformat@npm:10.5.0" +"intl-messageformat@npm:10.5.2": + version: 10.5.2 + resolution: "intl-messageformat@npm:10.5.2" dependencies: - "@formatjs/ecma402-abstract": 1.17.0 + "@formatjs/ecma402-abstract": 1.17.2 "@formatjs/fast-memoize": 2.2.0 - "@formatjs/icu-messageformat-parser": 2.6.0 + "@formatjs/icu-messageformat-parser": 2.6.2 tslib: ^2.4.0 - checksum: 164c49028b8bf2685f57f8f018d9a2c1d827e94b1c300ebf9df50b6aef25adedb3bf511b3cf603364d67257634b57926935066b2f3715ccb6c2af683cc0815a6 + checksum: 5ddc83d4c6dbc4dbb453a7c1d609503265f6a5c8207e8cc6660c3d45000fa29551bfbcbfe50331529be8d2f090bc4d6167a4ef85d3b5de986227a4579d038029 languageName: node linkType: hard From e6fd18e23b9d48e1374f4466ff1395c74130e638 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 07:43:55 -0400 Subject: [PATCH 20/81] Update dependency @types/js-yaml to v4.0.6 (#17958) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b8344a0663..e3bf8ae222 100644 --- a/package.json +++ b/package.json @@ -175,7 +175,7 @@ "@types/esprima": "4.0.3", "@types/glob": "8.1.0", "@types/html-minifier-terser": "7.0.0", - "@types/js-yaml": "4.0.5", + "@types/js-yaml": "4.0.6", "@types/leaflet": "1.9.4", "@types/leaflet-draw": "1.0.8", "@types/luxon": "3.3.2", diff --git a/yarn.lock b/yarn.lock index aa5f4b2be9..6fd11a1b51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4312,10 +4312,10 @@ __metadata: languageName: node linkType: hard -"@types/js-yaml@npm:4.0.5": - version: 4.0.5 - resolution: "@types/js-yaml@npm:4.0.5" - checksum: 7dcac8c50fec31643cc9d6444b5503239a861414cdfaa7ae9a38bc22597c4d850c4b8cec3d82d73b3fbca408348ce223b0408d598b32e094470dfffc6d486b4d +"@types/js-yaml@npm:4.0.6": + version: 4.0.6 + resolution: "@types/js-yaml@npm:4.0.6" + checksum: d4439ec2cc830d355c2a1d7508f49888931b2cfe59d786d27621edd530bf06314b1dceeaa759e21f9b035a0ff623a0ca306752ebb73df9485c02abe045bd962c languageName: node linkType: hard @@ -9767,7 +9767,7 @@ __metadata: "@types/esprima": 4.0.3 "@types/glob": 8.1.0 "@types/html-minifier-terser": 7.0.0 - "@types/js-yaml": 4.0.5 + "@types/js-yaml": 4.0.6 "@types/leaflet": 1.9.4 "@types/leaflet-draw": 1.0.8 "@types/luxon": 3.3.2 From 46e4eafe957f235c0fcbcc1b72e61d8378fecbbd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 07:45:50 -0400 Subject: [PATCH 21/81] Update dependency @types/babel__plugin-transform-runtime to v7.9.3 (#17957) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index e3bf8ae222..06d914203c 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,7 @@ "@rollup/plugin-json": "6.0.0", "@rollup/plugin-node-resolve": "15.2.1", "@rollup/plugin-replace": "5.0.2", - "@types/babel__plugin-transform-runtime": "7.9.2", + "@types/babel__plugin-transform-runtime": "7.9.3", "@types/chromecast-caf-receiver": "6.0.10", "@types/chromecast-caf-sender": "1.0.6", "@types/esprima": "4.0.3", diff --git a/yarn.lock b/yarn.lock index 6fd11a1b51..91782e335f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4064,10 +4064,10 @@ __metadata: languageName: node linkType: hard -"@types/babel__plugin-transform-runtime@npm:7.9.2": - version: 7.9.2 - resolution: "@types/babel__plugin-transform-runtime@npm:7.9.2" - checksum: 0eb18bf14b478804d34f96d47b992e53043776b8679e0c110051985a22ec18497e6f2c6d20f5289876c6094ccac2d41fa2f716a150e7512cee0a5c2ae1cf79b3 +"@types/babel__plugin-transform-runtime@npm:7.9.3": + version: 7.9.3 + resolution: "@types/babel__plugin-transform-runtime@npm:7.9.3" + checksum: ab6dce927ce6e2adb5106e591872f27c6bce2a2ca7314645fd0273caf24a433da50444916eb7ed5937ad2a6b74bc2c2246efe85ea5b9cb2c1edba261751c5e94 languageName: node linkType: hard @@ -9761,7 +9761,7 @@ __metadata: "@rollup/plugin-node-resolve": 15.2.1 "@rollup/plugin-replace": 5.0.2 "@thomasloven/round-slider": 0.6.0 - "@types/babel__plugin-transform-runtime": 7.9.2 + "@types/babel__plugin-transform-runtime": 7.9.3 "@types/chromecast-caf-receiver": 6.0.10 "@types/chromecast-caf-sender": 1.0.6 "@types/esprima": 4.0.3 From 713ebfcc2247843f462703c73a408d25795263c3 Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Tue, 19 Sep 2023 07:56:55 -0400 Subject: [PATCH 22/81] Enable shipped proposals in Babel (#17909) --- build-scripts/bundle.cjs | 1 + build-scripts/list-plugins-and-polyfills.js | 26 ++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/build-scripts/bundle.cjs b/build-scripts/bundle.cjs index e5b41979ca..ec800f9f57 100644 --- a/build-scripts/bundle.cjs +++ b/build-scripts/bundle.cjs @@ -100,6 +100,7 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({ useBuiltIns: latestBuild ? false : "entry", corejs: latestBuild ? false : { version: "3.32", proposals: true }, bugfixes: true, + shippedProposals: true, }, ], "@babel/preset-typescript", diff --git a/build-scripts/list-plugins-and-polyfills.js b/build-scripts/list-plugins-and-polyfills.js index a0978e6dba..abda2ca1ed 100755 --- a/build-scripts/list-plugins-and-polyfills.js +++ b/build-scripts/list-plugins-and-polyfills.js @@ -6,6 +6,8 @@ import presetEnv from "@babel/preset-env"; import compilationTargets from "@babel/helper-compilation-targets"; import coreJSCompat from "core-js-compat"; import { logPlugin } from "@babel/preset-env/lib/debug.js"; +// eslint-disable-next-line import/no-relative-packages +import shippedPolyfills from "../node_modules/babel-plugin-polyfill-corejs3/lib/shipped-proposals.js"; import { babelOptions } from "./bundle.cjs"; const detailsOpen = (heading) => @@ -26,6 +28,22 @@ const dummyAPI = { targets: () => ({}), }; +// Generate filter function based on proposal/method inputs +// Copied and adapted from babel-plugin-polyfill-corejs3/esm/index.mjs +const polyfillFilter = (method, proposals, shippedProposals) => (name) => { + if (proposals || method === "entry-global") return true; + if (shippedProposals && shippedPolyfills.default.has(name)) { + return true; + } + if (name.startsWith("esnext.")) { + const esName = `es.${name.slice(7)}`; + // If its imaginative esName is not in latest compat data, it means the proposal is not stage 4 + return esName in coreJSCompat.data; + } + return true; +}; + +// Log the plugins and polyfills for each build environment for (const buildType of ["Modern", "Legacy"]) { const browserslistEnv = buildType.toLowerCase(); const babelOpts = babelOptions({ latestBuild: browserslistEnv === "modern" }); @@ -46,7 +64,13 @@ for (const buildType of ["Modern", "Legacy"]) { const targets = compilationTargets.default(babelOpts?.targets, { browserslistEnv, }); - const polyfillList = coreJSCompat({ targets }).list; + const polyfillList = coreJSCompat({ targets }).list.filter( + polyfillFilter( + `${presetEnvOpts.useBuiltIns}-global`, + presetEnvOpts?.corejs?.proposals, + presetEnvOpts?.shippedProposals + ) + ); console.log( "The following %i polyfills may be injected by Babel:\n", polyfillList.length From e46f2cd9bf69effe927e484d48a4d06888f5aa9d Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Tue, 19 Sep 2023 08:51:38 -0400 Subject: [PATCH 23/81] Adjust password manager polyfill for form injections (#17830) --- src/auth/ha-password-manager-polyfill.ts | 91 ++++++++++++++++++------ 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/src/auth/ha-password-manager-polyfill.ts b/src/auth/ha-password-manager-polyfill.ts index 99e6e1926f..7c66d11fe3 100644 --- a/src/auth/ha-password-manager-polyfill.ts +++ b/src/auth/ha-password-manager-polyfill.ts @@ -35,20 +35,47 @@ export class HaPasswordManagerPolyfill extends LitElement { super.connectedCallback(); this._styleElement = document.createElement("style"); this._styleElement.textContent = css` + /* Polyfill form is sized and vertically aligned with true form, then positioned offscreen + rather than hiding so it does not create a new stacking context */ .password-manager-polyfill { position: absolute; - opacity: 0; - z-index: -1; + box-sizing: border-box; } - .password-manager-polyfill input { + /* Excluding our wrapper, move any children back on screen, including anything injected that might not already be positioned */ + .password-manager-polyfill > *:not(.wrapper), + .password-manager-polyfill > .wrapper > * { + position: relative; + left: 10000px; + } + /* Size and hide our polyfill fields */ + .password-manager-polyfill .underneath { + display: block; + box-sizing: border-box; width: 100%; - height: 62px; - padding: 0; + padding: 0 16px; border: 0; + z-index: -1; + height: 21px; + /* Transparency is only needed to hide during paint or in case of misalignment, + but LastPass will fail if it's 0, so we use 1% */ + opacity: 0.01; } - .password-manager-polyfill input[type="submit"] { - width: 0; - height: 0; + .password-manager-polyfill input.underneath { + height: 28px; + margin-bottom: 30.5px; + } + /* Button position is not important, but size should not be zero */ + .password-manager-polyfill > input.underneath[type="submit"] { + width: 1px; + height: 1px; + margin: 0 auto; + overflow: hidden; + } + /* Ensure injected elements will be on top */ + .password-manager-polyfill > *:not(.underneath, .wrapper), + .password-manager-polyfill > .wrapper > *:not(.underneath) { + isolation: isolate; + z-index: auto; } `.toString(); document.head.append(this._styleElement); @@ -77,16 +104,25 @@ export class HaPasswordManagerPolyfill extends LitElement { class="password-manager-polyfill" style=${styleMap({ top: `${this.boundingRect?.y || 148}px`, - left: `calc(50% - ${(this.boundingRect?.width || 360) / 2}px)`, + left: `calc(50% - ${ + (this.boundingRect?.width || 360) / 2 + }px - 10000px)`, width: `${this.boundingRect?.width || 360}px`, })} - aria-hidden="true" + action="/auth" + method="post" @submit=${this._handleSubmit} > ${autocompleteLoginFields(this.step.data_schema).map((input) => this.render_input(input) )} - + `; } @@ -99,26 +135,35 @@ export class HaPasswordManagerPolyfill extends LitElement { return ""; } return html` - + + + + `; } - private _handleSubmit(ev: Event) { + private _handleSubmit(ev: SubmitEvent) { ev.preventDefault(); fireEvent(this, "form-submitted"); } private _valueChanged(ev: Event) { - const target = ev.target! as HTMLInputElement; + const target = ev.target as HTMLInputElement; this.stepData = { ...this.stepData, [target.id]: target.value }; fireEvent(this, "value-changed", { value: this.stepData, From 5e107d43d7a6fcb10388a95eec6eec6258796c36 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:36:07 -0400 Subject: [PATCH 24/81] Update babel monorepo to v7.22.20 (#17965) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 4 ++-- yarn.lock | 40 ++++++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 06d914203c..778696e992 100644 --- a/package.json +++ b/package.json @@ -153,10 +153,10 @@ "xss": "1.0.14" }, "devDependencies": { - "@babel/core": "7.22.19", + "@babel/core": "7.22.20", "@babel/plugin-proposal-decorators": "7.22.15", "@babel/plugin-transform-runtime": "7.22.15", - "@babel/preset-env": "7.22.15", + "@babel/preset-env": "7.22.20", "@babel/preset-typescript": "7.22.15", "@koa/cors": "4.0.0", "@lokalise/node-api": "11.0.1", diff --git a/yarn.lock b/yarn.lock index 91782e335f..c50e244f4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -55,33 +55,33 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": - version: 7.22.9 - resolution: "@babel/compat-data@npm:7.22.9" - checksum: bed77d9044ce948b4327b30dd0de0779fa9f3a7ed1f2d31638714ed00229fa71fc4d1617ae0eb1fad419338d3658d0e9a5a083297451e09e73e078d0347ff808 +"@babel/compat-data@npm:^7.22.20, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": + version: 7.22.20 + resolution: "@babel/compat-data@npm:7.22.20" + checksum: efedd1d18878c10fde95e4d82b1236a9aba41395ef798cbb651f58dbf5632dbff475736c507b8d13d4c8f44809d41c0eb2ef0d694283af9ba5dd8339b6dab451 languageName: node linkType: hard -"@babel/core@npm:7.22.19, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": - version: 7.22.19 - resolution: "@babel/core@npm:7.22.19" +"@babel/core@npm:7.22.20, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": + version: 7.22.20 + resolution: "@babel/core@npm:7.22.20" dependencies: "@ampproject/remapping": ^2.2.0 "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.22.15 "@babel/helper-compilation-targets": ^7.22.15 - "@babel/helper-module-transforms": ^7.22.19 + "@babel/helper-module-transforms": ^7.22.20 "@babel/helpers": ^7.22.15 "@babel/parser": ^7.22.16 "@babel/template": ^7.22.15 - "@babel/traverse": ^7.22.19 + "@babel/traverse": ^7.22.20 "@babel/types": ^7.22.19 convert-source-map: ^1.7.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: d603f6f00b20c1edff6a6c9d32c559d4d09ee873380317271b57322bfb9da4349e59df53a21c65e9e5a1136f52bf612389d798640454e6fd9246a5c6d76b0c5c + checksum: 73663a079194b5dc406b2e2e5e50db81977d443e4faf7ef2c27e5836cd9a359e81e551115193dc9b1a93471275351a972e54904f4d3aa6cb156f51e26abf6765 languageName: node linkType: hard @@ -219,7 +219,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.22.15, @babel/helper-module-transforms@npm:^7.22.19, @babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9": +"@babel/helper-module-transforms@npm:^7.22.15, @babel/helper-module-transforms@npm:^7.22.20, @babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9": version: 7.22.20 resolution: "@babel/helper-module-transforms@npm:7.22.20" dependencies: @@ -1256,11 +1256,11 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:7.22.15, @babel/preset-env@npm:^7.11.0": - version: 7.22.15 - resolution: "@babel/preset-env@npm:7.22.15" +"@babel/preset-env@npm:7.22.20, @babel/preset-env@npm:^7.11.0": + version: 7.22.20 + resolution: "@babel/preset-env@npm:7.22.20" dependencies: - "@babel/compat-data": ^7.22.9 + "@babel/compat-data": ^7.22.20 "@babel/helper-compilation-targets": ^7.22.15 "@babel/helper-plugin-utils": ^7.22.5 "@babel/helper-validator-option": ^7.22.15 @@ -1334,7 +1334,7 @@ __metadata: "@babel/plugin-transform-unicode-regex": ^7.22.5 "@babel/plugin-transform-unicode-sets-regex": ^7.22.5 "@babel/preset-modules": 0.1.6-no-external-plugins - "@babel/types": ^7.22.15 + "@babel/types": ^7.22.19 babel-plugin-polyfill-corejs2: ^0.4.5 babel-plugin-polyfill-corejs3: ^0.8.3 babel-plugin-polyfill-regenerator: ^0.5.2 @@ -1342,7 +1342,7 @@ __metadata: semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c3cf0223cab006cbf0c563a49a5076caa0b62e3b61b4f10ba857347fcd4f85dbb662a78e6f289e4f29f72c36974696737ae86c23da114617f5b00ab2c1c66126 + checksum: 99357a5cb30f53bacdc0d1cd6dff0f052ea6c2d1ba874d969bba69897ef716e87283e84a59dc52fb49aa31fd1b6f55ed756c64c04f5678380700239f6030b881 languageName: node linkType: hard @@ -1401,7 +1401,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.22.15, @babel/traverse@npm:^7.22.19": +"@babel/traverse@npm:^7.22.15, @babel/traverse@npm:^7.22.20": version: 7.22.20 resolution: "@babel/traverse@npm:7.22.20" dependencies: @@ -9677,10 +9677,10 @@ __metadata: version: 0.0.0-use.local resolution: "home-assistant-frontend@workspace:." dependencies: - "@babel/core": 7.22.19 + "@babel/core": 7.22.20 "@babel/plugin-proposal-decorators": 7.22.15 "@babel/plugin-transform-runtime": 7.22.15 - "@babel/preset-env": 7.22.15 + "@babel/preset-env": 7.22.20 "@babel/preset-typescript": 7.22.15 "@babel/runtime": 7.22.15 "@braintree/sanitize-url": 6.0.4 From 3349031cbd1128f864580fd81bcd5c12512ccdcf Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 20 Sep 2023 12:09:44 +0200 Subject: [PATCH 25/81] Simplify data table template (#17825) * Simplify data table template * Fix backup and gallery --- gallery/src/pages/misc/entity-state.ts | 8 +- hassio/src/backups/hassio-backups.ts | 22 +- src/components/data-table/ha-data-table.ts | 4 +- .../ha-config-application-credentials.ts | 9 +- .../config/automation/ha-automation-picker.ts | 45 +-- src/panels/config/backup/ha-config-backup.ts | 20 +- .../config/blueprint/ha-blueprint-overview.ts | 29 +- .../devices/ha-config-devices-dashboard.ts | 284 +++++++++--------- .../config/entities/ha-config-entities.ts | 53 ++-- .../config/helpers/ha-config-helpers.ts | 48 ++- .../zha/zha-clusters-data-table.ts | 4 +- .../zha/zha-device-endpoint-data-table.ts | 20 +- .../zha/zha-groups-dashboard.ts | 10 +- .../zwave_js/zwave_js-provisioned.ts | 18 +- .../ha-config-lovelace-dashboards.ts | 32 +- .../resources/ha-config-lovelace-resources.ts | 8 +- src/panels/config/scene/ha-scene-dashboard.ts | 34 ++- src/panels/config/script/ha-script-picker.ts | 275 +++++++++-------- src/panels/config/tags/ha-config-tags.ts | 167 +++++----- src/panels/config/users/ha-config-users.ts | 28 +- .../ha-config-voice-assistants-expose.ts | 20 +- .../statistics/developer-tools-statistics.ts | 19 +- .../card-editor/hui-entity-picker-table.ts | 10 +- 23 files changed, 607 insertions(+), 560 deletions(-) diff --git a/gallery/src/pages/misc/entity-state.ts b/gallery/src/pages/misc/entity-state.ts index 58c639e6fd..9e62a6ae91 100644 --- a/gallery/src/pages/misc/entity-state.ts +++ b/gallery/src/pages/misc/entity-state.ts @@ -343,7 +343,7 @@ export class DemoEntityState extends LitElement { const columns: DataTableColumnContainer = { icon: { title: "Icon", - template: (_, entry) => html` + template: (entry) => html` + template: (entry) => html`${computeStateDisplay( hass.localize, entry.stateObj, @@ -371,14 +371,14 @@ export class DemoEntityState extends LitElement { }, device_class: { title: "Device class", - template: (dc) => html`${dc ?? "-"}`, + template: (entry) => html`${entry.device_class ?? "-"}`, width: "20%", filterable: true, sortable: true, }, domain: { title: "Domain", - template: (_, entry) => html`${computeDomain(entry.entity_id)}`, + template: (entry) => html`${computeDomain(entry.entity_id)}`, width: "20%", filterable: true, sortable: true, diff --git a/hassio/src/backups/hassio-backups.ts b/hassio/src/backups/hassio-backups.ts index 7dc5c94972..80282aa7d6 100644 --- a/hassio/src/backups/hassio-backups.ts +++ b/hassio/src/backups/hassio-backups.ts @@ -49,6 +49,10 @@ import { showHassioCreateBackupDialog } from "../dialogs/backup/show-dialog-hass import { supervisorTabs } from "../hassio-tabs"; import { hassioStyle } from "../resources/hassio-style"; +type BackupItem = HassioBackup & { + secondary: string; +}; + @customElement("hassio-backups") export class HassioBackups extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -117,15 +121,15 @@ export class HassioBackups extends LitElement { } private _columns = memoizeOne( - (narrow: boolean): DataTableColumnContainer => ({ + (narrow: boolean): DataTableColumnContainer => ({ name: { title: this.supervisor.localize("backup.name"), main: true, sortable: true, filterable: true, grows: true, - template: (entry: string, backup: any) => - html`${entry || backup.slug} + template: (backup) => + html`${backup.name || backup.slug}
${backup.secondary}
`, }, size: { @@ -134,7 +138,7 @@ export class HassioBackups extends LitElement { hidden: narrow, filterable: true, sortable: true, - template: (entry: number) => Math.ceil(entry * 10) / 10 + " MB", + template: (backup) => Math.ceil(backup.size * 10) / 10 + " MB", }, location: { title: this.supervisor.localize("backup.location"), @@ -142,8 +146,8 @@ export class HassioBackups extends LitElement { hidden: narrow, filterable: true, sortable: true, - template: (entry: string | null) => - entry || this.supervisor.localize("backup.data_disk"), + template: (backup) => + backup.location || this.supervisor.localize("backup.data_disk"), }, date: { title: this.supervisor.localize("backup.created"), @@ -152,8 +156,8 @@ export class HassioBackups extends LitElement { hidden: narrow, filterable: true, sortable: true, - template: (entry: string) => - relativeTime(new Date(entry), this.hass.locale), + template: (backup) => + relativeTime(new Date(backup.date), this.hass.locale), }, secondary: { title: "", @@ -163,7 +167,7 @@ export class HassioBackups extends LitElement { }) ); - private _backupData = memoizeOne((backups: HassioBackup[]) => + private _backupData = memoizeOne((backups: HassioBackup[]): BackupItem[] => backups.map((backup) => ({ ...backup, secondary: this._computeBackupContent(backup), diff --git a/src/components/data-table/ha-data-table.ts b/src/components/data-table/ha-data-table.ts index e888690639..10293fc761 100644 --- a/src/components/data-table/ha-data-table.ts +++ b/src/components/data-table/ha-data-table.ts @@ -74,7 +74,7 @@ export interface DataTableColumnData extends DataTableSortColumnData { title: TemplateResult | string; label?: TemplateResult | string; type?: "numeric" | "icon" | "icon-button" | "overflow-menu" | "flex"; - template?: (data: any, row: T) => TemplateResult | string | typeof nothing; + template?: (row: T) => TemplateResult | string | typeof nothing; width?: string; maxWidth?: string; grows?: boolean; @@ -431,7 +431,7 @@ export class HaDataTable extends LitElement { }) : ""} > - ${column.template ? column.template(row[key], row) : row[key]} + ${column.template ? column.template(row) : row[key]} `; })} diff --git a/src/panels/config/application_credentials/ha-config-application-credentials.ts b/src/panels/config/application_credentials/ha-config-application-credentials.ts index da139623ee..ec1b97dba3 100644 --- a/src/panels/config/application_credentials/ha-config-application-credentials.ts +++ b/src/panels/config/application_credentials/ha-config-application-credentials.ts @@ -62,17 +62,16 @@ export class HaConfigApplicationCredentials extends LitElement { ), direction: "asc", grows: true, - template: (_, entry: ApplicationCredential) => html`${entry.name}`, + template: (entry) => html`${entry.name}`, }, - clientId: { + client_id: { title: localize( "ui.panel.config.application_credentials.picker.headers.client_id" ), width: "30%", direction: "asc", hidden: narrow, - template: (_, entry: ApplicationCredential) => - html`${entry.client_id}`, + template: (entry) => html`${entry.client_id}`, }, application: { title: localize( @@ -81,7 +80,7 @@ export class HaConfigApplicationCredentials extends LitElement { sortable: true, width: "30%", direction: "asc", - template: (_, entry) => html`${domainToName(localize, entry.domain)}`, + template: (entry) => html`${domainToName(localize, entry.domain)}`, }, }; diff --git a/src/panels/config/automation/ha-automation-picker.ts b/src/panels/config/automation/ha-automation-picker.ts index a6ae94240b..c608b20086 100644 --- a/src/panels/config/automation/ha-automation-picker.ts +++ b/src/panels/config/automation/ha-automation-picker.ts @@ -55,6 +55,12 @@ import { findRelated } from "../../../data/search"; import { fetchBlueprints } from "../../../data/blueprint"; import { UNAVAILABLE } from "../../../data/entity"; +type AutomationItem = AutomationEntity & { + name: string; + last_triggered?: string | undefined; + disabled: boolean; +}; + @customElement("ha-automation-picker") class HaAutomationPicker extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -79,7 +85,7 @@ class HaAutomationPicker extends LitElement { ( automations: AutomationEntity[], filteredAutomations?: string[] | null - ) => { + ): AutomationItem[] => { if (filteredAutomations === null) { return []; } @@ -100,14 +106,14 @@ class HaAutomationPicker extends LitElement { private _columns = memoizeOne( (narrow: boolean, _locale): DataTableColumnContainer => { - const columns: DataTableColumnContainer = { + const columns: DataTableColumnContainer = { icon: { title: "", label: this.hass.localize( "ui.panel.config.automation.picker.headers.state" ), type: "icon", - template: (_, automation) => + template: (automation) => html` { + ? (automation) => { const date = new Date(automation.attributes.last_triggered); const now = new Date(); const dayDifference = differenceInDays(now, date); return html` - ${name} + ${automation.name}
${this.hass.localize("ui.card.automation.last_triggered")}: ${automation.attributes.last_triggered @@ -156,20 +162,17 @@ class HaAutomationPicker extends LitElement { sortable: true, width: "20%", title: this.hass.localize("ui.card.automation.last_triggered"), - template: (last_triggered) => { - const date = new Date(last_triggered); + template: (automation) => { + if (!automation.last_triggered) { + return this.hass.localize("ui.components.relative_time.never"); + } + const date = new Date(automation.last_triggered); const now = new Date(); const dayDifference = differenceInDays(now, date); return html` - ${last_triggered - ? dayDifference > 3 - ? formatShortDateTime( - date, - this.hass.locale, - this.hass.config - ) - : relativeTime(date, this.hass.locale) - : this.hass.localize("ui.components.relative_time.never")} + ${dayDifference > 3 + ? formatShortDateTime(date, this.hass.locale, this.hass.config) + : relativeTime(date, this.hass.locale)} `; }, }; @@ -178,8 +181,8 @@ class HaAutomationPicker extends LitElement { columns.disabled = this.narrow ? { title: "", - template: (disabled: boolean) => - disabled + template: (automation) => + automation.disabled ? html` ${this.hass.localize( @@ -196,8 +199,8 @@ class HaAutomationPicker extends LitElement { : { width: "20%", title: "", - template: (disabled: boolean) => - disabled + template: (automation) => + automation.disabled ? html` ${this.hass.localize( @@ -212,7 +215,7 @@ class HaAutomationPicker extends LitElement { title: "", width: this.narrow ? undefined : "10%", type: "overflow-menu", - template: (_: string, automation: any) => html` + template: (automation) => html` ({ + (narrow, _language): DataTableColumnContainer => ({ name: { title: this.hass.localize("ui.panel.config.backup.name"), main: true, sortable: true, filterable: true, grows: true, - template: (entry: string, backup: BackupContent) => - html`${entry} + template: (backup) => + html`${backup.name}
${backup.path}
`, }, size: { @@ -65,7 +65,7 @@ class HaConfigBackup extends LitElement { hidden: narrow, filterable: true, sortable: true, - template: (entry: number) => Math.ceil(entry * 10) / 10 + " MB", + template: (backup) => Math.ceil(backup.size * 10) / 10 + " MB", }, date: { title: this.hass.localize("ui.panel.config.backup.created"), @@ -74,15 +74,15 @@ class HaConfigBackup extends LitElement { hidden: narrow, filterable: true, sortable: true, - template: (entry: string) => - relativeTime(new Date(entry), this.hass.locale), + template: (backup) => + relativeTime(new Date(backup.date), this.hass.locale), }, actions: { title: "", width: "15%", type: "overflow-menu", - template: (_: string, backup: BackupContent) => + template: (backup) => html` { @@ -86,7 +87,7 @@ class HaBlueprintOverview extends LitElement { >; private _processedBlueprints = memoizeOne( - (blueprints: Record) => { + (blueprints: Record): BlueprintMetaDataPath[] => { const result: any[] = []; Object.entries(blueprints).forEach(([type, typeBlueprints]) => Object.entries(typeBlueprints).forEach(([path, blueprint]) => { @@ -125,9 +126,9 @@ class HaBlueprintOverview extends LitElement { direction: "asc", grows: true, template: narrow - ? (name, entity: any) => html` - ${name}
-
${entity.path}
+ ? (blueprint) => html` + ${blueprint.name}
+
${blueprint.path}
` : undefined, }, @@ -135,9 +136,9 @@ class HaBlueprintOverview extends LitElement { title: this.hass.localize( "ui.panel.config.blueprint.overview.headers.type" ), - template: (type: BlueprintDomain) => + template: (blueprint) => html`${this.hass.localize( - `ui.panel.config.blueprint.overview.types.${type}` + `ui.panel.config.blueprint.overview.types.${blueprint.type}` )}`, sortable: true, filterable: true, @@ -163,7 +164,7 @@ class HaBlueprintOverview extends LitElement { title: "", width: this.narrow ? undefined : "10%", type: "overflow-menu", - template: (_: string, blueprint) => + template: (blueprint) => blueprint.error ? html` this._createNew(blueprint), }, @@ -324,7 +325,7 @@ class HaBlueprintOverview extends LitElement { private _handleRowClicked(ev: HASSDomEvent) { const blueprint = this._processedBlueprints(this.blueprints).find( (b) => b.fullpath === ev.detail.id - ); + )!; if (blueprint.error) { showAlertDialog(this, { title: this.hass.localize("ui.panel.config.blueprint.overview.error", { diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index 6697123192..0526d048d1 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -2,27 +2,26 @@ import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item"; import { mdiCancel, mdiFilterVariant, mdiPlus } from "@mdi/js"; import { - css, CSSResultGroup, - html, LitElement, - nothing, TemplateResult, + css, + html, + nothing, } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { HASSDomEvent } from "../../../common/dom/fire_event"; import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { - protocolIntegrationPicked, PROTOCOL_INTEGRATIONS, + protocolIntegrationPicked, } from "../../../common/integrations/protocolIntegrationPicked"; import { navigate } from "../../../common/navigate"; import { LocalizeFunc } from "../../../common/translations/localize"; import { computeRTL } from "../../../common/util/compute_rtl"; import { DataTableColumnContainer, - DataTableRowData, RowClickedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/entity/ha-battery-icon"; @@ -33,9 +32,9 @@ import "../../../components/ha-icon-button"; import { AreaRegistryEntry } from "../../../data/area_registry"; import { ConfigEntry, sortConfigEntries } from "../../../data/config_entries"; import { - computeDeviceName, DeviceEntityLookup, DeviceRegistryEntry, + computeDeviceName, } from "../../../data/device_registry"; import { EntityRegistryEntry, @@ -231,7 +230,7 @@ export class HaConfigDeviceDashboard extends LitElement { outputDevices = outputDevices.filter((device) => !device.disabled_by); } - outputDevices = outputDevices.map((device) => { + const formattedOutputDevices = outputDevices.map((device) => { const deviceEntries = sortConfigEntries( device.config_entries .filter((entId) => entId in entryLookup) @@ -277,156 +276,153 @@ export class HaConfigDeviceDashboard extends LitElement { }; }); - this._numHiddenDevices = startLength - outputDevices.length; + this._numHiddenDevices = startLength - formattedOutputDevices.length; return { - devicesOutput: outputDevices, + devicesOutput: formattedOutputDevices, filteredConfigEntry: filterConfigEntry, filteredDomains, }; } ); - private _columns = memoizeOne( - (narrow: boolean, showDisabled: boolean): DataTableColumnContainer => { - const columns: DataTableColumnContainer = { - icon: { - title: "", - type: "icon", - template: (_icon, device) => - device.domains.length - ? html`` - : "", - }, - }; + private _columns = memoizeOne((narrow: boolean, showDisabled: boolean) => { + type DeviceItem = ReturnType< + typeof this._devicesAndFilterDomains + >["devicesOutput"][number]; - if (narrow) { - columns.name = { - title: this.hass.localize( - "ui.panel.config.devices.data_table.device" - ), - main: true, - sortable: true, - filterable: true, - direction: "asc", - grows: true, - template: (name, device: DataTableRowData) => html` - ${name} -
${device.area} | ${device.integration}
- `, - }; - } else { - columns.name = { - title: this.hass.localize( - "ui.panel.config.devices.data_table.device" - ), - main: true, - sortable: true, - filterable: true, - grows: true, - direction: "asc", - }; - } + const columns: DataTableColumnContainer = { + icon: { + title: "", + type: "icon", + template: (device) => + device.domains.length + ? html`` + : "", + }, + }; - columns.manufacturer = { - title: this.hass.localize( - "ui.panel.config.devices.data_table.manufacturer" - ), - sortable: true, - hidden: narrow, - filterable: true, - width: "15%", - }; - columns.model = { - title: this.hass.localize("ui.panel.config.devices.data_table.model"), - sortable: true, - hidden: narrow, - filterable: true, - width: "15%", - }; - columns.area = { - title: this.hass.localize("ui.panel.config.devices.data_table.area"), - sortable: true, - hidden: narrow, - filterable: true, - width: "15%", - }; - columns.integration = { - title: this.hass.localize( - "ui.panel.config.devices.data_table.integration" - ), - sortable: true, - hidden: narrow, - filterable: true, - width: "15%", - }; - columns.battery_entity = { - title: this.hass.localize("ui.panel.config.devices.data_table.battery"), + if (narrow) { + columns.name = { + title: this.hass.localize("ui.panel.config.devices.data_table.device"), + main: true, sortable: true, filterable: true, - type: "numeric", - width: narrow ? "95px" : "15%", - maxWidth: "95px", - valueColumn: "battery_level", - template: (batteryEntityPair: DeviceRowData["battery_entity"]) => { - const battery = - batteryEntityPair && batteryEntityPair[0] - ? this.hass.states[batteryEntityPair[0]] - : undefined; - const batteryDomain = battery - ? computeStateDomain(battery) - : undefined; - const batteryCharging = - batteryEntityPair && batteryEntityPair[1] - ? this.hass.states[batteryEntityPair[1]] - : undefined; - - return battery && - (batteryDomain === "binary_sensor" || !isNaN(battery.state as any)) - ? html` - ${batteryDomain === "sensor" - ? this.hass.formatEntityState(battery) - : nothing} - - ` - : html`—`; - }, + direction: "asc", + grows: true, + template: (device) => html` + ${device.name} +
${device.area} | ${device.integration}
+ `, + }; + } else { + columns.name = { + title: this.hass.localize("ui.panel.config.devices.data_table.device"), + main: true, + sortable: true, + filterable: true, + grows: true, + direction: "asc", }; - if (showDisabled) { - columns.disabled_by = { - title: "", - label: this.hass.localize( - "ui.panel.config.devices.data_table.disabled_by" - ), - type: "icon", - template: (disabled_by) => - disabled_by - ? html`
- - - ${this.hass.localize("ui.panel.config.devices.disabled")} - -
` - : "—", - }; - } - return columns; } - ); + + columns.manufacturer = { + title: this.hass.localize( + "ui.panel.config.devices.data_table.manufacturer" + ), + sortable: true, + hidden: narrow, + filterable: true, + width: "15%", + }; + columns.model = { + title: this.hass.localize("ui.panel.config.devices.data_table.model"), + sortable: true, + hidden: narrow, + filterable: true, + width: "15%", + }; + columns.area = { + title: this.hass.localize("ui.panel.config.devices.data_table.area"), + sortable: true, + hidden: narrow, + filterable: true, + width: "15%", + }; + columns.integration = { + title: this.hass.localize( + "ui.panel.config.devices.data_table.integration" + ), + sortable: true, + hidden: narrow, + filterable: true, + width: "15%", + }; + columns.battery_entity = { + title: this.hass.localize("ui.panel.config.devices.data_table.battery"), + sortable: true, + filterable: true, + type: "numeric", + width: narrow ? "95px" : "15%", + maxWidth: "95px", + valueColumn: "battery_level", + template: (device) => { + const batteryEntityPair = device.battery_entity; + const battery = + batteryEntityPair && batteryEntityPair[0] + ? this.hass.states[batteryEntityPair[0]] + : undefined; + const batteryDomain = battery ? computeStateDomain(battery) : undefined; + const batteryCharging = + batteryEntityPair && batteryEntityPair[1] + ? this.hass.states[batteryEntityPair[1]] + : undefined; + + return battery && + (batteryDomain === "binary_sensor" || !isNaN(battery.state as any)) + ? html` + ${batteryDomain === "sensor" + ? this.hass.formatEntityState(battery) + : nothing} + + ` + : html`—`; + }, + }; + if (showDisabled) { + columns.disabled_by = { + title: "", + label: this.hass.localize( + "ui.panel.config.devices.data_table.disabled_by" + ), + type: "icon", + template: (device) => + device.disabled_by + ? html`
+ + + ${this.hass.localize("ui.panel.config.devices.disabled")} + +
` + : "—", + }; + } + return columns; + }); public willUpdate(changedProps) { if (changedProps.has("_searchParms")) { diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index 9c0815850c..8a0dcc6f98 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -183,7 +183,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { "ui.panel.config.entities.picker.headers.state_icon" ), type: "icon", - template: (_, entry: EntityRow) => html` + template: (entry) => html` html` - ${name}
+ ? (entry) => html` + ${entry.name}
- ${entity.entity_id} | - ${this.hass.localize(`component.${entity.platform}.title`) || - entity.platform} + ${entry.entity_id} | + ${this.hass.localize(`component.${entry.platform}.title`) || + entry.platform}
` : undefined, @@ -228,8 +228,9 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { sortable: true, filterable: true, width: "20%", - template: (platform) => - this.hass.localize(`component.${platform}.title`) || platform, + template: (entry) => + this.hass.localize(`component.${entry.platform}.title`) || + entry.platform, }, area: { title: this.hass.localize( @@ -248,10 +249,12 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { hidden: narrow || !showDisabled, filterable: true, width: "15%", - template: (disabled_by: EntityRegistryEntry["disabled_by"]) => - disabled_by === null + template: (entry) => + entry.disabled_by === null ? "—" - : this.hass.localize(`config_entry.disabled_by.${disabled_by}`), + : this.hass.localize( + `config_entry.disabled_by.${entry.disabled_by}` + ), }, status: { title: this.hass.localize( @@ -261,11 +264,11 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { sortable: true, filterable: true, width: "68px", - template: (_status, entity: EntityRow) => - entity.unavailable || - entity.disabled_by || - entity.hidden_by || - entity.readonly + template: (entry) => + entry.unavailable || + entry.disabled_by || + entry.hidden_by || + entry.readonly ? html`
- ${entity.restored + ${entry.restored ? this.hass.localize( "ui.panel.config.entities.picker.status.restored" ) - : entity.unavailable + : entry.unavailable ? this.hass.localize( "ui.panel.config.entities.picker.status.unavailable" ) - : entity.disabled_by + : entry.disabled_by ? this.hass.localize( "ui.panel.config.entities.picker.status.disabled" ) - : entity.hidden_by + : entry.hidden_by ? this.hass.localize( "ui.panel.config.entities.picker.status.hidden" ) diff --git a/src/panels/config/helpers/ha-config-helpers.ts b/src/panels/config/helpers/ha-config-helpers.ts index 1346cfb5df..8507edad42 100644 --- a/src/panels/config/helpers/ha-config-helpers.ts +++ b/src/panels/config/helpers/ha-config-helpers.ts @@ -6,7 +6,10 @@ import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { navigate } from "../../../common/navigate"; -import { LocalizeFunc } from "../../../common/translations/localize"; +import { + LocalizeFunc, + LocalizeKeys, +} from "../../../common/translations/localize"; import { extractSearchParam } from "../../../common/url/search-params"; import { DataTableColumnContainer, @@ -27,6 +30,7 @@ import { } from "../../../data/entity_registry"; import { domainToName } from "../../../data/integration"; import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow"; +import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow"; import { showAlertDialog, showConfirmationDialog, @@ -38,9 +42,19 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { HomeAssistant, Route } from "../../../types"; import { configSections } from "../ha-panel-config"; import "../integrations/ha-integration-overflow-menu"; -import { HelperDomain, isHelperDomain } from "./const"; +import { isHelperDomain } from "./const"; import { showHelperDetailDialog } from "./show-dialog-helper-detail"; -import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow"; + +type HelperItem = { + id: string; + name: string; + icon?: string; + entity_id: string; + editable?: boolean; + type: string; + configEntry?: ConfigEntry; + entity?: HassEntity; +}; // This groups items by a key but only returns last entry per key. const groupByOne = ( @@ -108,16 +122,16 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { private _columns = memoizeOne( (narrow: boolean, localize: LocalizeFunc): DataTableColumnContainer => { - const columns: DataTableColumnContainer = { + const columns: DataTableColumnContainer = { icon: { title: "", label: localize("ui.panel.config.helpers.picker.headers.icon"), type: "icon", - template: (icon, helper: any) => + template: (helper) => helper.entity ? html`` : html``, }, @@ -128,10 +142,10 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { filterable: true, grows: true, direction: "asc", - template: (name, item: any) => html` - ${name} + template: (helper) => html` + ${helper.name} ${narrow - ? html`
${item.entity_id}
` + ? html`
${helper.entity_id}
` : ""} `, }, @@ -149,11 +163,13 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { sortable: true, width: "25%", filterable: true, - template: (type: HelperDomain, row) => - row.configEntry - ? domainToName(localize, type) + template: (helper) => + helper.configEntry + ? domainToName(localize, helper.type) : html` - ${localize(`ui.panel.config.helpers.types.${type}`) || type} + ${localize( + `ui.panel.config.helpers.types.${helper.type}` as LocalizeKeys + ) || helper.type} `, }; columns.editable = { @@ -162,8 +178,8 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { "ui.panel.config.helpers.picker.headers.editable" ), type: "icon", - template: (editable) => html` - ${!editable + template: (helper) => html` + ${!helper.editable ? html`
, configEntries: Record - ) => { + ): HelperItem[] => { const configEntriesCopy = { ...configEntries }; const states = stateItems.map((entityState) => { diff --git a/src/panels/config/integrations/integration-panels/zha/zha-clusters-data-table.ts b/src/panels/config/integrations/integration-panels/zha/zha-clusters-data-table.ts index 9cebc071b2..bf45ceecbf 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-clusters-data-table.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-clusters-data-table.ts @@ -38,7 +38,7 @@ export class ZHAClustersDataTable extends LitElement { }); private _columns = memoizeOne( - (narrow: boolean): DataTableColumnContainer => + (narrow: boolean): DataTableColumnContainer => narrow ? { name: { @@ -57,7 +57,7 @@ export class ZHAClustersDataTable extends LitElement { }, id: { title: "ID", - template: (id: number) => html` ${formatAsPaddedHex(id)} `, + template: (cluster) => html` ${formatAsPaddedHex(cluster.id)} `, sortable: true, width: "25%", }, diff --git a/src/panels/config/integrations/integration-panels/zha/zha-device-endpoint-data-table.ts b/src/panels/config/integrations/integration-panels/zha/zha-device-endpoint-data-table.ts index bebc5826a8..fbadb2ec06 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-device-endpoint-data-table.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-device-endpoint-data-table.ts @@ -67,9 +67,9 @@ export class ZHADeviceEndpointDataTable extends LitElement { filterable: true, direction: "asc", grows: true, - template: (name, device: any) => html` + template: (device) => html` - ${name} + ${device.name} `, }, @@ -86,9 +86,9 @@ export class ZHADeviceEndpointDataTable extends LitElement { filterable: true, direction: "asc", grows: true, - template: (name, device: any) => html` + template: (device) => html` - ${name} + ${device.name} `, }, @@ -102,10 +102,10 @@ export class ZHADeviceEndpointDataTable extends LitElement { sortable: false, filterable: false, width: "50%", - template: (entities) => html` - ${entities.length - ? entities.length > 3 - ? html`${entities + template: (device) => html` + ${device.entities.length + ? device.entities.length > 3 + ? html`${device.entities .slice(0, 2) .map( (entity) => @@ -115,8 +115,8 @@ export class ZHADeviceEndpointDataTable extends LitElement { ${entity.name || entity.original_name}
` )} -
And ${entities.length - 2} more...
` - : entities.map( +
And ${device.entities.length - 2} more...
` + : device.entities.map( (entity) => html`
+ (narrow: boolean): DataTableColumnContainer => narrow ? { name: { @@ -94,16 +94,14 @@ export class ZHAGroupsDashboard extends LitElement { title: this.hass.localize("ui.panel.config.zha.groups.group_id"), type: "numeric", width: "15%", - template: (groupId: number) => html` - ${formatAsPaddedHex(groupId)} - `, + template: (group) => html` ${formatAsPaddedHex(group.group_id)} `, sortable: true, }, members: { title: this.hass.localize("ui.panel.config.zha.groups.members"), type: "numeric", width: "15%", - template: (members: ZHADevice[]) => html` ${members.length} `, + template: (group) => html` ${group.members.length} `, sortable: true, }, } diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-provisioned.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-provisioned.ts index a9a41cdadb..e19478cfed 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-provisioned.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-provisioned.ts @@ -41,15 +41,15 @@ class ZWaveJSProvisioned extends LitElement { } private _columns = memoizeOne( - (narrow: boolean): DataTableColumnContainer => ({ + (narrow: boolean): DataTableColumnContainer => ({ included: { title: this.hass.localize( "ui.panel.config.zwave_js.provisioned.included" ), type: "icon", width: "100px", - template: (_info, provisioningEntry: any) => - provisioningEntry.additional_properties.nodeId + template: (entry) => + entry.additional_properties.nodeId ? html` - securityClasses + template: (entry) => { + const securityClasses = entry.security_classes; + return securityClasses .map((secClass) => this.hass.localize( `ui.panel.config.zwave_js.security_classes.${SecurityClass[secClass]}.title` ) ) - .join(", "), + .join(", "); + }, }, unprovision: { title: this.hass.localize( @@ -96,13 +98,13 @@ class ZWaveJSProvisioned extends LitElement { ), type: "icon-button", width: "100px", - template: (_info, provisioningEntry: any) => html` + template: (entry) => html` `, diff --git a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts index cfbac3ec2c..7ab29c4ae9 100644 --- a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts +++ b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts @@ -68,12 +68,12 @@ export class HaConfigLovelaceDashboards extends LitElement { "ui.panel.config.lovelace.dashboards.picker.headers.icon" ), type: "icon", - template: (icon: DataTableItem["icon"], dashboard) => - icon + template: (dashboard) => + dashboard.icon ? html` { + template: (dashboard) => { const titleTemplate = html` - ${title} + ${dashboard.title} ${dashboard.default ? html` html` + template: (dashboard) => html` ${this.hass.localize( - `ui.panel.config.lovelace.dashboards.conf_mode.${mode}` - ) || mode} + `ui.panel.config.lovelace.dashboards.conf_mode.${dashboard.mode}` + ) || dashboard.mode} `, }; if (dashboards.some((dashboard) => dashboard.filename)) { @@ -155,8 +155,8 @@ export class HaConfigLovelaceDashboards extends LitElement { sortable: true, type: "icon", width: "100px", - template: (requireAdmin: DataTableItem["require_admin"]) => - requireAdmin + template: (dashboard) => + dashboard.require_admin ? html`` : html`—`, }; @@ -166,8 +166,8 @@ export class HaConfigLovelaceDashboards extends LitElement { ), type: "icon", width: "121px", - template: (sidebar: DataTableItem["show_in_sidebar"]) => - sidebar + template: (dashboard) => + dashboard.show_in_sidebar ? html`` : html`—`, }; @@ -180,12 +180,12 @@ export class HaConfigLovelaceDashboards extends LitElement { ), filterable: true, width: "100px", - template: (urlPath) => + template: (dashboard) => narrow ? html` ` : html` - ${this.hass.localize( "ui.panel.config.lovelace.dashboards.picker.open" )} ({ + (_language): DataTableColumnContainer => ({ url: { title: this.hass.localize( "ui.panel.config.lovelace.resources.picker.headers.url" @@ -58,10 +58,10 @@ export class HaConfigLovelaceRescources extends LitElement { sortable: true, filterable: true, width: "30%", - template: (type: LovelaceResource["type"]) => html` + template: (resource) => html` ${this.hass.localize( - `ui.panel.config.lovelace.resources.types.${type}` - ) || type} + `ui.panel.config.lovelace.resources.types.${resource.type}` + ) || resource.type} `, }, }) diff --git a/src/panels/config/scene/ha-scene-dashboard.ts b/src/panels/config/scene/ha-scene-dashboard.ts index 3a7a7790b8..5e8fdc13e4 100644 --- a/src/panels/config/scene/ha-scene-dashboard.ts +++ b/src/panels/config/scene/ha-scene-dashboard.ts @@ -47,6 +47,10 @@ import { formatShortDateTime } from "../../../common/datetime/format_date_time"; import { relativeTime } from "../../../common/datetime/relative_time"; import { isUnavailableState } from "../../../data/entity"; +type SceneItem = SceneEntity & { + name: string; +}; + @customElement("ha-scene-dashboard") class HaSceneDashboard extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -66,7 +70,7 @@ class HaSceneDashboard extends LitElement { @state() private _filterValue?; private _scenes = memoizeOne( - (scenes: SceneEntity[], filteredScenes?: string[] | null) => { + (scenes: SceneEntity[], filteredScenes?: string[] | null): SceneItem[] => { if (filteredScenes === null) { return []; } @@ -83,14 +87,14 @@ class HaSceneDashboard extends LitElement { private _columns = memoizeOne( (_language, narrow): DataTableColumnContainer => { - const columns: DataTableColumnContainer = { + const columns: DataTableColumnContainer = { icon: { title: "", label: this.hass.localize( "ui.panel.config.scene.picker.headers.state" ), type: "icon", - template: (_, scene) => html` + template: (scene) => html` `, }, @@ -112,20 +116,18 @@ class HaSceneDashboard extends LitElement { ), sortable: true, width: "30%", - template: (last_activated) => { - const date = new Date(last_activated); + template: (scene) => { + const lastActivated = scene.state; + if (!lastActivated || isUnavailableState(lastActivated)) { + return this.hass.localize("ui.components.relative_time.never"); + } + const date = new Date(scene.state); const now = new Date(); const dayDifference = differenceInDays(now, date); return html` - ${last_activated && !isUnavailableState(last_activated) - ? dayDifference > 3 - ? formatShortDateTime( - date, - this.hass.locale, - this.hass.config - ) - : relativeTime(date, this.hass.locale) - : this.hass.localize("ui.components.relative_time.never")} + ${dayDifference > 3 + ? formatShortDateTime(date, this.hass.locale, this.hass.config) + : relativeTime(date, this.hass.locale)} `; }, }; @@ -133,7 +135,7 @@ class HaSceneDashboard extends LitElement { columns.only_editable = { title: "", width: "56px", - template: (_info, scene: any) => + template: (scene) => !scene.attributes.id ? html` @@ -152,7 +154,7 @@ class HaSceneDashboard extends LitElement { title: "", width: "72px", type: "overflow-menu", - template: (_: string, scene: any) => html` + template: (scene) => html` { + ( + scripts: ScriptEntity[], + filteredScripts?: string[] | null + ): ScriptItem[] => { if (filteredScripts === null) { return []; } @@ -93,126 +100,136 @@ class HaScriptPicker extends LitElement { } ); - private _columns = memoizeOne((narrow, _locale): DataTableColumnContainer => { - const columns: DataTableColumnContainer = { - icon: { - title: "", - label: this.hass.localize( - "ui.panel.config.script.picker.headers.state" - ), - type: "icon", - template: (_icon, script) => - html``, - }, - name: { - title: this.hass.localize("ui.panel.config.script.picker.headers.name"), - main: true, - sortable: true, - filterable: true, - direction: "asc", - grows: true, - template: narrow - ? (name, script: any) => { - const date = new Date(script.attributes.last_triggered); - const now = new Date(); - const dayDifference = differenceInDays(now, date); - return html` - ${name} -
- ${this.hass.localize("ui.card.automation.last_triggered")}: - ${script.attributes.last_triggered - ? dayDifference > 3 - ? formatShortDateTime( - date, - this.hass.locale, - this.hass.config - ) - : relativeTime(date, this.hass.locale) - : this.hass.localize("ui.components.relative_time.never")} -
- `; - } - : undefined, - }, - }; - if (!narrow) { - columns.last_triggered = { - sortable: true, - width: "40%", - title: this.hass.localize("ui.card.automation.last_triggered"), - template: (last_triggered) => { - const date = new Date(last_triggered); - const now = new Date(); - const dayDifference = differenceInDays(now, date); - return html` - ${last_triggered - ? dayDifference > 3 - ? formatShortDateTime(date, this.hass.locale, this.hass.config) - : relativeTime(date, this.hass.locale) - : this.hass.localize("ui.components.relative_time.never")} - `; + private _columns = memoizeOne( + (narrow, _locale): DataTableColumnContainer => { + const columns: DataTableColumnContainer = { + icon: { + title: "", + label: this.hass.localize( + "ui.panel.config.script.picker.headers.state" + ), + type: "icon", + template: (script) => + html``, + }, + name: { + title: this.hass.localize( + "ui.panel.config.script.picker.headers.name" + ), + main: true, + sortable: true, + filterable: true, + direction: "asc", + grows: true, + template: narrow + ? (script) => { + const date = new Date(script.last_triggered); + const now = new Date(); + const dayDifference = differenceInDays(now, date); + return html` + ${script.name} +
+ ${this.hass.localize("ui.card.automation.last_triggered")}: + ${script.last_triggered + ? dayDifference > 3 + ? formatShortDateTime( + date, + this.hass.locale, + this.hass.config + ) + : relativeTime(date, this.hass.locale) + : this.hass.localize("ui.components.relative_time.never")} +
+ `; + } + : undefined, }, }; + if (!narrow) { + columns.last_triggered = { + sortable: true, + width: "40%", + title: this.hass.localize("ui.card.automation.last_triggered"), + template: (script) => { + const date = new Date(script.last_triggered); + const now = new Date(); + const dayDifference = differenceInDays(now, date); + return html` + ${script.last_triggered + ? dayDifference > 3 + ? formatShortDateTime( + date, + this.hass.locale, + this.hass.config + ) + : relativeTime(date, this.hass.locale) + : this.hass.localize("ui.components.relative_time.never")} + `; + }, + }; + } + + columns.actions = { + title: "", + width: this.narrow ? undefined : "10%", + type: "overflow-menu", + template: (script) => html` + this._showInfo(script), + }, + { + path: mdiPlay, + label: this.hass.localize("ui.panel.config.script.picker.run"), + action: () => this._runScript(script), + }, + { + path: mdiTransitConnection, + label: this.hass.localize( + "ui.panel.config.script.picker.show_trace" + ), + action: () => this._showTrace(script), + }, + { + divider: true, + }, + { + path: mdiContentDuplicate, + label: this.hass.localize( + "ui.panel.config.script.picker.duplicate" + ), + action: () => this._duplicate(script), + }, + { + label: this.hass.localize( + "ui.panel.config.script.picker.delete" + ), + path: mdiDelete, + action: () => this._deleteConfirm(script), + warning: true, + }, + ]} + > + + `, + }; + + return columns; } - - columns.actions = { - title: "", - width: this.narrow ? undefined : "10%", - type: "overflow-menu", - template: (_: string, script: any) => html` - this._showInfo(script), - }, - { - path: mdiPlay, - label: this.hass.localize("ui.panel.config.script.picker.run"), - action: () => this._runScript(script), - }, - { - path: mdiTransitConnection, - label: this.hass.localize( - "ui.panel.config.script.picker.show_trace" - ), - action: () => this._showTrace(script), - }, - { - divider: true, - }, - { - path: mdiContentDuplicate, - label: this.hass.localize( - "ui.panel.config.script.picker.duplicate" - ), - action: () => this._duplicate(script), - }, - { - label: this.hass.localize("ui.panel.config.script.picker.delete"), - path: mdiDelete, - action: () => this._deleteConfirm(script), - warning: true, - }, - ]} - > - - `, - }; - - return columns; - }); + ); protected render(): TemplateResult { return html` diff --git a/src/panels/config/tags/ha-config-tags.ts b/src/panels/config/tags/ha-config-tags.ts index 61a61c8af7..4ac788eba2 100644 --- a/src/panels/config/tags/ha-config-tags.ts +++ b/src/panels/config/tags/ha-config-tags.ts @@ -36,6 +36,7 @@ import { showTagDetailDialog } from "./show-dialog-tag-detail"; import "./tag-image"; export interface TagRowData extends Tag { + display_name: string; last_scanned_datetime: Date | null; } @@ -55,94 +56,90 @@ export class HaConfigTags extends SubscribeMixin(LitElement) { return this.hass.auth.external?.config.canWriteTag; } - private _columns = memoizeOne( - (narrow: boolean, _language): DataTableColumnContainer => { - const columns: DataTableColumnContainer = { - icon: { - title: "", - label: this.hass.localize("ui.panel.config.tag.headers.icon"), - type: "icon", - template: (_icon, tag) => html``, - }, - display_name: { - title: this.hass.localize("ui.panel.config.tag.headers.name"), - main: true, - sortable: true, - filterable: true, - grows: true, - template: (name, tag: any) => - html`${name} - ${narrow - ? html`
- ${tag.last_scanned_datetime - ? html`` - : this.hass.localize("ui.panel.config.tag.never_scanned")} -
` - : ""}`, - }, - }; - if (!narrow) { - columns.last_scanned_datetime = { - title: this.hass.localize("ui.panel.config.tag.headers.last_scanned"), - sortable: true, - direction: "desc", - width: "20%", - template: (last_scanned_datetime) => html` - ${last_scanned_datetime - ? html`` - : this.hass.localize("ui.panel.config.tag.never_scanned")} - `, - }; - } - if (this._canWriteTags) { - columns.write = { - title: "", - label: this.hass.localize("ui.panel.config.tag.headers.write"), - type: "icon-button", - template: (_write, tag: any) => - html` `, - }; - } - columns.automation = { + private _columns = memoizeOne((narrow: boolean, _language) => { + const columns: DataTableColumnContainer = { + icon: { title: "", - type: "icon-button", - template: (_automation, tag: any) => - html` `, + label: this.hass.localize("ui.panel.config.tag.headers.icon"), + type: "icon", + template: (tag) => html``, + }, + display_name: { + title: this.hass.localize("ui.panel.config.tag.headers.name"), + main: true, + sortable: true, + filterable: true, + grows: true, + template: (tag) => + html`${tag.name} + ${narrow + ? html`
+ ${tag.last_scanned_datetime + ? html`` + : this.hass.localize("ui.panel.config.tag.never_scanned")} +
` + : ""}`, + }, + }; + if (!narrow) { + columns.last_scanned_datetime = { + title: this.hass.localize("ui.panel.config.tag.headers.last_scanned"), + sortable: true, + direction: "desc", + width: "20%", + template: (tag) => html` + ${tag.last_scanned_datetime + ? html`` + : this.hass.localize("ui.panel.config.tag.never_scanned")} + `, }; - columns.edit = { - title: "", - type: "icon-button", - template: (_settings, tag: any) => - html` `, - }; - return columns; } - ); + if (this._canWriteTags) { + columns.write = { + title: "", + label: this.hass.localize("ui.panel.config.tag.headers.write"), + type: "icon-button", + template: (tag) => + html` `, + }; + } + columns.automation = { + title: "", + type: "icon-button", + template: (tag) => + html` `, + }; + columns.edit = { + title: "", + type: "icon-button", + template: (tag) => + html` `, + }; + return columns; + }); private _data = memoizeOne((tags: Tag[]): TagRowData[] => tags.map((tag) => ({ diff --git a/src/panels/config/users/ha-config-users.ts b/src/panels/config/users/ha-config-users.ts index a125ef8b81..80d069bdf9 100644 --- a/src/panels/config/users/ha-config-users.ts +++ b/src/panels/config/users/ha-config-users.ts @@ -49,14 +49,14 @@ export class HaConfigUsers extends LitElement { width: "25%", direction: "asc", grows: true, - template: (name, user) => + template: (user) => narrow - ? html` ${name}
+ ? html` ${user.name}
${user.username ? `${user.username} |` : ""} ${localize(`groups.${user.group_ids[0]}`)}
` - : html` ${name || + : html` ${user.name || this.hass!.localize( "ui.panel.config.users.editor.unnamed_user" )}`, @@ -68,7 +68,7 @@ export class HaConfigUsers extends LitElement { width: "20%", direction: "asc", hidden: narrow, - template: (username) => html`${username || "—"}`, + template: (user) => html`${user.name || "—"}`, }, group_ids: { title: localize("ui.panel.config.users.picker.headers.group"), @@ -77,8 +77,8 @@ export class HaConfigUsers extends LitElement { width: "20%", direction: "asc", hidden: narrow, - template: (groupIds: User["group_ids"]) => html` - ${localize(`groups.${groupIds[0]}`)} + template: (user) => html` + ${localize(`groups.${user.group_ids[0]}`)} `, }, is_active: { @@ -90,8 +90,8 @@ export class HaConfigUsers extends LitElement { filterable: true, width: "80px", hidden: narrow, - template: (is_active) => - is_active + template: (user) => + user.is_active ? html`` : "", }, @@ -104,8 +104,8 @@ export class HaConfigUsers extends LitElement { filterable: true, width: "80px", hidden: narrow, - template: (generated) => - generated + template: (user) => + user.system_generated ? html`` : "", }, @@ -118,8 +118,10 @@ export class HaConfigUsers extends LitElement { filterable: true, width: "80px", hidden: narrow, - template: (local) => - local ? html`` : "", + template: (user) => + user.local_only + ? html`` + : "", }, icons: { title: "", @@ -131,7 +133,7 @@ export class HaConfigUsers extends LitElement { filterable: false, width: "104px", hidden: !narrow, - template: (_, user) => { + template: (user) => { const badges = computeUserBadges(this.hass, user, false); return html`${badges.map( ([icon, tooltip]) => diff --git a/src/panels/config/voice-assistants/ha-config-voice-assistants-expose.ts b/src/panels/config/voice-assistants/ha-config-voice-assistants-expose.ts index e6f171f367..abfc59eacf 100644 --- a/src/panels/config/voice-assistants/ha-config-voice-assistants-expose.ts +++ b/src/panels/config/voice-assistants/ha-config-voice-assistants-expose.ts @@ -134,7 +134,7 @@ export class VoiceAssistantsExpose extends LitElement { title: "", type: "icon", hidden: narrow, - template: (_, entry) => html` + template: (entry) => html` html` - ${name}
+ template: (entry) => html` + ${entry.name}
${entry.entity_id}
`, }, @@ -172,13 +172,13 @@ export class VoiceAssistantsExpose extends LitElement { filterable: true, width: "160px", type: "flex", - template: (assistants, entry) => + template: (entry) => html`${availableAssistants.map((key) => { const supported = !supportedEntities?.[key] || supportedEntities[key].includes(entry.entity_id); const manual = entry.manAssistants?.includes(key); - return assistants.includes(key) + return entry.assistants.includes(key) ? html` - aliases.length === 0 + template: (entry) => + entry.aliases.length === 0 ? "-" - : aliases.length === 1 - ? aliases[0] + : entry.aliases.length === 1 + ? entry.aliases[0] : this.hass.localize( "ui.panel.config.voice_assistants.expose.aliases", - { count: aliases.length } + { count: entry.aliases.length } ), }, remove: { diff --git a/src/panels/developer-tools/statistics/developer-tools-statistics.ts b/src/panels/developer-tools/statistics/developer-tools-statistics.ts index 3ed66f9f5b..7eb112a634 100644 --- a/src/panels/developer-tools/statistics/developer-tools-statistics.ts +++ b/src/panels/developer-tools/statistics/developer-tools-statistics.ts @@ -80,7 +80,9 @@ class HaPanelDevStatistics extends SubscribeMixin(LitElement) { ); private _columns = memoizeOne( - (localize: LocalizeFunc): DataTableColumnContainer => ({ + ( + localize: LocalizeFunc + ): DataTableColumnContainer => ({ displayName: { title: localize( "ui.panel.developer-tools.tabs.statistics.data_table.name" @@ -123,8 +125,8 @@ class HaPanelDevStatistics extends SubscribeMixin(LitElement) { filterable: true, direction: "asc", width: "30%", - template: (issues_string) => - html`${issues_string ?? + template: (statistic) => + html`${statistic.issues_string ?? localize("ui.panel.developer-tools.tabs.statistics.no_issue")}`, }, fix: { @@ -132,9 +134,12 @@ class HaPanelDevStatistics extends SubscribeMixin(LitElement) { label: this.hass.localize( "ui.panel.developer-tools.tabs.statistics.fix_issue.fix" ), - template: (_, data: any) => - html`${data.issues - ? html` + template: (statistic) => + html`${statistic.issues + ? html` ${localize( "ui.panel.developer-tools.tabs.statistics.fix_issue.fix" )} @@ -146,7 +151,7 @@ class HaPanelDevStatistics extends SubscribeMixin(LitElement) { title: "", label: localize("ui.panel.developer-tools.tabs.statistics.adjust_sum"), type: "icon-button", - template: (_info, statistic: StatisticsMetaData) => + template: (statistic) => statistic.has_sum ? html` html` + template: (entity) => html` html` + template: (entity: any) => html`
- ${name} + ${entity.name} ${narrow ? html`
${entity.entity_id}
` : ""} @@ -103,10 +103,10 @@ export class HuiEntityPickerTable extends LitElement { sortable: true, width: "15%", hidden: narrow, - template: (lastChanged: string) => html` + template: (entity) => html` `, From 4b5c7021ff06bb175efe94d42bc2b07e04126628 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 20 Sep 2023 12:43:21 +0200 Subject: [PATCH 26/81] Add select option tile feature (#17971) --- src/components/ha-control-select-menu.ts | 54 ++++-- src/panels/lovelace/cards/hui-tile-card.ts | 1 - .../create-tile-feature-element.ts | 4 +- .../hui-tile-card-features-editor.ts | 5 +- .../hui-select-options-tile-feature.ts | 154 ++++++++++++++++++ src/panels/lovelace/tile-features/types.ts | 7 +- src/state/state-display-mixin.ts | 14 +- 7 files changed, 216 insertions(+), 23 deletions(-) create mode 100644 src/panels/lovelace/tile-features/hui-select-options-tile-feature.ts diff --git a/src/components/ha-control-select-menu.ts b/src/components/ha-control-select-menu.ts index 1984f50ffd..04422d890e 100644 --- a/src/components/ha-control-select-menu.ts +++ b/src/components/ha-control-select-menu.ts @@ -1,10 +1,12 @@ import { Ripple } from "@material/mwc-ripple"; import { RippleHandlers } from "@material/mwc-ripple/ripple-handlers"; import { SelectBase } from "@material/mwc-select/mwc-select-base"; +import { mdiMenuDown } from "@mdi/js"; import { css, html, nothing } from "lit"; import { customElement, eventOptions, + property, query, queryAsync, state, @@ -24,6 +26,12 @@ export class HaControlSelectMenu extends SelectBase { @query(".select-anchor") protected anchorElement!: HTMLDivElement | null; + @property({ type: Boolean, attribute: "show-arrow" }) + public showArrow?: boolean; + + @property({ type: Boolean, attribute: "hide-label" }) + public hideLabel?: boolean; + @queryAsync("mwc-ripple") private _ripple!: Promise; @state() private _shouldRenderRipple = false; @@ -36,7 +44,9 @@ export class HaControlSelectMenu extends SelectBase { "select-no-value": !this.selectedText, }; - const labelledby = this.label ? "label" : undefined; + const labelledby = this.label && !this.hideLabel ? "label" : undefined; + const labelAttribute = + this.label && this.hideLabel ? this.label : undefined; return html`
@@ -57,6 +67,7 @@ export class HaControlSelectMenu extends SelectBase { aria-invalid=${!this.isUiValid} aria-haspopup="listbox" aria-labelledby=${ifDefined(labelledby)} + aria-label=${ifDefined(labelAttribute)} aria-required=${this.required} @click=${this.onClick} @focus=${this.onFocus} @@ -72,11 +83,14 @@ export class HaControlSelectMenu extends SelectBase { > ${this.renderIcon()}
-

${this.label}

+ ${this.hideLabel + ? nothing + : html`

${this.label}

`} ${this.selectedText ? html`

${this.selectedText}

` : nothing}
+ ${this.renderArrow()} ${this._shouldRenderRipple && !this.disabled ? html` ` : nothing} @@ -86,13 +100,29 @@ export class HaControlSelectMenu extends SelectBase { `; } + private renderArrow() { + if (!this.showArrow) return nothing; + + return html` +
+ +
+ `; + } + private renderIcon() { const index = this.mdcFoundation?.getSelectedIndex(); const items = this.menuElement?.items ?? []; const item = index != null ? items[index] : undefined; - const icon = - item?.querySelector("[slot='graphic']") ?? - (null as HaSvgIcon | HaIcon | null); + const defaultIcon = this.querySelector("[slot='icon']"); + const icon = (item?.querySelector("[slot='graphic']") ?? null) as + | HaSvgIcon + | HaIcon + | null; + + if (!defaultIcon && !icon) { + return null; + } return html`
@@ -171,14 +201,18 @@ export class HaControlSelectMenu extends SelectBase { --control-select-menu-background-color: var(--disabled-color); --control-select-menu-background-opacity: 0.2; --control-select-menu-border-radius: 14px; + --control-select-menu-height: 48px; + --control-select-menu-padding: 6px 10px; --mdc-icon-size: 20px; + font-size: 14px; + line-height: 1.4; width: auto; color: var(--primary-text-color); -webkit-tap-highlight-color: transparent; } .select-anchor { - height: 48px; - padding: 6px 10px; + height: var(--control-select-menu-height); + padding: var(--control-select-menu-padding); overflow: hidden; position: relative; cursor: pointer; @@ -193,15 +227,12 @@ export class HaControlSelectMenu extends SelectBase { --mdc-ripple-color: var(--control-select-menu-background-color); /* For safari border-radius overflow */ z-index: 0; - font-size: inherit; transition: color 180ms ease-in-out; gap: 10px; width: 100%; user-select: none; - font-size: 14px; font-style: normal; font-weight: 400; - line-height: 20px; letter-spacing: 0.25px; } .content { @@ -223,8 +254,7 @@ export class HaControlSelectMenu extends SelectBase { } .label { - font-size: 12px; - line-height: 16px; + font-size: 0.85em; letter-spacing: 0.4px; } diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index 915bed56d4..89e6141720 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -410,7 +410,6 @@ export class HuiTileCard extends LitElement implements LovelaceCard { ha-card { --mdc-ripple-color: var(--tile-color); height: 100%; - z-index: 0; overflow: hidden; transition: box-shadow 180ms ease-in-out, diff --git a/src/panels/lovelace/create-element/create-tile-feature-element.ts b/src/panels/lovelace/create-element/create-tile-feature-element.ts index 41f6e2b699..e8af650baa 100644 --- a/src/panels/lovelace/create-element/create-tile-feature-element.ts +++ b/src/panels/lovelace/create-element/create-tile-feature-element.ts @@ -1,6 +1,5 @@ import "../tile-features/hui-alarm-modes-tile-feature"; import "../tile-features/hui-climate-hvac-modes-tile-feature"; -import "../tile-features/hui-target-temperature-tile-feature"; import "../tile-features/hui-cover-open-close-tile-feature"; import "../tile-features/hui-cover-position-tile-feature"; import "../tile-features/hui-cover-tilt-position-tile-feature"; @@ -9,6 +8,8 @@ import "../tile-features/hui-fan-speed-tile-feature"; import "../tile-features/hui-lawn-mower-commands-tile-feature"; import "../tile-features/hui-light-brightness-tile-feature"; import "../tile-features/hui-light-color-temp-tile-feature"; +import "../tile-features/hui-select-options-tile-feature"; +import "../tile-features/hui-target-temperature-tile-feature"; import "../tile-features/hui-vacuum-commands-tile-feature"; import "../tile-features/hui-water-heater-operation-modes-tile-feature"; import { LovelaceTileFeatureConfig } from "../tile-features/types"; @@ -28,6 +29,7 @@ const TYPES: Set = new Set([ "lawn-mower-commands", "light-brightness", "light-color-temp", + "select-options", "target-temperature", "vacuum-commands", "water-heater-operation-modes", diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts index 773eb60f13..ea8d25b91a 100644 --- a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts @@ -35,6 +35,7 @@ import { supportsFanSpeedTileFeature } from "../../tile-features/hui-fan-speed-t import { supportsLawnMowerCommandTileFeature } from "../../tile-features/hui-lawn-mower-commands-tile-feature"; import { supportsLightBrightnessTileFeature } from "../../tile-features/hui-light-brightness-tile-feature"; import { supportsLightColorTempTileFeature } from "../../tile-features/hui-light-color-temp-tile-feature"; +import { supportsSelectOptionTileFeature } from "../../tile-features/hui-select-options-tile-feature"; import { supportsTargetTemperatureTileFeature } from "../../tile-features/hui-target-temperature-tile-feature"; import { supportsVacuumCommandTileFeature } from "../../tile-features/hui-vacuum-commands-tile-feature"; import { supportsWaterHeaterOperationModesTileFeature } from "../../tile-features/hui-water-heater-operation-modes-tile-feature"; @@ -46,7 +47,6 @@ type SupportsFeature = (stateObj: HassEntity) => boolean; const FEATURE_TYPES: FeatureType[] = [ "alarm-modes", "climate-hvac-modes", - "target-temperature", "cover-open-close", "cover-position", "cover-tilt-position", @@ -55,6 +55,8 @@ const FEATURE_TYPES: FeatureType[] = [ "lawn-mower-commands", "light-brightness", "light-color-temp", + "select-options", + "target-temperature", "vacuum-commands", "water-heater-operation-modes", ]; @@ -83,6 +85,7 @@ const SUPPORTS_FEATURE_TYPES: Record = "vacuum-commands": supportsVacuumCommandTileFeature, "water-heater-operation-modes": supportsWaterHeaterOperationModesTileFeature, + "select-options": supportsSelectOptionTileFeature, }; const CUSTOM_FEATURE_ENTRIES: Record< diff --git a/src/panels/lovelace/tile-features/hui-select-options-tile-feature.ts b/src/panels/lovelace/tile-features/hui-select-options-tile-feature.ts new file mode 100644 index 0000000000..13c2fb9567 --- /dev/null +++ b/src/panels/lovelace/tile-features/hui-select-options-tile-feature.ts @@ -0,0 +1,154 @@ +import { HassEntity } from "home-assistant-js-websocket"; +import { css, html, LitElement, nothing, PropertyValues } from "lit"; +import { customElement, property, query, state } from "lit/decorators"; +import { stopPropagation } from "../../../common/dom/stop_propagation"; +import { computeDomain } from "../../../common/entity/compute_domain"; +import "../../../components/ha-control-select-menu"; +import type { HaControlSelectMenu } from "../../../components/ha-control-select-menu"; +import { UNAVAILABLE } from "../../../data/entity"; +import { InputSelectEntity } from "../../../data/input_select"; +import { SelectEntity } from "../../../data/select"; +import { HomeAssistant } from "../../../types"; +import { LovelaceTileFeature } from "../types"; +import { SelectOptionsTileFeatureConfig } from "./types"; + +export const supportsSelectOptionTileFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return domain === "select" || domain === "input_select"; +}; + +@customElement("hui-select-options-tile-feature") +class HuiSelectOptionsTileFeature + extends LitElement + implements LovelaceTileFeature +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public stateObj?: + | SelectEntity + | InputSelectEntity; + + @state() private _config?: SelectOptionsTileFeatureConfig; + + @state() _currentOption?: string; + + @query("ha-control-select-menu", true) + private _haSelect!: HaControlSelectMenu; + + static getStubConfig(): SelectOptionsTileFeatureConfig { + return { + type: "select-options", + }; + } + + public setConfig(config: SelectOptionsTileFeatureConfig): void { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + } + + protected willUpdate(changedProp: PropertyValues): void { + super.willUpdate(changedProp); + if (changedProp.has("stateObj") && this.stateObj) { + this._currentOption = this.stateObj.state; + } + } + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + if (changedProps.has("hass")) { + const oldHass = changedProps.get("hass") as HomeAssistant | undefined; + if ( + this.hass && + this.hass.formatEntityAttributeValue !== + oldHass?.formatEntityAttributeValue + ) { + this._haSelect.layoutOptions(); + } + } + } + + private async _valueChanged(ev: CustomEvent) { + const option = (ev.target as any).value as string; + + if (option === this.stateObj!.state) return; + + const oldOption = this.stateObj!.state; + this._currentOption = option; + + try { + await this._setOption(option); + } catch (err) { + this._currentOption = oldOption; + } + } + + private async _setOption(option: string) { + const domain = computeDomain(this.stateObj!.entity_id); + await this.hass!.callService(domain, "select_option", { + entity_id: this.stateObj!.entity_id, + option: option, + }); + } + + protected render() { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsSelectOptionTileFeature(this.stateObj) + ) { + return nothing; + } + + const stateObj = this.stateObj; + + return html` +
+ + ${stateObj.attributes.options!.map( + (option) => html` + + ${this.hass!.formatEntityState(stateObj, option)} + + ` + )} + +
+ `; + } + + static get styles() { + return css` + ha-control-select-menu { + box-sizing: border-box; + --control-select-menu-height: 40px; + --control-select-menu-border-radius: 10px; + line-height: 1.2; + display: block; + width: 100%; + } + .container { + padding: 0 12px 12px 12px; + width: auto; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-select-options-tile-feature": HuiSelectOptionsTileFeature; + } +} diff --git a/src/panels/lovelace/tile-features/types.ts b/src/panels/lovelace/tile-features/types.ts index 6401c28ec5..809cffe1d9 100644 --- a/src/panels/lovelace/tile-features/types.ts +++ b/src/panels/lovelace/tile-features/types.ts @@ -40,6 +40,10 @@ export interface ClimateHvacModesTileFeatureConfig { hvac_modes?: HvacMode[]; } +export interface SelectOptionsTileFeatureConfig { + type: "select-options"; +} + export interface TargetTemperatureTileFeatureConfig { type: "target-temperature"; } @@ -86,7 +90,8 @@ export type LovelaceTileFeatureConfig = | LightColorTempTileFeatureConfig | VacuumCommandsTileFeatureConfig | TargetTemperatureTileFeatureConfig - | WaterHeaterOperationModesTileFeatureConfig; + | WaterHeaterOperationModesTileFeatureConfig + | SelectOptionsTileFeatureConfig; export type LovelaceTileFeatureContext = { entity_id?: string; diff --git a/src/state/state-display-mixin.ts b/src/state/state-display-mixin.ts index 5f160c41e0..4ba3243b51 100644 --- a/src/state/state-display-mixin.ts +++ b/src/state/state-display-mixin.ts @@ -17,15 +17,15 @@ export default >(superClass: T) => { } const oldHass = changedProps.get("hass") as HomeAssistant | undefined; - if (this.hass) { - if ( - this.hass.localize !== oldHass?.localize || + if ( + this.hass && + (!oldHass || + this.hass.localize !== oldHass.localize || this.hass.locale !== oldHass.locale || this.hass.config !== oldHass.config || - this.hass.entities !== oldHass.entities - ) { - this._updateStateDisplay(); - } + this.hass.entities !== oldHass.entities) + ) { + this._updateStateDisplay(); } } From 6179c751824101fa480190f25d8e3e00074c7a13 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 20 Sep 2023 20:39:54 +0200 Subject: [PATCH 27/81] don't round update entity images (#17972) --- src/components/entity/state-badge.ts | 6 +++++- src/panels/config/dashboard/ha-config-updates.ts | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/entity/state-badge.ts b/src/components/entity/state-badge.ts index 17a9bcbbba..a9c1afd35c 100644 --- a/src/components/entity/state-badge.ts +++ b/src/components/entity/state-badge.ts @@ -131,11 +131,15 @@ export class StateBadge extends LitElement { if (this.hass) { imageUrl = this.hass.hassUrl(imageUrl); } - if (computeDomain(stateObj.entity_id) === "camera") { + const domain = computeDomain(stateObj.entity_id); + if (domain === "camera") { imageUrl = cameraUrlWithWidthHeight(imageUrl, 80, 80); } hostStyle.backgroundImage = `url(${imageUrl})`; this._showIcon = false; + if (domain === "update") { + hostStyle.borderRadius = "0"; + } } else if (this.color) { // Externally provided overriding color wins over state color iconStyle.color = this.color; diff --git a/src/panels/config/dashboard/ha-config-updates.ts b/src/panels/config/dashboard/ha-config-updates.ts index b3285e808c..ece376c8e8 100644 --- a/src/panels/config/dashboard/ha-config-updates.ts +++ b/src/panels/config/dashboard/ha-config-updates.ts @@ -86,7 +86,7 @@ class HaConfigUpdates extends SubscribeMixin(LitElement) { return html` Date: Thu, 21 Sep 2023 11:27:41 +0100 Subject: [PATCH 28/81] Add climate preset tile feature (#17946) * Add climate preset tile feature * Minor fixes * Formatting fixes * Update src/panels/lovelace/create-element/create-tile-feature-element.ts * Update src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts --------- Co-authored-by: Paul Bottein --- .../create-tile-feature-element.ts | 2 + .../hui-tile-card-features-editor.ts | 3 + .../hui-climate-presets-tile-feature.ts | 140 ++++++++++++++++++ src/panels/lovelace/tile-features/types.ts | 5 + src/translations/en.json | 6 +- 5 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 src/panels/lovelace/tile-features/hui-climate-presets-tile-feature.ts diff --git a/src/panels/lovelace/create-element/create-tile-feature-element.ts b/src/panels/lovelace/create-element/create-tile-feature-element.ts index e8af650baa..c40aa42103 100644 --- a/src/panels/lovelace/create-element/create-tile-feature-element.ts +++ b/src/panels/lovelace/create-element/create-tile-feature-element.ts @@ -1,5 +1,6 @@ import "../tile-features/hui-alarm-modes-tile-feature"; import "../tile-features/hui-climate-hvac-modes-tile-feature"; +import "../tile-features/hui-climate-presets-tile-feature"; import "../tile-features/hui-cover-open-close-tile-feature"; import "../tile-features/hui-cover-position-tile-feature"; import "../tile-features/hui-cover-tilt-position-tile-feature"; @@ -21,6 +22,7 @@ import { const TYPES: Set = new Set([ "alarm-modes", "climate-hvac-modes", + "climate-presets", "cover-open-close", "cover-position", "cover-tilt-position", diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts index ea8d25b91a..cdb420d230 100644 --- a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts @@ -27,6 +27,7 @@ import { HomeAssistant } from "../../../../types"; import { getTileFeatureElementClass } from "../../create-element/create-tile-feature-element"; import { supportsAlarmModesTileFeature } from "../../tile-features/hui-alarm-modes-tile-feature"; import { supportsClimateHvacModesTileFeature } from "../../tile-features/hui-climate-hvac-modes-tile-feature"; +import { supportsClimatePresetsTileFeature } from "../../tile-features/hui-climate-presets-tile-feature"; import { supportsCoverOpenCloseTileFeature } from "../../tile-features/hui-cover-open-close-tile-feature"; import { supportsCoverPositionTileFeature } from "../../tile-features/hui-cover-position-tile-feature"; import { supportsCoverTiltPositionTileFeature } from "../../tile-features/hui-cover-tilt-position-tile-feature"; @@ -47,6 +48,7 @@ type SupportsFeature = (stateObj: HassEntity) => boolean; const FEATURE_TYPES: FeatureType[] = [ "alarm-modes", "climate-hvac-modes", + "climate-presets", "cover-open-close", "cover-position", "cover-tilt-position", @@ -73,6 +75,7 @@ const SUPPORTS_FEATURE_TYPES: Record = { "alarm-modes": supportsAlarmModesTileFeature, "climate-hvac-modes": supportsClimateHvacModesTileFeature, + "climate-presets": supportsClimatePresetsTileFeature, "cover-open-close": supportsCoverOpenCloseTileFeature, "cover-position": supportsCoverPositionTileFeature, "cover-tilt-position": supportsCoverTiltPositionTileFeature, diff --git a/src/panels/lovelace/tile-features/hui-climate-presets-tile-feature.ts b/src/panels/lovelace/tile-features/hui-climate-presets-tile-feature.ts new file mode 100644 index 0000000000..4dd81fd007 --- /dev/null +++ b/src/panels/lovelace/tile-features/hui-climate-presets-tile-feature.ts @@ -0,0 +1,140 @@ +import { HassEntity } from "home-assistant-js-websocket"; +import { css, html, LitElement, PropertyValues, TemplateResult } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { styleMap } from "lit/directives/style-map"; +import { stateColorCss } from "../../../common/entity/state_color"; +import { ClimateEntity, computePresetModeIcon } from "../../../data/climate"; +import { UNAVAILABLE } from "../../../data/entity"; +import { HomeAssistant } from "../../../types"; +import { LovelaceTileFeature } from "../types"; +import { ClimatePresetsTileFeatureConfig } from "./types"; +import type { ControlSelectOption } from "../../../components/ha-control-select"; +import { computeDomain } from "../../../common/entity/compute_domain"; +import "../../../components/ha-control-button"; +import "../../../components/ha-control-button-group"; +import "../../../components/ha-control-select"; +import "../../../components/ha-control-slider"; + +export const supportsClimatePresetsTileFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return domain === "climate"; +}; + +@customElement("hui-climate-presets-tile-feature") +class HuiClimatePresetsTileFeature + extends LitElement + implements LovelaceTileFeature +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public stateObj?: ClimateEntity; + + @state() private _config?: ClimatePresetsTileFeatureConfig; + + @state() _currentPreset?: string; + + static getStubConfig(): ClimatePresetsTileFeatureConfig { + return { + type: "climate-presets", + }; + } + + public setConfig(config: ClimatePresetsTileFeatureConfig): void { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + } + + protected willUpdate(changedProp: PropertyValues): void { + super.willUpdate(changedProp); + if (changedProp.has("stateObj") && this.stateObj) { + this._currentPreset = this.stateObj.attributes.preset_mode as string; + } + } + + private async _valueChanged(ev: CustomEvent) { + const preset = (ev.detail as any).value as string; + const oldPreset = this.stateObj!.attributes.preset_mode; + + if (preset === oldPreset) return; + this._currentPreset = preset; + + try { + await this._setPreset(preset); + } catch (err) { + this._currentPreset = oldPreset; + } + } + + private async _setPreset(preset: string) { + await this.hass!.callService("climate", "set_preset_mode", { + entity_id: this.stateObj!.entity_id, + preset_mode: preset, + }); + } + + protected render(): TemplateResult | null { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsClimatePresetsTileFeature(this.stateObj) + ) { + return null; + } + + const color = stateColorCss(this.stateObj); + + const presets = (this.stateObj.attributes.preset_modes as string[]) || []; + + const options = presets.map((preset) => ({ + value: preset, + label: this.hass!.formatEntityAttributeName(this.stateObj!, preset), + path: computePresetModeIcon(preset), + })); + + return html` +
+ + +
+ `; + } + + static get styles() { + return css` + ha-control-select { + --control-select-color: var(--tile-color); + --control-select-padding: 0; + --control-select-thickness: 40px; + --control-select-border-radius: 10px; + --control-select-button-border-radius: 10px; + } + ha-control-button-group { + margin: 0 12px 12px 12px; + --control-button-group-spacing: 12px; + } + .container { + padding: 0 12px 12px 12px; + width: auto; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-climate-preset-tile-feature": HuiClimatePresetsTileFeature; + } +} diff --git a/src/panels/lovelace/tile-features/types.ts b/src/panels/lovelace/tile-features/types.ts index 809cffe1d9..9a6670bf52 100644 --- a/src/panels/lovelace/tile-features/types.ts +++ b/src/panels/lovelace/tile-features/types.ts @@ -40,6 +40,10 @@ export interface ClimateHvacModesTileFeatureConfig { hvac_modes?: HvacMode[]; } +export interface ClimatePresetsTileFeatureConfig { + type: "climate-presets"; +} + export interface SelectOptionsTileFeatureConfig { type: "select-options"; } @@ -80,6 +84,7 @@ export interface LawnMowerCommandsTileFeatureConfig { export type LovelaceTileFeatureConfig = | AlarmModesTileFeatureConfig | ClimateHvacModesTileFeatureConfig + | ClimatePresetsTileFeatureConfig | CoverOpenCloseTileFeatureConfig | CoverPositionTileFeatureConfig | CoverTiltPositionTileFeatureConfig diff --git a/src/translations/en.json b/src/translations/en.json index d2fac51d13..a0a3103b98 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -105,7 +105,8 @@ "cooling": "{name} cooling", "high": "high", "low": "low", - "mode": "Mode" + "mode": "Mode", + "preset": "Preset" }, "counter": { "actions": { @@ -5037,6 +5038,9 @@ "label": "Climate HVAC modes", "hvac_modes": "HVAC modes" }, + "climate-presets": { + "label": "Climate Presets" + }, "target-temperature": { "label": "Target temperature" }, From e7960bf8c02553d7dd1a436ef48020a5eab1f26e Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 21 Sep 2023 17:23:31 +0200 Subject: [PATCH 29/81] Make pull request template more in line with core (#17441) --- .github/PULL_REQUEST_TEMPLATE.md | 9 ++------- .prettierignore | 1 + 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 8b35690bb4..6884bb3a80 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,9 +2,7 @@ You are amazing! Thanks for contributing to our project! Please, DO NOT DELETE ANY TEXT from this template! (unless instructed). --> - ## Breaking change - -## Proposed change +## Proposed change -## Type of change +## Type of change AN^dTF8*kC3BoIPHFJ&2cj=6M~S zE%X0zF((4f?j3+DhY+hu&%f`XoJoM~?6t{jzs$?;*5KZ^zn?|r{80e_Fg_T;gQI05 zR~4`U4`l?|I-s4})&(j+1>h&2PkX@Bd>s~6%$w(jlRKbZuW#-VR4$jT5PAt=Mi2%* zX8Z)b3CGRnTcag7wafgbicJ6p{%AFVnPcY7w<|r!J;1a%KAfn)$hPFEU=nb8z6Nhs z`j543w5AypoPcHvVC<>+D@BxR`)+K~nV$uIkRvGTrD0qLOwHF|f%(i2b_8(?7_I`m zaRfie4!E({gzJmukC;$KP~7~^I(B+<2Db-bAMqwZv~>_C{2)7^y(sJ#tm9ys1aQL- zRzSDKpL}n^`B$`Y#PtDP?EQU^BPeO{7`SmUF3$X5uYzo6o=t-7PS}>8`uk1Q0bMvI z2`a#F3UNLSwO#FWUxv%^6Z|G@8wVH(Dxinrb}E4-blw4h@nT<&3SdV{OQ-^9yx5~v06S7z zLKQ&c#U8B!*pbo_ssI`<_GlHrj+B;A1<-i0N2>sKq_l)8fX0hGS_QBpr6p7WG+yk{ zDu5j+Eujja@nVlw0qjU=2~_}%7kjh{U`I+zr~+ub*rQbdJ5pN0Kcz_8Up@golmGw# M07*qoM6N<$f+-af-T(jq literal 0 HcmV?d00001 diff --git a/public/static/icons/tile-win-150x150.png b/public/static/icons/tile-win-150x150.png index e102cd2017e77a244729ff0869bbd40a14fede56..56aadb5630b193f790de34db9ad08524e884bc24 100644 GIT binary patch literal 2277 zcmb7E2|Sc}ADxFta-`S0~aP$WNWRx}*&=P%c761U1+nlsF z<0maQHUS&REwnq`?Ib%y?kL=m{X2JS)fUX+7JEba zP9>X~=NC3%pGaos7C+hSxeby}?pDIh;GbtQ%h`GE)~b*8KMsMz{eywa<^4tZ$MOCF z+raz<=SRRSccY`NUGO8n(S8K5=a&Eelx;74vx?vK|5>s*|80WVd{w`9+9-OC&i`sh zen6w_0FtI|E;_rEN$=NI-bP5au7AjpQEOhlEw=yFYUXamwoDNiD_{HzG2k=VqxFj^ zpDQ*jC5oyr3-)})$b)8x9BR*&c=@xG>X8@e8o2?N$|s-%`MbnHL*T_MACLrCr4xb# zHUjtd%RP<~fEd>qf9RFn+4)XfXT%>y1XTYN^^JU`NuM6cIAA;g%PmL}}BiNUP z4*qZwXddT$gKUT69@2*y*$O0#4BrfcS6P6BEWaG<2GZ3&j|MjV&!8(v@0}K~&rH|k z3k4A9*wEKKO5gN~9=@*mNGOnZ1&9?8w$TKg*k`Li{SE*S?6x#DvJc9fN?UP|I;HTq z>l~IvtCEfIF2LeLj$1xUluB5#D$}N!8WR;2k)jpHOB1ZbZ0+dOmPqLRg?9B23kq4i zHyN60Fts+l?iu*q#nINjG*+MgNNfHO&tJUmJujqf4L{oYa3G{{kU!z=*PHOhdr2oe zgwtv@JTu+Oou7G{WWms7M4K8LgsjfI!FZ>tjFF^}=t0=sbR=2A z&l%njR+PrtRgpCr#AvZnmIj{j;syzgsYHiXP|~#mq4P!hjZAj6-i?Xyer0x(cV(>-xrBCI@ne?*OtI#YQn_a)eluYffmVUjFFrJljM9B z{Mprxo|afh;RV~FI2n4!Dyg!(YftLI5(n#;MV}b`#JbgsObj`AlA)}C768e66Efqb7_dG8{Sx*Q^H{t5E61LK6=9{`$=fZI%Z5c47%xmbR+Qj5{ z>BjpfN>8hL`$!je2LH19-u(`v!=8D|Yz>jooj9MetLJ_Jg*Ghd(ebmHJ|>fKr=%Kd#j5ms_8vm~G65xW*LPrGE*MLF@o zCB(TVtDN3EAWUI%zJ8j{{hep8dqg%=z2ABnIGt%R07S|;WUiK_lbq#Z3beqQm?M2 zb8|7UubMFXA=&-6y}-)h%3DC@3G5Td=Zssupq`2ZLQcz3a2z+M8SHD z7}l}AtTDTnomsoBq-jN{1dr7y5>Mt$7MRm75gQ;Km8!y-q|4VQC)n+8=) z!$_1Y46_0V+;7Rq zpN!)dTxfn(H+w4jwJ~8plAv=w^g{1vhSgxy7B;3mse%k!9rw_pxS7k@b$TP@bY@fyV#8QNvS8n~ z^wpx|g$!R*GFci@ciL+hzj|}U;|g3Ld`-ihmj2GP{KHb$S=jdf%H_SW>i||Ds}Sw} QV!Z delta 2126 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 literal 2647 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 S-lvKH0000{lcJ diff --git a/public/static/icons/tile-win-70x70.png b/public/static/icons/tile-win-70x70.png index 79fbe881e93e0bd2c6f42ee121241a1c5a917850..7373c8cd1ba7201664f341be546d2e9c4e910614 100644 GIT binary patch literal 1191 zcmeAS@N?(olHy`uVBq!ia0vp^ZXnFT3?e@WZ39w_#X;^)j5kl})B`!31s;*b3=Cqb zAk63)r1Al%U|xVvh$~R?)0dyP(8n)7fe20Z<7X^_Xlk%>F^$5ijG!R3%pqtIl7b%? zmi|DJMGqp%r9OTJnZJAK##Ueqb(IA91v4-!$S`siUcVH>!qoob|Hn*5*6!cmvjiKy zaj`ajeUrh|^(ULLBafr<=jVj&VR6U*eafxonI+KlLDTLR+e=yf9{0qY(+;6`s-|uG zQapF>yKv!KC)fkd{MC!>^jcNQa;m?Cjs4n-o2!}kxhk%iA+lfk+>v>+*Uo2KvU~xz zQR@mJkM{<5Zt8@Q$R=xVW>vqX~UZeNZPw#aPDRY%Au)f58vc{wM_pXzB z>>CBHe)+)R@Jp<;E~47M=aO%>WW()}_vI4R@{?cgE|5`(E=)|C(A#bHS&41w^b-f4#IH=5Gf{^vq0;qnVnNcwQZ2T&pP}kLnVS7EJX-np z_MLA07-ux|5_{CgnmoI8hh8mLIq>|{Qaiusf1cdv zc{yI!cJsFBKewJc@Z_18`MCXBOP9RbK4aga)+vrpzw;f?t37z*=`Ve8K|#Tv c_CJ{qENR%Ta$f!nFtsvxy85}Sb4q9e08oecssI20 delta 801 zcmV++1K#|n3AhH3B!3K0OjJcz!}CqR^mowtLB93b1w9M^00QSpL_t(|+U=F=ZY&`T zgB^JPcRo9@iHXplZU0p|*%5?GzL;B!|Mqt*T>qwW8HlWZSh-=`FGvp4_X`;gbH9Ix zuUbc#KmWGYOH4VgL!Ss^jB3d-p*KC=C{KGl<~eOfi|nbYsegJ5Y@DPXoXze18cGU_ zfV7>Q17cCD^AnU9avxpUVvwV|8$ig^vFCrFVBr}y$M~yUq|m%m$EKh|(H#ZJ1V!8o z4de7}_=@QwdiFTMZs5YRG4(6vT^cT8Xw^4I8m<^eoEYnxpW;i5&&$!e&~d>`eubGj zX7}1q{p|~=o_~sm?(WJuHw^LYY~>8t=VCIB;%CfFTg(Y)tsG)WHR-P-8X3&@IFya+ zV+3pZuB1i@>0mWEarzQCx{)Y(GJWtovLr=wA2EttU4T6Qz^R#aCSfM)UG5U-73o6& zPCqkS6O*R@Uh+Jf#zp8f)Q#G{+9nd47(&`L@OF4564TSU?^L6AU|TaSKcsT{op8jb zV@x!RB7bDUNK9yjeH2I9C^5$CuMkKfuVE^!=UYB1fWcl~Gz`Ob8Ck%jT(Sw*+ zKA`y}hD1=M4c-W2)V19WE=4()+Jy*hM8`0lqs{ATkSZcw)*YjCdN;zL?W^4RYSNMA z!oU$GYUy`OdlsrH!A*<|wW?rdI@=X8@P^T5WPcH1`BLDAi905IQ!HV5k%+V#MbW+~ zR8^iBBwsO_tYE7$0m9xeH67c2gc&zPzr{^ViBtV8Mn|muZ7T_Us|T$5hB(r%@NWIO z!ib-N_ABE1c7h@>aK(64c*#4K-7rdt7coAAiym0{?QcQkZMtAA-1isf^d|$p!VJH} fQyLc3`(pn9?b;t+!80Pv00000NkvXXu0mjf%x{34 diff --git a/public/static/images/notification-badge.png b/public/static/images/notification-badge.png index e4350c3fd57d2a654da7b56b0921f450cdedbf39..bf4017bc4717c938ac605b5ab2b5fcb1907f72f7 100644 GIT binary patch delta 1841 zcmV-12hRA^2DJ{58Gi-<0082ccQ^n5010qNS#tmY1?K<&1?K^z=(YI(000?uMObuG zZ)S9NVRB^vcXxL#X>MzCV_|S*E^l&Yo9;Xs000KUNkl5H&dCbh2IrsR1%iX>A%*^k8zh`F7IrBTGqLktg{;2v6 zpzO5x4j?1Lfr-GGfC9DvZvfkU29)hKPN?*>A*?~@cTj!FpKz_LYNS8a3g`bj(`N^{}J)!$KXuTd1QE zM#E7S16&U~wH$4sj$ik`)^5)LB^@$be-W65j>w$c}vw{SD~A%`)O4 zgxSFS+7D_CxDa?a*Ko?oBH#l3PqpTKDS!Uc)yqH&qICuO4449(=PRNTay~E#`V6?+ zUo55NE)WA+fs6dcQc5NOtu2^cZEQxi0WULf;#V6m#$sF7w*VJgtgy)J2Oa{J0K5Br z_Z6@)`u=|4L12)DHYcw!Bgv^%m246#sAk@*-&v`Wh=;6uZ~r-p!^0TT|P5q zH=qaDWl;Vv;AfKn%5Fff?>fqEzz7R55mR=4g81sa1}UW` zDW$$Pi2Z-q>H%K>mmnu5ar_W%`vGv4rS_AMbkA=C9tYk7enf_wvA`ABIe%Hjh6LN5R~{}$ABAv%M8kQk&g+%i4XQ3SJQ;-m4f4`3;x5i=1gy6*o_ov@S_4|Jza5yk8rd${Dw5(3D9i|3xl9dD>Yr=DZ#}aJU zjqJr~AJQ=u$?q@3{cgS%<>!)YIO+y&A^C80IUX;pWx;1w#6ptwgf8G_lJ$gBD8R5& zi|;*UZuA~ECv->eoqrBv@q%vyAiW9wC-y=Uf&m~V>?VF*=q8^vR#aUpG0u}Vpk$iyFf{hUogXyZyp=9xN@s) zXIv5MIvo9em%t?k2Brg^E{-7;ac{5P-LzOiz%9^mmOSIz@AbE4)_0~z{q^%$^5oT$ z_d%)OR)u-bJ@}`#73^DfPVSHdtWqHsPOy2Wcl~N;e6X=m!oXDV7;&wXIudVPof2S5B6Sl_IcD3xzu`nFiz z+Behem+pd3J|cIxoL0Yo8_bt2ec_y3zYF8`0Nq&|u$p-^ovlRu4EXca_uxbs*iFNz_&9`UHTC~R|T~t9NA(t_m@j=tN z|C48an0^a#(r2aDA$R{qz7bQXzr84^X!f>uO0%ziHrx8j zR^k2Pl&8usRO>egdveJ$%sTh!oAHBljZ5s9EYub-Htaj`p0V$tP6fk;eBOGl4d<#) zUkW~<&hR_>2|t74HP!URPi{PA@Tl)QEp}*{>VL@w_SsSeKW5(L>_`Y_TyURp!Gt7@ zhW0w~2B%w$O?B)S;v|3nW#GE;o;~0|ojouVe=~|KsOJYU92rHH*fTuf`8%8O+a-Bs ziOO03q8@P9H0nFNl5@EDB`GMw|EF^6wsc)I$ztaD0e F0sssrvDp9s diff --git a/src/common/const.ts b/src/common/const.ts index 03e2f424d6..81119ca16e 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -31,7 +31,6 @@ import { mdiGauge, mdiGoogleAssistant, mdiGoogleCirclesCommunities, - mdiHomeAssistant, mdiHomeAutomation, mdiImage, mdiImageFilterFrames, @@ -70,6 +69,8 @@ import { mdiWifi, } from "@mdi/js"; +import { mdiHomeAssistant } from "../resources/home-assistant-logo-svg"; + // Constants should be alphabetically sorted by name. // Arrays with values should be alphabetically sorted if order doesn't matter. // Each constant should have a description what it is supposed to be used for. diff --git a/src/components/ha-icon.ts b/src/components/ha-icon.ts index 0ce63ed8ba..0aa89e6435 100644 --- a/src/components/ha-icon.ts +++ b/src/components/ha-icon.ts @@ -124,6 +124,17 @@ export class HaIcon extends LitElement { return; } + if (iconName === "home-assistant") { + const icon = (await import("../resources/home-assistant-logo-svg")) + .mdiHomeAssistant; + + if (this.icon === requestedIcon) { + this._path = icon; + } + cachedIcons[iconName] = icon; + return; + } + let databaseIcon: string | undefined; try { databaseIcon = await getIcon(iconName); diff --git a/src/components/ha-logo-svg.ts b/src/components/ha-logo-svg.ts index 644f35e93e..532c002c67 100644 --- a/src/components/ha-logo-svg.ts +++ b/src/components/ha-logo-svg.ts @@ -1,14 +1,23 @@ -import { css, CSSResultGroup, LitElement, svg, SVGTemplateResult } from "lit"; +import { css, CSSResultGroup, LitElement, html, TemplateResult } from "lit"; import { customElement } from "lit/decorators"; @customElement("ha-logo-svg") export class HaLogoSvg extends LitElement { - protected render(): SVGTemplateResult { - return svg` - - - - `; + protected render(): TemplateResult { + return html` + + + `; } static get styles(): CSSResultGroup { diff --git a/src/data/trigger.ts b/src/data/trigger.ts index 65ce25d726..859595a78a 100644 --- a/src/data/trigger.ts +++ b/src/data/trigger.ts @@ -5,7 +5,6 @@ import { mdiCodeBraces, mdiDevices, mdiGestureDoubleTap, - mdiHomeAssistant, mdiMapMarker, mdiMapMarkerRadius, mdiMessageAlert, @@ -18,6 +17,8 @@ import { mdiWebhook, } from "@mdi/js"; +import { mdiHomeAssistant } from "../resources/home-assistant-logo-svg"; + export const TRIGGER_TYPES = { calendar: mdiCalendar, device: mdiDevices, diff --git a/src/html/authorize.html.template b/src/html/authorize.html.template index 96107af171..740d2b2c79 100644 --- a/src/html/authorize.html.template +++ b/src/html/authorize.html.template @@ -10,31 +10,48 @@ max-width: 360px; margin: 0 auto; } - .header { - font-size: 1.96em; display: flex; - align-items: center; justify-content: center; - font-weight: 300; + height: 73px; } - - .header img { - margin-right: 16px; + .logomark { + fill: #F2F4F9; + } + .wordmark { + fill: #1D2126; } @media (prefers-color-scheme: dark) { html { background-color: #111111; color: #e1e1e1; } + .wordmark { + fill: #F2F4F9; + } }
- - Home Assistant + + + + + + + + + + + + + + + + +

Initializing

diff --git a/src/html/index.html.template b/src/html/index.html.template index a74297f024..faca8c9f06 100644 --- a/src/html/index.html.template +++ b/src/html/index.html.template @@ -3,34 +3,18 @@ Home Assistant <%= renderTemplate("_header.html.template") %> - + - - - - - + + @@ -74,9 +58,19 @@
- - - + + +
diff --git a/src/panels/config/automation/dialog-new-automation.ts b/src/panels/config/automation/dialog-new-automation.ts index 735d6aa9de..b6c0da7f44 100644 --- a/src/panels/config/automation/dialog-new-automation.ts +++ b/src/panels/config/automation/dialog-new-automation.ts @@ -2,12 +2,11 @@ import "@material/mwc-list/mwc-list"; import { mdiAccount, mdiFile, - mdiHomeAssistant, mdiOpenInNew, mdiPencilOutline, mdiWeb, } from "@mdi/js"; -import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; @@ -18,16 +17,17 @@ import "../../../components/ha-icon-next"; import "../../../components/ha-list-item"; import "../../../components/ha-tip"; import { showAutomationEditor } from "../../../data/automation"; -import { showScriptEditor } from "../../../data/script"; import { Blueprint, BlueprintDomain, - Blueprints, BlueprintSourceType, + Blueprints, fetchBlueprints, getBlueprintSourceType, } from "../../../data/blueprint"; +import { showScriptEditor } from "../../../data/script"; import { HassDialog } from "../../../dialogs/make-dialog-manager"; +import { mdiHomeAssistant } from "../../../resources/home-assistant-logo-svg"; import { haStyle, haStyleDialog } from "../../../resources/styles"; import type { HomeAssistant } from "../../../types"; import { documentationUrl } from "../../../util/documentation-url"; diff --git a/src/panels/config/info/ha-config-info.ts b/src/panels/config/info/ha-config-info.ts index b1f4fafb31..2ad19834ae 100644 --- a/src/panels/config/info/ha-config-info.ts +++ b/src/panels/config/info/ha-config-info.ts @@ -4,22 +4,22 @@ import { mdiFileDocument, mdiHandsPray, mdiHelp, - mdiHomeAssistant, mdiNewspaperVariant, mdiTshirtCrew, } from "@mdi/js"; -import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit"; import { property, state } from "lit/decorators"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import "../../../components/ha-card"; import "../../../components/ha-clickable-list-item"; import "../../../components/ha-logo-svg"; import { - fetchHassioHassOsInfo, HassioHassOSInfo, + fetchHassioHassOsInfo, } from "../../../data/hassio/host"; -import { fetchHassioInfo, HassioInfo } from "../../../data/hassio/supervisor"; +import { HassioInfo, fetchHassioInfo } from "../../../data/hassio/supervisor"; import "../../../layouts/hass-subpage"; +import { mdiHomeAssistant } from "../../../resources/home-assistant-logo-svg"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant, Route } from "../../../types"; import { documentationUrl } from "../../../util/documentation-url"; diff --git a/src/resources/home-assistant-logo-svg.ts b/src/resources/home-assistant-logo-svg.ts new file mode 100644 index 0000000000..9eeb6ee856 --- /dev/null +++ b/src/resources/home-assistant-logo-svg.ts @@ -0,0 +1,2 @@ +export const mdiHomeAssistant = + "m12.151 1.5882c-0.32617 1.292e-4 -0.65235 0.12907-0.89964 0.38672l-8.3848 8.7354c-0.061873 0.06443-0.12224 0.13674-0.18069 0.21539-1.018e-4 1.72e-4 -2.376e-4 1.72e-4 -3.31e-4 3.53e-4 -0.058394 0.07855-0.1147 0.16343-0.16842 0.25303-0.25934 0.43253-0.4552 0.97486-0.52317 1.4555-0.00255 0.018-0.00764 0.03695-0.00942 0.05478-0.012052 0.09874-0.018418 0.19443-0.018418 0.28568v7.959c0 0.72958 0.5729 1.3265 1.2731 1.3265h7.8313l-3.4484-3.593c-0.17739 0.06365-0.36671 0.09984-0.56362 0.09984-0.95908 0-1.7399-0.81359-1.7399-1.8129 0-0.99929 0.78085-1.8129 1.7399-1.8129 0.95908 0 1.7399 0.8136 1.7399 1.8129 0 0.20605-0.034883 0.40329-0.095985 0.58812l2.6847 2.7972v-10.248c-0.57715-0.29532-0.97606-0.91251-0.97606-1.6262 0-0.99929 0.78084-1.8129 1.7399-1.8129 0.95908 0 1.7399 0.81359 1.7399 1.8129 0 0.71366-0.39891 1.3309-0.97606 1.6262v7.187l2.6702-2.782c-0.05262-0.17333-0.08156-0.35738-0.08156-0.5484 0-0.9993 0.78084-1.8129 1.7399-1.8129 0.95908 0 1.7399 0.8136 1.7399 1.8129 0 0.99929-0.78084 1.8129-1.7399 1.8129-0.21219 0-0.41417-0.04152-0.60174-0.114l-3.7269 3.8831v2.7299h8.1479c0.61268 0 1.1279-0.45698 1.2471-1.06 0.01698-0.08588 0.02597-0.17475 0.02606-0.26565v-7.959c0-0.09119-0.0059-0.18679-0.01842-0.2855-0.06026-0.49355-0.26358-1.0617-0.53262-1.5105-0.05373-0.08961-0.11007-0.17449-0.16842-0.25304-8.5e-5 -1.81e-4 -2.55e-4 -1.81e-4 -3.4e-4 -3.53e-4 -0.05848-0.07864-0.11884-0.15094-0.18069-0.21539l-8.3848-8.7363c-0.2473-0.25768-0.57348-0.38663-0.89965-0.38675z"; From 2a8d98307e1773c1f8d12fc30763ff52b581575e Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 26 Sep 2023 17:58:02 +0200 Subject: [PATCH 61/81] Fix chart not able to setup because canvas in use (#18018) * Fix chart not able to setup because canvas in use * Update ha-chart-base.ts --- src/components/chart/ha-chart-base.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/chart/ha-chart-base.ts b/src/components/chart/ha-chart-base.ts index 60d0d039f8..1d4604fa3b 100644 --- a/src/components/chart/ha-chart-base.ts +++ b/src/components/chart/ha-chart-base.ts @@ -53,13 +53,14 @@ export class HaChartBase extends LitElement { @state() private _hiddenDatasets: Set = new Set(); public disconnectedCallback() { - this._releaseCanvas(); super.disconnectedCallback(); + this._releaseCanvas(); } public connectedCallback() { super.connectedCallback(); if (this.hasUpdated) { + this._releaseCanvas(); this._setupChart(); } } @@ -110,7 +111,7 @@ export class HaChartBase extends LitElement { return; } if (changedProps.has("plugins") || changedProps.has("chartType")) { - this.chart.destroy(); + this._releaseCanvas(); this._setupChart(); return; } From c567a61dd72efbab2fabda32665ccbc53a000992 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 26 Sep 2023 18:17:45 +0200 Subject: [PATCH 62/81] Add wake word to assist pipeline settings (#18019) * Add wake word to assist pipeline settings * Update assist-pipeline-detail-wakeword.ts * Add icon for wake word domain * format state * implement `wake_word/info` command --- src/common/const.ts | 2 + src/common/entity/compute_state_display.ts | 1 + src/data/assist_pipeline.ts | 4 + src/data/wake_word.ts | 12 ++ .../assist-pipeline-detail-wakeword.ts | 138 ++++++++++++++++++ .../dialog-voice-assistant-pipeline-detail.ts | 9 ++ src/translations/en.json | 8 +- 7 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/data/wake_word.ts create mode 100644 src/panels/config/voice-assistants/assist-pipeline-detail/assist-pipeline-detail-wakeword.ts diff --git a/src/common/const.ts b/src/common/const.ts index 81119ca16e..daead2ada9 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -15,6 +15,7 @@ import { mdiCalendarClock, mdiCarCoolantLevel, mdiCash, + mdiChatSleep, mdiClock, mdiCloudUpload, mdiCog, @@ -124,6 +125,7 @@ export const FIXED_DOMAIN_ICONS = { tts: mdiSpeakerMessage, updater: mdiCloudUpload, vacuum: mdiRobotVacuum, + wake_word: mdiChatSleep, zone: mdiMapMarkerRadius, }; diff --git a/src/common/entity/compute_state_display.ts b/src/common/entity/compute_state_display.ts index 4baad8357d..fdcb95f523 100644 --- a/src/common/entity/compute_state_display.ts +++ b/src/common/entity/compute_state_display.ts @@ -193,6 +193,7 @@ export const computeStateDisplayFromEntityAttributes = ( "scene", "stt", "tts", + "wake_word", ].includes(domain) || (domain === "sensor" && attributes.device_class === "timestamp") ) { diff --git a/src/data/assist_pipeline.ts b/src/data/assist_pipeline.ts index 18cfab3cc5..3ee5a8a27a 100644 --- a/src/data/assist_pipeline.ts +++ b/src/data/assist_pipeline.ts @@ -14,6 +14,8 @@ export interface AssistPipeline { tts_engine: string | null; tts_language: string | null; tts_voice: string | null; + wake_word_entity: string | null; + wake_word_id: string | null; } export interface AssistPipelineMutableParams { @@ -26,6 +28,8 @@ export interface AssistPipelineMutableParams { tts_engine: string | null; tts_language: string | null; tts_voice: string | null; + wake_word_entity: string | null; + wake_word_id: string | null; } export interface assistRunListing { diff --git a/src/data/wake_word.ts b/src/data/wake_word.ts new file mode 100644 index 0000000000..563fde271e --- /dev/null +++ b/src/data/wake_word.ts @@ -0,0 +1,12 @@ +import type { HomeAssistant } from "../types"; + +export interface WakeWord { + id: string; + name: string; +} + +export const fetchWakeWordInfo = (hass: HomeAssistant, entity_id: string) => + hass.callWS<{ wake_words: WakeWord[] }>({ + type: "wake_word/info", + entity_id, + }); diff --git a/src/panels/config/voice-assistants/assist-pipeline-detail/assist-pipeline-detail-wakeword.ts b/src/panels/config/voice-assistants/assist-pipeline-detail/assist-pipeline-detail-wakeword.ts new file mode 100644 index 0000000000..01480f5441 --- /dev/null +++ b/src/panels/config/voice-assistants/assist-pipeline-detail/assist-pipeline-detail-wakeword.ts @@ -0,0 +1,138 @@ +import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { LocalizeKeys } from "../../../../common/translations/localize"; +import "../../../../components/ha-form/ha-form"; +import { AssistPipeline } from "../../../../data/assist_pipeline"; +import { HomeAssistant } from "../../../../types"; +import { fetchWakeWordInfo, WakeWord } from "../../../../data/wake_word"; + +@customElement("assist-pipeline-detail-wakeword") +export class AssistPipelineDetailWakeWord extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property() public data?: Partial; + + @state() private _wakeWords?: WakeWord[]; + + private _schema = memoizeOne( + (wakeWords?: WakeWord[]) => + [ + { + name: "", + type: "grid", + schema: [ + { + name: "wake_word_entity", + selector: { + entity: { + domain: "wake_word", + }, + }, + }, + wakeWords?.length + ? { + name: "wake_word_id", + required: true, + selector: { + select: { + options: wakeWords.map((ww) => ({ + value: ww.id, + label: ww.name, + })), + }, + }, + } + : { name: "", type: "constant" }, + ] as const, + }, + ] as const + ); + + private _computeLabel = (schema): string => + schema.name + ? this.hass.localize( + `ui.panel.config.voice_assistants.assistants.pipeline.detail.form.${schema.name}` as LocalizeKeys + ) + : ""; + + protected willUpdate(changedProps: PropertyValues) { + if ( + changedProps.has("data") && + changedProps.get("data")?.wake_word_entity !== this.data?.wake_word_entity + ) { + this._fetchWakeWords(); + } + } + + protected render() { + return html` +
+
+
+

+ ${this.hass.localize( + `ui.panel.config.voice_assistants.assistants.pipeline.detail.steps.wakeword.title` + )} +

+

+ ${this.hass.localize( + `ui.panel.config.voice_assistants.assistants.pipeline.detail.steps.wakeword.description` + )} +

+
+ +
+
+ `; + } + + private async _fetchWakeWords() { + if (!this.data?.wake_word_entity) { + this._wakeWords = undefined; + return; + } + this._wakeWords = ( + await fetchWakeWordInfo(this.hass, this.data.wake_word_entity) + ).wake_words; + } + + static get styles(): CSSResultGroup { + return css` + .section { + border: 1px solid var(--divider-color); + border-radius: 8px; + } + .content { + padding: 16px; + } + .intro { + margin-bottom: 16px; + } + h3 { + font-weight: normal; + font-size: 22px; + line-height: 28px; + margin-top: 0; + margin-bottom: 4px; + } + p { + color: var(--secondary-text-color); + font-size: var(--mdc-typography-body2-font-size, 0.875rem); + margin-top: 0; + margin-bottom: 0; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "assist-pipeline-detail-wakeword": AssistPipelineDetailWakeWord; + } +} diff --git a/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts b/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts index e8e60b5611..08d1cadfc3 100644 --- a/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts +++ b/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts @@ -25,6 +25,7 @@ import "./assist-pipeline-detail/assist-pipeline-detail-config"; import "./assist-pipeline-detail/assist-pipeline-detail-conversation"; import "./assist-pipeline-detail/assist-pipeline-detail-stt"; import "./assist-pipeline-detail/assist-pipeline-detail-tts"; +import "./assist-pipeline-detail/assist-pipeline-detail-wakeword"; import "./debug/assist-render-pipeline-events"; import { VoiceAssistantPipelineDetailsDialogParams } from "./show-dialog-voice-assistant-pipeline-detail"; @@ -192,6 +193,12 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement { keys="tts_engine,tts_language,tts_voice" @value-changed=${this._valueChanged} > +
${this._params.pipeline?.id ? html` @@ -249,6 +256,8 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement { tts_engine: data.tts_engine ?? null, tts_language: data.tts_language ?? null, tts_voice: data.tts_voice ?? null, + wake_word_entity: data.wake_word_entity ?? null, + wake_word_id: data.wake_word_id ?? null, }; if (this._params!.pipeline?.id) { await this._params!.updatePipeline(values); diff --git a/src/translations/en.json b/src/translations/en.json index a8760f02b3..0b3b957c8d 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2173,7 +2173,9 @@ "stt_language": "[%key:ui::panel::config::voice_assistants::assistants::pipeline::detail::form::language%]", "tts_engine": "Text-to-speech", "tts_language": "[%key:ui::panel::config::voice_assistants::assistants::pipeline::detail::form::language%]", - "tts_voice": "Voice" + "tts_voice": "Voice", + "wake_word_entity": "Wake word engine", + "wake_word_id": "Wake word" }, "steps": { "config": { @@ -2191,6 +2193,10 @@ "tts": { "title": "Text-to-speech", "description": "When you are controlling your assistant with voice, the text-to-speech engine turns the conversation text responses into audio." + }, + "wakeword": { + "title": "Wake word", + "description": "If a device supports wake words, you can activate Assist by saying this word." } }, "no_cloud_message": "You should have an active cloud subscription to use cloud speech services.", From acb32ae5c877ad63cad687a6468466c13c87ee9a Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:59:59 -0700 Subject: [PATCH 63/81] Allow saving the light current color as a favorite (#17992) --- .../lights/dialog-light-color-favorite.ts | 50 +++++++++++++++---- .../ha-more-info-light-favorite-colors.ts | 1 + .../show-dialog-light-color-favorite.ts | 1 + 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/dialogs/more-info/components/lights/dialog-light-color-favorite.ts b/src/dialogs/more-info/components/lights/dialog-light-color-favorite.ts index 8549c90682..935b6377ac 100644 --- a/src/dialogs/more-info/components/lights/dialog-light-color-favorite.ts +++ b/src/dialogs/more-info/components/lights/dialog-light-color-favorite.ts @@ -53,7 +53,8 @@ class DialogLightColorFavorite extends LitElement { ): Promise { this._entry = dialogParams.entry; this._dialogParams = dialogParams; - this._updateModes(dialogParams.defaultMode); + this._updateModes(); + this._loadCurrentColorAndMode(dialogParams.add, dialogParams.defaultMode); await this.updateComplete; } @@ -64,7 +65,7 @@ class DialogLightColorFavorite extends LitElement { fireEvent(this, "dialog-closed", { dialog: this.localName }); } - private _updateModes(defaultMode?: LightPickerMode) { + private _updateModes() { const supportsTemp = lightSupportsColorMode( this.stateObj!, LightColorMode.COLOR_TEMP @@ -81,13 +82,44 @@ class DialogLightColorFavorite extends LitElement { } this._modes = modes; - this._mode = - defaultMode ?? - (this.stateObj!.attributes.color_mode - ? this.stateObj!.attributes.color_mode === LightColorMode.COLOR_TEMP - ? LightColorMode.COLOR_TEMP - : "color" - : this._modes[0]); + } + + private _loadCurrentColorAndMode( + add?: boolean, + defaultMode?: LightPickerMode + ) { + const attributes = this.stateObj!.attributes; + const color_mode = attributes.color_mode; + + let currentColor: LightColor | undefined; + let currentMode: LightPickerMode | undefined; + if (color_mode === LightColorMode.XY) { + currentMode = "color"; + // XY color not supported for favorites. Try to grab the hs or rgb instead. + if (attributes.hs_color) { + currentColor = { hs_color: attributes.hs_color }; + } else if (attributes.rgb_color) { + currentColor = { rgb_color: attributes.rgb_color }; + } + } else if ( + color_mode === LightColorMode.COLOR_TEMP && + attributes.color_temp_kelvin + ) { + currentMode = LightColorMode.COLOR_TEMP; + currentColor = { + color_temp_kelvin: attributes.color_temp_kelvin, + }; + } else if (attributes[color_mode + "_color"]) { + currentMode = "color"; + currentColor = { + [color_mode + "_color"]: attributes[color_mode + "_color"], + } as LightColor; + } + + if (add) { + this._color = currentColor; + } + this._mode = defaultMode ?? currentMode ?? this._modes[0]; } private _colorChanged(ev: CustomEvent) { diff --git a/src/dialogs/more-info/components/lights/ha-more-info-light-favorite-colors.ts b/src/dialogs/more-info/components/lights/ha-more-info-light-favorite-colors.ts index ad00a5b105..3b1ac50329 100644 --- a/src/dialogs/more-info/components/lights/ha-more-info-light-favorite-colors.ts +++ b/src/dialogs/more-info/components/lights/ha-more-info-light-favorite-colors.ts @@ -141,6 +141,7 @@ export class HaMoreInfoLightFavoriteColors extends LitElement { private _add = async () => { const color = await showLightColorFavoriteDialog(this, { entry: this.entry!, + add: true, title: this.hass.localize( "ui.dialogs.more_info_control.light.favorite_color.add_title" ), diff --git a/src/dialogs/more-info/components/lights/show-dialog-light-color-favorite.ts b/src/dialogs/more-info/components/lights/show-dialog-light-color-favorite.ts index d8bc865093..e91e3223ef 100644 --- a/src/dialogs/more-info/components/lights/show-dialog-light-color-favorite.ts +++ b/src/dialogs/more-info/components/lights/show-dialog-light-color-favorite.ts @@ -7,6 +7,7 @@ export interface LightColorFavoriteDialogParams { entry: ExtEntityRegistryEntry; title: string; defaultMode?: LightPickerMode; + add?: boolean; submit?: (color?: LightColor) => void; cancel?: () => void; } From d8c98d8f96fbb88b08b63c9e823504a8b844b71f Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 26 Sep 2023 20:17:03 +0200 Subject: [PATCH 64/81] Move auth components from shadow DOM to light DOM (#18015) --- src/auth/ha-auth-flow.ts | 57 +++---- src/auth/ha-auth-form-string.ts | 69 +++++++++ src/auth/ha-auth-form.ts | 30 ++++ src/auth/ha-auth-textfield.ts | 186 +++++++++++++++++++++++ src/auth/ha-authorize.ts | 76 +++++---- src/auth/ha-password-manager-polyfill.ts | 172 --------------------- src/components/ha-form/ha-form-string.ts | 52 ++++--- src/components/ha-form/ha-form.ts | 17 ++- src/html/authorize.html.template | 2 +- 9 files changed, 392 insertions(+), 269 deletions(-) create mode 100644 src/auth/ha-auth-form-string.ts create mode 100644 src/auth/ha-auth-form.ts create mode 100644 src/auth/ha-auth-textfield.ts delete mode 100644 src/auth/ha-password-manager-polyfill.ts diff --git a/src/auth/ha-auth-flow.ts b/src/auth/ha-auth-flow.ts index f23733bb79..b64cd092dd 100644 --- a/src/auth/ha-auth-flow.ts +++ b/src/auth/ha-auth-flow.ts @@ -1,19 +1,12 @@ +/* eslint-disable lit/prefer-static-styles */ import "@material/mwc-button"; import { genClientId } from "home-assistant-js-websocket"; -import { - css, - CSSResultGroup, - html, - LitElement, - nothing, - PropertyValues, -} from "lit"; +import { html, LitElement, nothing, PropertyValues } from "lit"; import { customElement, property, state } from "lit/decorators"; import { LocalizeFunc } from "../common/translations/localize"; import "../components/ha-alert"; import "../components/ha-checkbox"; import { computeInitialHaFormData } from "../components/ha-form/compute-initial-ha-form-data"; -import "../components/ha-form/ha-form"; import "../components/ha-formfield"; import "../components/ha-markdown"; import { AuthProvider, autocompleteLoginFields } from "../data/auth"; @@ -21,7 +14,7 @@ import { DataEntryFlowStep, DataEntryFlowStepForm, } from "../data/data_entry_flow"; -import "./ha-password-manager-polyfill"; +import "./ha-auth-form"; type State = "loading" | "error" | "step"; @@ -49,6 +42,10 @@ export class HaAuthFlow extends LitElement { @state() private _storeToken = false; + createRenderRoot() { + return this; + } + willUpdate(changedProps: PropertyValues) { super.willUpdate(changedProps); @@ -79,13 +76,17 @@ export class HaAuthFlow extends LitElement { protected render() { return html` +
${this._renderForm()}
- `; } @@ -128,12 +129,6 @@ export class HaAuthFlow extends LitElement { (form as any).focus(); } }, 100); - - setTimeout(() => { - this.renderRoot.querySelector( - "ha-password-manager-polyfill" - )!.boundingRect = this.getBoundingClientRect(); - }, 500); } private _renderForm() { @@ -205,7 +200,7 @@ export class HaAuthFlow extends LitElement { > ` : nothing} - + > ${this.clientId === genClientId() && !["select_mfa_module", "mfa"].includes(step.step_id) ? html` @@ -395,20 +390,6 @@ export class HaAuthFlow extends LitElement { this._submitting = false; } } - - static get styles(): CSSResultGroup { - return css` - .action { - margin: 24px 0 8px; - text-align: center; - } - /* Align with the rest of the form. */ - .store-token { - margin-top: 10px; - margin-left: -16px; - } - `; - } } declare global { diff --git a/src/auth/ha-auth-form-string.ts b/src/auth/ha-auth-form-string.ts new file mode 100644 index 0000000000..89fa713e42 --- /dev/null +++ b/src/auth/ha-auth-form-string.ts @@ -0,0 +1,69 @@ +/* eslint-disable lit/prefer-static-styles */ +import { TemplateResult, html } from "lit"; +import { customElement } from "lit/decorators"; +import { HaFormString } from "../components/ha-form/ha-form-string"; +import "../components/ha-icon-button"; +import "./ha-auth-textfield"; + +@customElement("ha-auth-form-string") +export class HaAuthFormString extends HaFormString { + protected createRenderRoot() { + // add parent style to light dom + const style = document.createElement("style"); + style.innerHTML = HaFormString.elementStyles as unknown as string; + this.append(style); + return this; + } + + protected render(): TemplateResult { + return html` + +
` + : this.schema.description?.suffix + } + .validationMessage=${this.schema.required ? "Required" : undefined} + @input=${this._valueChanged} + @change=${this._valueChanged} + > + ${this.renderIcon()} + + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-auth-form-string": HaAuthFormString; + } +} diff --git a/src/auth/ha-auth-form.ts b/src/auth/ha-auth-form.ts new file mode 100644 index 0000000000..1a098caf0d --- /dev/null +++ b/src/auth/ha-auth-form.ts @@ -0,0 +1,30 @@ +/* eslint-disable lit/prefer-static-styles */ +import { customElement } from "lit/decorators"; +import { HaForm } from "../components/ha-form/ha-form"; +import "./ha-auth-form-string"; + +@customElement("ha-auth-form") +export class HaAuthForm extends HaForm { + protected fieldElementName(type: string): string { + if (type === "string") { + return `ha-auth-form-${type}`; + } + return super.fieldElementName(type); + } + + protected createRenderRoot() { + // add parent style to light dom + const style = document.createElement("style"); + style.innerHTML = HaForm.elementStyles as unknown as string; + this.append(style); + // attach it as soon as possible to make sure we fetch all events. + this.addValueChangedListener(this); + return this; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-auth-form": HaAuthForm; + } +} diff --git a/src/auth/ha-auth-textfield.ts b/src/auth/ha-auth-textfield.ts new file mode 100644 index 0000000000..7c4bb2c6cc --- /dev/null +++ b/src/auth/ha-auth-textfield.ts @@ -0,0 +1,186 @@ +/* eslint-disable lit/prefer-static-styles */ +import { html } from "lit"; +import { customElement } from "lit/decorators"; +import { HaTextField } from "../components/ha-textfield"; +import "@material/mwc-textfield/mwc-textfield.css"; + +@customElement("ha-auth-textfield") +export class HaAuthTextField extends HaTextField { + public render() { + return html` + + ${super.render()} + `; + } + + protected createRenderRoot() { + // add parent style to light dom + const style = document.createElement("style"); + style.innerHTML = HaTextField.elementStyles as unknown as string; + this.append(style); + return this; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-auth-textfield": HaAuthTextField; + } +} diff --git a/src/auth/ha-authorize.ts b/src/auth/ha-authorize.ts index 9778edfc0a..54d59bd8e9 100644 --- a/src/auth/ha-authorize.ts +++ b/src/auth/ha-authorize.ts @@ -1,13 +1,7 @@ -import punycode from "punycode"; -import { - css, - CSSResultGroup, - html, - LitElement, - nothing, - PropertyValues, -} from "lit"; +/* eslint-disable lit/prefer-static-styles */ +import { html, LitElement, nothing, PropertyValues } from "lit"; import { customElement, property, state } from "lit/decorators"; +import punycode from "punycode"; import { applyThemesOnElement } from "../common/dom/apply_themes_on_element"; import { extractSearchParamsObject } from "../common/url/search-params"; import "../components/ha-alert"; @@ -61,13 +55,27 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) { protected render() { if (this._error) { - return html`${this._error} ${this.redirectUri}`; + return html` + + ${this._error} ${this.redirectUri} + `; } if (!this._authProviders) { return html` +

${this.localize("ui.panel.page-authorize.initializing")}

`; } @@ -79,6 +87,25 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) { const app = this.clientId && this.clientId in appNames; return html` + + ${!this._ownInstance ? html` ${app @@ -123,6 +150,10 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) { `; } + createRenderRoot() { + return this; + } + protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); @@ -217,25 +248,4 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) { private async _handleAuthProviderPick(ev) { this._authProvider = ev.detail; } - - static get styles(): CSSResultGroup { - return css` - ha-pick-auth-provider { - display: block; - margin-top: 48px; - } - ha-auth-flow { - display: block; - margin-top: 24px; - } - ha-alert { - display: block; - margin: 16px 0; - } - p { - font-size: 14px; - line-height: 20px; - } - `; - } } diff --git a/src/auth/ha-password-manager-polyfill.ts b/src/auth/ha-password-manager-polyfill.ts deleted file mode 100644 index 7c66d11fe3..0000000000 --- a/src/auth/ha-password-manager-polyfill.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { css, html, LitElement, nothing } from "lit"; -import { customElement, property } from "lit/decorators"; -import { styleMap } from "lit/directives/style-map"; -import { fireEvent } from "../common/dom/fire_event"; -import type { HaFormSchema } from "../components/ha-form/types"; -import { autocompleteLoginFields } from "../data/auth"; -import type { DataEntryFlowStep } from "../data/data_entry_flow"; - -declare global { - interface HTMLElementTagNameMap { - "ha-password-manager-polyfill": HaPasswordManagerPolyfill; - } - interface HASSDomEvents { - "form-submitted": undefined; - } -} - -const ENABLED_HANDLERS = [ - "homeassistant", - "legacy_api_password", - "command_line", -]; - -@customElement("ha-password-manager-polyfill") -export class HaPasswordManagerPolyfill extends LitElement { - @property({ attribute: false }) public step?: DataEntryFlowStep; - - @property({ attribute: false }) public stepData: any; - - @property({ attribute: false }) public boundingRect?: DOMRect; - - private _styleElement?: HTMLStyleElement; - - public connectedCallback() { - super.connectedCallback(); - this._styleElement = document.createElement("style"); - this._styleElement.textContent = css` - /* Polyfill form is sized and vertically aligned with true form, then positioned offscreen - rather than hiding so it does not create a new stacking context */ - .password-manager-polyfill { - position: absolute; - box-sizing: border-box; - } - /* Excluding our wrapper, move any children back on screen, including anything injected that might not already be positioned */ - .password-manager-polyfill > *:not(.wrapper), - .password-manager-polyfill > .wrapper > * { - position: relative; - left: 10000px; - } - /* Size and hide our polyfill fields */ - .password-manager-polyfill .underneath { - display: block; - box-sizing: border-box; - width: 100%; - padding: 0 16px; - border: 0; - z-index: -1; - height: 21px; - /* Transparency is only needed to hide during paint or in case of misalignment, - but LastPass will fail if it's 0, so we use 1% */ - opacity: 0.01; - } - .password-manager-polyfill input.underneath { - height: 28px; - margin-bottom: 30.5px; - } - /* Button position is not important, but size should not be zero */ - .password-manager-polyfill > input.underneath[type="submit"] { - width: 1px; - height: 1px; - margin: 0 auto; - overflow: hidden; - } - /* Ensure injected elements will be on top */ - .password-manager-polyfill > *:not(.underneath, .wrapper), - .password-manager-polyfill > .wrapper > *:not(.underneath) { - isolation: isolate; - z-index: auto; - } - `.toString(); - document.head.append(this._styleElement); - } - - public disconnectedCallback() { - super.disconnectedCallback(); - this._styleElement?.remove(); - delete this._styleElement; - } - - protected createRenderRoot() { - // Add under document body so the element isn't placed inside any shadow roots - return document.body; - } - - protected render() { - if ( - this.step && - this.step.type === "form" && - this.step.step_id === "init" && - ENABLED_HANDLERS.includes(this.step.handler[0]) - ) { - return html` -
- ${autocompleteLoginFields(this.step.data_schema).map((input) => - this.render_input(input) - )} - -
- `; - } - return nothing; - } - - private render_input(schema: HaFormSchema) { - const inputType = schema.name.includes("password") ? "password" : "text"; - if (schema.type !== "string") { - return ""; - } - return html` - - - - - `; - } - - private _handleSubmit(ev: SubmitEvent) { - ev.preventDefault(); - fireEvent(this, "form-submitted"); - } - - private _valueChanged(ev: Event) { - const target = ev.target as HTMLInputElement; - this.stepData = { ...this.stepData, [target.id]: target.value }; - fireEvent(this, "value-changed", { - value: this.stepData, - }); - } -} diff --git a/src/components/ha-form/ha-form-string.ts b/src/components/ha-form/ha-form-string.ts index 5cc63ce1d4..3118fcf948 100644 --- a/src/components/ha-form/ha-form-string.ts +++ b/src/components/ha-form/ha-form-string.ts @@ -1,11 +1,13 @@ +/* eslint-disable lit/prefer-static-styles */ import { mdiEye, mdiEyeOff } from "@mdi/js"; import { - css, CSSResultGroup, - html, LitElement, PropertyValues, TemplateResult, + css, + html, + nothing, } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { fireEvent } from "../../common/dom/fire_event"; @@ -32,7 +34,7 @@ export class HaFormString extends LitElement implements HaFormElement { @property({ type: Boolean }) public disabled = false; - @state() private _unmaskedPassword = false; + @state() protected unmaskedPassword = false; @query("ha-textfield") private _input?: HaTextField; @@ -43,14 +45,11 @@ export class HaFormString extends LitElement implements HaFormElement { } protected render(): TemplateResult { - const isPassword = MASKED_FIELDS.some((field) => - this.schema.name.includes(field) - ); return html`
` : this.schema.description?.suffix} @@ -70,14 +69,19 @@ export class HaFormString extends LitElement implements HaFormElement { @input=${this._valueChanged} @change=${this._valueChanged} > - ${isPassword - ? html`` - : ""} + ${this.renderIcon()} + `; + } + + protected renderIcon() { + if (!this.isPassword) return nothing; + return html` + `; } @@ -87,11 +91,11 @@ export class HaFormString extends LitElement implements HaFormElement { } } - private _toggleUnmaskedPassword(): void { - this._unmaskedPassword = !this._unmaskedPassword; + protected toggleUnmaskedPassword(): void { + this.unmaskedPassword = !this.unmaskedPassword; } - private _valueChanged(ev: Event): void { + protected _valueChanged(ev: Event): void { let value: string | undefined = (ev.target as HaTextField).value; if (this.data === value) { return; @@ -104,7 +108,7 @@ export class HaFormString extends LitElement implements HaFormElement { }); } - private get _stringType(): string { + protected get stringType(): string { if (this.schema.format) { if (["email", "url"].includes(this.schema.format)) { return this.schema.format; @@ -116,6 +120,10 @@ export class HaFormString extends LitElement implements HaFormElement { return "text"; } + protected get isPassword(): boolean { + return MASKED_FIELDS.some((field) => this.schema.name.includes(field)); + } + static get styles(): CSSResultGroup { return css` :host { diff --git a/src/components/ha-form/ha-form.ts b/src/components/ha-form/ha-form.ts index 98c177f482..b02f7f5b0d 100644 --- a/src/components/ha-form/ha-form.ts +++ b/src/components/ha-form/ha-form.ts @@ -1,3 +1,4 @@ +/* eslint-disable lit/prefer-static-styles */ import { css, CSSResultGroup, @@ -135,7 +136,7 @@ export class HaForm extends LitElement implements HaFormElement { .required=${item.required || false} .context=${this._generateContext(item)} >` - : dynamicElement(`ha-form-${item.type}`, { + : dynamicElement(this.fieldElementName(item.type), { schema: item, data: getValue(this.data, item), label: this._computeLabel(item, this.data), @@ -152,6 +153,10 @@ export class HaForm extends LitElement implements HaFormElement { `; } + protected fieldElementName(type: string): string { + return `ha-form-${type}`; + } + private _generateContext( schema: HaFormSchema ): Record | undefined { @@ -169,10 +174,17 @@ export class HaForm extends LitElement implements HaFormElement { protected createRenderRoot() { const root = super.createRenderRoot(); // attach it as soon as possible to make sure we fetch all events. - root.addEventListener("value-changed", (ev) => { + this.addValueChangedListener(root); + return root; + } + + protected addValueChangedListener(element: Element | ShadowRoot) { + element.addEventListener("value-changed", (ev) => { ev.stopPropagation(); const schema = (ev.target as HaFormElement).schema as HaFormSchema; + if (ev.target === this) return; + const newValue = !schema.name ? ev.detail.value : { [schema.name]: ev.detail.value }; @@ -181,7 +193,6 @@ export class HaForm extends LitElement implements HaFormElement { value: { ...this.data, ...newValue }, }); }); - return root; } private _computeLabel(schema: HaFormSchema, data: HaFormDataContainer) { diff --git a/src/html/authorize.html.template b/src/html/authorize.html.template index 740d2b2c79..b5fd0259f4 100644 --- a/src/html/authorize.html.template +++ b/src/html/authorize.html.template @@ -53,7 +53,7 @@
-

Initializing

+
<%= renderTemplate("_js_base.html.template") %> <%= renderTemplate("_preload_roboto.html.template") %> From d794ec34080843583afc6a97c646bb1ea7e32c91 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 26 Sep 2023 21:27:27 +0200 Subject: [PATCH 65/81] Update assist-pipeline-detail-wakeword.ts --- .../assist-pipeline-detail/assist-pipeline-detail-wakeword.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/panels/config/voice-assistants/assist-pipeline-detail/assist-pipeline-detail-wakeword.ts b/src/panels/config/voice-assistants/assist-pipeline-detail/assist-pipeline-detail-wakeword.ts index 01480f5441..dfa6f0fd39 100644 --- a/src/panels/config/voice-assistants/assist-pipeline-detail/assist-pipeline-detail-wakeword.ts +++ b/src/panels/config/voice-assistants/assist-pipeline-detail/assist-pipeline-detail-wakeword.ts @@ -36,6 +36,8 @@ export class AssistPipelineDetailWakeWord extends LitElement { required: true, selector: { select: { + mode: "dropdown", + sort: true, options: wakeWords.map((ww) => ({ value: ww.id, label: ww.name, From c69fb77b62f3650517c99cb5a341b15b85577254 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Tue, 26 Sep 2023 12:54:40 -0700 Subject: [PATCH 66/81] Fix choose description when a non-list form of conditions is used (#18023) --- .../action/types/ha-automation-action-choose.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/panels/config/automation/action/types/ha-automation-action-choose.ts b/src/panels/config/automation/action/types/ha-automation-action-choose.ts index a34bb036e2..f77328bf4b 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-choose.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-choose.ts @@ -82,26 +82,23 @@ export class HaChooseAction extends LitElement implements ActionElement { if (this.isExpanded(idx)) { return ""; } - if (!option.conditions || option.conditions.length === 0) { + const conditions = ensureArray(option.conditions); + if (!conditions || conditions.length === 0) { return this.hass.localize( "ui.panel.config.automation.editor.actions.type.choose.no_conditions" ); } let str = ""; - if (typeof option.conditions[0] === "string") { - str += option.conditions[0]; + if (typeof conditions[0] === "string") { + str += conditions[0]; } else { - str += describeCondition( - option.conditions[0], - this.hass, - this._entityReg - ); + str += describeCondition(conditions[0], this.hass, this._entityReg); } - if (option.conditions.length > 1) { + if (conditions.length > 1) { str += this.hass.localize( "ui.panel.config.automation.editor.actions.type.choose.option_description_additional", "numberOfAdditionalConditions", - option.conditions.length - 1 + conditions.length - 1 ); } return str; From 49a66961e2df6be6f162b96adb06f9fc553b6bce Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:00:39 -0700 Subject: [PATCH 67/81] Fix adjust statistic dialog after a period of sensor unavailability (#17934) * Fix adjust statistic dialog after a period of sensor unavailability * Remove fetching an unnecessary datapoint --- .../dialog-statistics-adjust-sum.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/panels/developer-tools/statistics/dialog-statistics-adjust-sum.ts b/src/panels/developer-tools/statistics/dialog-statistics-adjust-sum.ts index 8dd31d35c0..b34769e44b 100644 --- a/src/panels/developer-tools/statistics/dialog-statistics-adjust-sum.ts +++ b/src/panels/developer-tools/statistics/dialog-statistics-adjust-sum.ts @@ -132,20 +132,20 @@ export class DialogStatisticsFixUnsupportedUnitMetadata extends LitElement { if (!this._stats5min || !this._statsHour) { stats = html``; - } else if (this._statsHour.length < 2 && this._stats5min.length < 2) { + } else if (this._statsHour.length < 1 && this._stats5min.length < 1) { stats = html`

No statistics found for this period.

`; } else { const data = - this._stats5min.length >= 2 ? this._stats5min : this._statsHour; + this._stats5min.length >= 1 ? this._stats5min : this._statsHour; const unit = getDisplayUnit( this.hass, this._params!.statistic.statistic_id, this._params!.statistic ); const rows: TemplateResult[] = []; - for (let i = 1; i < data.length; i++) { + for (let i = 0; i < data.length; i++) { const stat = data[i]; - const growth = Math.round((stat.sum! - data[i - 1].sum!) * 100) / 100; + const growth = Math.round(stat.change! * 100) / 100; rows.push(html` { From b899e39a9e062943c87587da746345832ee43715 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 26 Sep 2023 22:37:27 +0200 Subject: [PATCH 68/81] Fix markdown card template handling (#17851) --- .../template/developer-tools-template.ts | 4 +- .../lovelace/cards/hui-markdown-card.ts | 57 ++++++++++++++----- .../editor/card-editor/hui-card-preview.ts | 2 + 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/panels/developer-tools/template/developer-tools-template.ts b/src/panels/developer-tools/template/developer-tools-template.ts index 6e6f842c76..e3596b6a3f 100644 --- a/src/panels/developer-tools/template/developer-tools-template.ts +++ b/src/panels/developer-tools/template/developer-tools-template.ts @@ -340,6 +340,8 @@ class HaPanelDevTemplate extends LitElement { private async _subscribeTemplate() { this._rendering = true; await this._unsubscribeTemplate(); + this._error = undefined; + this._errorLevel = undefined; this._templateResult = undefined; try { this._unsubRenderTemplate = subscribeRenderTemplate( @@ -353,8 +355,6 @@ class HaPanelDevTemplate extends LitElement { } } else { this._templateResult = result; - this._error = undefined; - this._errorLevel = undefined; } }, { diff --git a/src/panels/lovelace/cards/hui-markdown-card.ts b/src/panels/lovelace/cards/hui-markdown-card.ts index d527869646..858089ed5f 100644 --- a/src/panels/lovelace/cards/hui-markdown-card.ts +++ b/src/panels/lovelace/cards/hui-markdown-card.ts @@ -12,6 +12,7 @@ import { classMap } from "lit/directives/class-map"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import "../../../components/ha-card"; import "../../../components/ha-markdown"; +import "../../../components/ha-alert"; import { RenderTemplateResult, subscribeRenderTemplate, @@ -37,11 +38,17 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { @property({ attribute: false }) public hass?: HomeAssistant; + @property({ type: Boolean }) public editMode?: boolean; + @state() private _config?: MarkdownCardConfig; + @state() private _error?: string; + + @state() private _errorLevel?: "ERROR" | "WARNING"; + @state() private _templateResult?: RenderTemplateResult; - @state() private _unsubRenderTemplate?: Promise; + private _unsubRenderTemplate?: Promise; public getCardSize(): number { return this._config === undefined @@ -79,6 +86,12 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { } return html` + ${this._error + ? html`${this._error}` + : nothing} { - this._templateResult = result as RenderTemplateResult; + if ("error" in result) { + // We show the latest error, or a warning if there are no errors + if (result.level === "ERROR" || this._errorLevel !== "ERROR") { + this._error = result.error; + this._errorLevel = result.level; + } + return; + } + this._templateResult = result; }, { template: this._config.content, @@ -137,10 +163,15 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { user: this.hass.user!.name, }, strict: true, + report_errors: this.editMode, } ); await this._unsubRenderTemplate; - } catch (_err) { + } catch (e: any) { + if (this.editMode) { + this._error = e.message; + this._errorLevel = undefined; + } this._templateResult = { result: this._config!.content, listeners: { all: false, domains: [], entities: [], time: false }, @@ -154,17 +185,10 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { return; } - try { - const unsub = await this._unsubRenderTemplate; - unsub(); - this._unsubRenderTemplate = undefined; - } catch (err: any) { - if (err.code === "not_found") { - // If we get here, the connection was probably already closed. Ignore. - } else { - throw err; - } - } + this._unsubRenderTemplate.then((unsub) => unsub()).catch(() => {}); + this._unsubRenderTemplate = undefined; + this._error = undefined; + this._errorLevel = undefined; } static get styles(): CSSResultGroup { @@ -172,6 +196,9 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { ha-card { height: 100%; } + ha-alert { + margin-bottom: 8px; + } ha-markdown { padding: 0 16px 16px; word-wrap: break-word; diff --git a/src/panels/lovelace/editor/card-editor/hui-card-preview.ts b/src/panels/lovelace/editor/card-editor/hui-card-preview.ts index 8bcfb57cf3..ad7788312a 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-preview.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-preview.ts @@ -87,6 +87,8 @@ export class HuiCardPreview extends ReactiveElement { this._cleanup(); this._element = createCardElement(configValue); + this._element.editMode = true; + if (this.hass) { this._element!.hass = this.hass; } From cbd424ff5a2f2a81f60cc3d92b2d90bd09087738 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 26 Sep 2023 22:39:25 +0200 Subject: [PATCH 69/81] Fix aria label auth page (#18032) --- build-scripts/webpack.cjs | 1 + package.json | 1 + src/auth/ha-auth-flow.ts | 4 +- src/auth/ha-auth-form-string.ts | 18 +++++--- src/auth/ha-auth-form.ts | 22 ++++++++-- src/auth/ha-auth-textfield.ts | 74 +++++++++++++++++++++++++++++++-- yarn.lock | 3 +- 7 files changed, 108 insertions(+), 15 deletions(-) diff --git a/build-scripts/webpack.cjs b/build-scripts/webpack.cjs index efed17792f..769dd58a12 100644 --- a/build-scripts/webpack.cjs +++ b/build-scripts/webpack.cjs @@ -165,6 +165,7 @@ const createWebpackConfig = ({ "lit/directives/guard$": "lit/directives/guard.js", "lit/directives/cache$": "lit/directives/cache.js", "lit/directives/repeat$": "lit/directives/repeat.js", + "lit/directives/live$": "lit/directives/live.js", "lit/polyfill-support$": "lit/polyfill-support.js", "@lit-labs/virtualizer/layouts/grid": "@lit-labs/virtualizer/layouts/grid.js", diff --git a/package.json b/package.json index 473d3b7b27..361e74d119 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "@material/mwc-dialog": "0.27.0", "@material/mwc-drawer": "0.27.0", "@material/mwc-fab": "0.27.0", + "@material/mwc-floating-label": "0.27.0", "@material/mwc-formfield": "0.27.0", "@material/mwc-icon-button": "0.27.0", "@material/mwc-linear-progress": "0.27.0", diff --git a/src/auth/ha-auth-flow.ts b/src/auth/ha-auth-flow.ts index b64cd092dd..f8f00cc972 100644 --- a/src/auth/ha-auth-flow.ts +++ b/src/auth/ha-auth-flow.ts @@ -77,11 +77,11 @@ export class HaAuthFlow extends LitElement { protected render() { return html` + ha-auth-form .root > * { + display: block; + } + ha-auth-form .root > *:not([own-margin]):not(:last-child) { + margin-bottom: 24px; + } + ha-auth-form ha-alert[own-margin] { + margin-bottom: 4px; + } + + ${super.render()} + `; + } } declare global { diff --git a/src/auth/ha-auth-textfield.ts b/src/auth/ha-auth-textfield.ts index 7c4bb2c6cc..123deef03f 100644 --- a/src/auth/ha-auth-textfield.ts +++ b/src/auth/ha-auth-textfield.ts @@ -1,11 +1,79 @@ +/* eslint-disable lit/value-after-constraints */ /* eslint-disable lit/prefer-static-styles */ -import { html } from "lit"; +import { floatingLabel } from "@material/mwc-floating-label/mwc-floating-label-directive"; +import { TemplateResult, html } from "lit"; import { customElement } from "lit/decorators"; +import { ifDefined } from "lit/directives/if-defined"; +import { live } from "lit/directives/live"; import { HaTextField } from "../components/ha-textfield"; -import "@material/mwc-textfield/mwc-textfield.css"; @customElement("ha-auth-textfield") export class HaAuthTextField extends HaTextField { + protected renderLabel(): TemplateResult | string { + return !this.label + ? "" + : html` + ${this.label} + `; + } + + protected renderInput(shouldRenderHelperText: boolean): TemplateResult { + const minOrUndef = this.minLength === -1 ? undefined : this.minLength; + const maxOrUndef = this.maxLength === -1 ? undefined : this.maxLength; + const autocapitalizeOrUndef = this.autocapitalize + ? (this.autocapitalize as + | "off" + | "none" + | "on" + | "sentences" + | "words" + | "characters") + : undefined; + const showValidationMessage = this.validationMessage && !this.isUiValid; + const ariaLabelledbyOrUndef = this.label ? this.name : undefined; + const ariaControlsOrUndef = shouldRenderHelperText + ? "helper-text" + : undefined; + const ariaDescribedbyOrUndef = + this.focused || this.helperPersistent || showValidationMessage + ? "helper-text" + : undefined; + // TODO: live() directive needs casting for lit-analyzer + // https://github.com/runem/lit-analyzer/pull/91/files + // TODO: lit-analyzer labels min/max as (number|string) instead of string + return html` `; + } + public render() { return html`