diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 7d056f13fd57..2db287bfd4d4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -24,6 +24,7 @@ body: required: true - label: I have tried a different browser to see if it is related to my browser. required: true + - label: I have tried reproducing the issue in [safe mode](https://www.home-assistant.io/blog/2023/11/01/release-202311/#restarting-into-safe-mode) to rule out problems with unsupported custom resources. - type: markdown attributes: value: | diff --git a/.github/workflows/cast_deployment.yaml b/.github/workflows/cast_deployment.yaml index da5a9c89d354..2aa9ce5168e0 100644 --- a/.github/workflows/cast_deployment.yaml +++ b/.github/workflows/cast_deployment.yaml @@ -26,7 +26,7 @@ jobs: ref: dev - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn @@ -62,7 +62,7 @@ jobs: ref: master - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 607e26f29e20..af8a33890396 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,7 +26,7 @@ jobs: - name: Check out files from GitHub uses: actions/checkout@v4.1.1 - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn @@ -57,14 +57,14 @@ jobs: - name: Check out files from GitHub uses: actions/checkout@v4.1.1 - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn - name: Install dependencies run: yarn install --immutable - name: Build resources - run: ./node_modules/.bin/gulp build-translations build-locale-data + run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data - name: Run Tests run: yarn run test build: @@ -75,7 +75,7 @@ jobs: - name: Check out files from GitHub uses: actions/checkout@v4.1.1 - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn @@ -99,7 +99,7 @@ jobs: - name: Check out files from GitHub uses: actions/checkout@v4.1.1 - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b1fbba90483f..d4d15cc4bcdd 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,14 +36,14 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -57,4 +57,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/demo_deployment.yaml b/.github/workflows/demo_deployment.yaml index 5a4f6f2ccee6..9aa8219845bf 100644 --- a/.github/workflows/demo_deployment.yaml +++ b/.github/workflows/demo_deployment.yaml @@ -27,7 +27,7 @@ jobs: ref: dev - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn @@ -63,7 +63,7 @@ jobs: ref: master - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn diff --git a/.github/workflows/design_deployment.yaml b/.github/workflows/design_deployment.yaml index 9ab9820fb668..7fd0110210e4 100644 --- a/.github/workflows/design_deployment.yaml +++ b/.github/workflows/design_deployment.yaml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v4.1.1 - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn diff --git a/.github/workflows/design_preview.yaml b/.github/workflows/design_preview.yaml index d26178ba9f2a..b24148d66ddc 100644 --- a/.github/workflows/design_preview.yaml +++ b/.github/workflows/design_preview.yaml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@v4.1.1 - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index cbff00ba5707..4ff941bb8ac2 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -28,7 +28,7 @@ jobs: python-version: ${{ env.PYTHON_VERSION }} - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a47c5325d085..8bded3fcc5e2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -34,7 +34,7 @@ jobs: python-version: ${{ env.PYTHON_VERSION }} - name: Setup Node - uses: actions/setup-node@v4.0.0 + uses: actions/setup-node@v4.0.1 with: node-version-file: ".nvmrc" cache: yarn diff --git a/build-scripts/bundle.cjs b/build-scripts/bundle.cjs index 18731af3d5ec..c341909b19b0 100644 --- a/build-scripts/bundle.cjs +++ b/build-scripts/bundle.cjs @@ -1,6 +1,7 @@ const path = require("path"); const env = require("./env.cjs"); const paths = require("./paths.cjs"); +const { dependencies } = require("../package.json"); // GitHub base URL to use for production source maps // Nightly builds use the commit SHA, otherwise assumes there is a tag that matches the version @@ -90,7 +91,7 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({ "@babel/preset-env", { useBuiltIns: latestBuild ? false : "usage", - corejs: latestBuild ? false : "3.33", + corejs: latestBuild ? false : dependencies["core-js"], bugfixes: true, shippedProposals: true, }, @@ -140,7 +141,7 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({ // Import helpers and regenerator from runtime package [ "@babel/plugin-transform-runtime", - { version: require("../package.json").dependencies["@babel/runtime"] }, + { version: dependencies["@babel/runtime"] }, ], // Support some proposals still in TC39 process ["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }], diff --git a/gallery/src/data/demo_states.js b/gallery/src/data/demo_states.js index 060ce56e29ad..d57cc1a422b0 100644 --- a/gallery/src/data/demo_states.js +++ b/gallery/src/data/demo_states.js @@ -509,7 +509,7 @@ export default { away_mode: "on", aux_heat: "off", unit_of_measurement: "°C", - friendly_name: "Hvac", + friendly_name: "HVAC", supported_features: 3833, }, last_changed: "2018-07-19T10:44:46.200650+00:00", diff --git a/gallery/src/pages/lovelace/thermostat-card.ts b/gallery/src/pages/lovelace/thermostat-card.ts index cc33346a0eb6..623adf5e3436 100644 --- a/gallery/src/pages/lovelace/thermostat-card.ts +++ b/gallery/src/pages/lovelace/thermostat-card.ts @@ -35,6 +35,18 @@ const ENTITIES = [ friendly_name: "Nest", supported_features: 43, }), + getEntity("climate", "sensibo", "fan_only", { + current_temperature: null, + temperature: null, + min_temp: 0, + max_temp: 1, + target_temp_step: 1, + hvac_modes: ["fan_only", "off"], + friendly_name: "Sensibo purifier", + fan_modes: ["low", "high"], + fan_mode: "low", + supported_features: 9, + }), getEntity("climate", "unavailable", "unavailable", { supported_features: 43, }), @@ -57,6 +69,23 @@ const CONFIGS = [ entity: climate.nest `, }, + { + heading: "Fan only example", + config: ` +- type: thermostat + entity: climate.sensibo + features: + - type: climate-hvac-modes + hvac_modes: + - fan_only + - 'off' + - type: climate-fan-modes + style: icons + fan_modes: + - low + - high + `, + }, { heading: "Unavailable", config: ` diff --git a/gallery/src/pages/more-info/climate.ts b/gallery/src/pages/more-info/climate.ts index daa3554c5035..f6216a55b1c4 100644 --- a/gallery/src/pages/more-info/climate.ts +++ b/gallery/src/pages/more-info/climate.ts @@ -31,6 +31,21 @@ const ENTITIES = [ max_temp: 30, supported_features: ClimateEntityFeature.TARGET_TEMPERATURE, }), + getEntity("climate", "fan", "fan_only", { + friendly_name: "Basic fan", + hvac_modes: ["fan_only", "off"], + hvac_mode: "fan_only", + fan_modes: ["low", "high"], + fan_mode: "low", + current_temperature: null, + temperature: null, + min_temp: 0, + max_temp: 1, + target_temp_step: 1, + supported_features: + // eslint-disable-next-line no-bitwise + ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE, + }), getEntity("climate", "hvac", "auto", { friendly_name: "Basic hvac", hvac_modes: ["auto", "off"], diff --git a/gallery/src/pages/more-info/update.ts b/gallery/src/pages/more-info/update.ts index ce4fa4f6f73d..43951d4c5e8a 100644 --- a/gallery/src/pages/more-info/update.ts +++ b/gallery/src/pages/more-info/update.ts @@ -1,12 +1,6 @@ import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { customElement, property, query } from "lit/decorators"; import "../../../../src/components/ha-card"; -import { - UPDATE_SUPPORT_BACKUP, - UPDATE_SUPPORT_PROGRESS, - UPDATE_SUPPORT_INSTALL, - UPDATE_SUPPORT_RELEASE_NOTES, -} from "../../../../src/data/update"; import "../../../../src/dialogs/more-info/more-info-content"; import { getEntity } from "../../../../src/fake_data/entity"; import { @@ -15,13 +9,14 @@ import { } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-more-infos"; import { LONG_TEXT } from "../../data/text"; +import { UpdateEntityFeature } from "../../../../src/data/update"; const base_attributes = { title: "Awesome", installed_version: "1.2.2", latest_version: "1.2.3", release_url: "https://home-assistant.io", - supported_features: UPDATE_SUPPORT_INSTALL, + supported_features: UpdateEntityFeature.INSTALL, skipped_version: null, in_progress: false, release_summary: @@ -61,7 +56,7 @@ const ENTITIES = [ getEntity("update", "update7", "on", { ...base_attributes, supported_features: - base_attributes.supported_features + UPDATE_SUPPORT_BACKUP, + base_attributes.supported_features + UpdateEntityFeature.BACKUP, friendly_name: "With backup support", }), getEntity("update", "update8", "on", { @@ -73,21 +68,21 @@ const ENTITIES = [ ...base_attributes, in_progress: 25, supported_features: - base_attributes.supported_features + UPDATE_SUPPORT_PROGRESS, + base_attributes.supported_features + UpdateEntityFeature.PROGRESS, friendly_name: "With 25 in_progress", }), getEntity("update", "update10", "on", { ...base_attributes, in_progress: 50, supported_features: - base_attributes.supported_features + UPDATE_SUPPORT_PROGRESS, + base_attributes.supported_features + UpdateEntityFeature.PROGRESS, friendly_name: "With 50 in_progress", }), getEntity("update", "update11", "on", { ...base_attributes, in_progress: 75, supported_features: - base_attributes.supported_features + UPDATE_SUPPORT_PROGRESS, + base_attributes.supported_features + UpdateEntityFeature.PROGRESS, friendly_name: "With 75 in_progress", }), getEntity("update", "update12", "unavailable", { @@ -114,19 +109,19 @@ const ENTITIES = [ ...base_attributes, friendly_name: "Update with release notes", supported_features: - base_attributes.supported_features + UPDATE_SUPPORT_RELEASE_NOTES, + base_attributes.supported_features + UpdateEntityFeature.RELEASE_NOTES, }), getEntity("update", "update17", "off", { ...base_attributes, friendly_name: "Update with release notes error", supported_features: - base_attributes.supported_features + UPDATE_SUPPORT_RELEASE_NOTES, + base_attributes.supported_features + UpdateEntityFeature.RELEASE_NOTES, }), getEntity("update", "update18", "off", { ...base_attributes, friendly_name: "Update with release notes loading", supported_features: - base_attributes.supported_features + UPDATE_SUPPORT_RELEASE_NOTES, + base_attributes.supported_features + UpdateEntityFeature.RELEASE_NOTES, }), getEntity("update", "update19", "on", { ...base_attributes, @@ -142,9 +137,10 @@ const ENTITIES = [ getEntity("update", "update21", "on", { ...base_attributes, in_progress: true, - friendly_name: "Update with in_progress true and UPDATE_SUPPORT_PROGRESS", + friendly_name: + "Update with in_progress true and UpdateEntityFeature.PROGRESS", supported_features: - base_attributes.supported_features + UPDATE_SUPPORT_PROGRESS, + base_attributes.supported_features + UpdateEntityFeature.PROGRESS, }), ]; diff --git a/hassio/src/dialogs/datadisk/dialog-hassio-datadisk.ts b/hassio/src/dialogs/datadisk/dialog-hassio-datadisk.ts index 8a1c3c670221..4dcfde2ec2b4 100644 --- a/hassio/src/dialogs/datadisk/dialog-hassio-datadisk.ts +++ b/hassio/src/dialogs/datadisk/dialog-hassio-datadisk.ts @@ -4,7 +4,6 @@ import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../src/common/dom/fire_event"; import "../../../../src/components/ha-circular-progress"; -import "../../../../src/components/ha-markdown"; import "../../../../src/components/ha-select"; import { extractApiErrorMessage, diff --git a/package.json b/package.json index 540059eeb516..663a412014d2 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "license": "Apache-2.0", "type": "module", "dependencies": { - "@babel/runtime": "7.23.5", + "@babel/runtime": "7.23.7", "@braintree/sanitize-url": "7.0.0", "@codemirror/autocomplete": "6.11.1", "@codemirror/commands": "6.3.2", @@ -33,7 +33,7 @@ "@codemirror/legacy-modes": "6.3.3", "@codemirror/search": "6.5.5", "@codemirror/state": "6.3.3", - "@codemirror/view": "6.22.2", + "@codemirror/view": "6.22.3", "@egjs/hammerjs": "2.0.17", "@formatjs/intl-datetimeformat": "6.12.0", "@formatjs/intl-displaynames": "6.6.4", @@ -80,9 +80,9 @@ "@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.1", - "@mdi/js": "7.3.67", - "@mdi/svg": "7.3.67", + "@material/web": "=1.1.1", + "@mdi/js": "7.4.47", + "@mdi/svg": "7.4.47", "@polymer/paper-input": "3.2.1", "@polymer/paper-item": "3.0.1", "@polymer/paper-listbox": "3.0.1", @@ -90,8 +90,8 @@ "@polymer/paper-toast": "3.0.1", "@polymer/polymer": "3.5.1", "@thomasloven/round-slider": "0.6.0", - "@vaadin/combo-box": "24.2.5", - "@vaadin/vaadin-themable-mixin": "24.2.5", + "@vaadin/combo-box": "24.3.2", + "@vaadin/vaadin-themable-mixin": "24.3.2", "@vibrant/color": "3.2.1-alpha.1", "@vibrant/core": "3.2.1-alpha.1", "@vibrant/quantizer-mmcq": "3.2.1-alpha.1", @@ -101,16 +101,16 @@ "app-datepicker": "5.1.1", "chart.js": "4.4.1", "comlink": "4.4.1", - "core-js": "3.33.3", + "core-js": "3.34.0", "cropperjs": "1.6.1", "date-fns": "2.30.0", "date-fns-tz": "2.0.0", "deep-clone-simple": "1.1.1", "deep-freeze": "0.0.1", - "element-internals-polyfill": "1.3.9", + "element-internals-polyfill": "1.3.10", "fuse.js": "7.0.0", "google-timezones-json": "1.2.0", - "hls.js": "1.4.13", + "hls.js": "1.4.14", "home-assistant-js-websocket": "9.1.0", "idb-keyval": "6.2.1", "intl-messageformat": "10.5.8", @@ -119,7 +119,7 @@ "leaflet-draw": "1.0.4", "lit": "2.8.0", "luxon": "3.4.4", - "marked": "11.0.1", + "marked": "11.1.0", "memoize-one": "6.0.0", "node-vibrant": "3.2.1-alpha.1", "proxy-polyfill": "0.3.2", @@ -138,7 +138,7 @@ "unfetch": "5.0.0", "vis-data": "7.1.9", "vis-network": "9.1.9", - "vue": "2.7.15", + "vue": "2.7.16", "vue2-daterange-picker": "0.6.8", "weekstart": "2.0.0", "workbox-cacheable-response": "7.0.0", @@ -150,13 +150,13 @@ "xss": "1.0.14" }, "devDependencies": { - "@babel/core": "7.23.5", - "@babel/helper-define-polyfill-provider": "0.4.3", - "@babel/plugin-proposal-decorators": "7.23.5", - "@babel/plugin-transform-runtime": "7.23.4", - "@babel/preset-env": "7.23.5", + "@babel/core": "7.23.7", + "@babel/helper-define-polyfill-provider": "0.4.4", + "@babel/plugin-proposal-decorators": "7.23.7", + "@babel/plugin-transform-runtime": "7.23.7", + "@babel/preset-env": "7.23.7", "@babel/preset-typescript": "7.23.3", - "@bundle-stats/plugin-webpack-filter": "4.8.3", + "@bundle-stats/plugin-webpack-filter": "4.8.4", "@koa/cors": "5.0.0", "@lokalise/node-api": "12.1.0", "@octokit/auth-oauth-device": "6.0.1", @@ -165,7 +165,7 @@ "@open-wc/dev-server-hmr": "0.1.4", "@rollup/plugin-babel": "6.0.4", "@rollup/plugin-commonjs": "25.0.7", - "@rollup/plugin-json": "6.0.1", + "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "15.2.3", "@rollup/plugin-replace": "5.0.5", "@types/babel__plugin-transform-runtime": "7.9.5", @@ -184,22 +184,22 @@ "@types/tar": "6.1.10", "@types/ua-parser-js": "0.7.39", "@types/webspeechapi": "0.0.29", - "@typescript-eslint/eslint-plugin": "6.13.2", - "@typescript-eslint/parser": "6.13.2", + "@typescript-eslint/eslint-plugin": "6.16.0", + "@typescript-eslint/parser": "6.16.0", "@web/dev-server": "0.1.38", "@web/dev-server-rollup": "0.4.1", "babel-loader": "9.1.3", "babel-plugin-template-html-minifier": "4.1.0", - "chai": "4.3.10", + "chai": "5.0.0", "del": "7.1.0", - "eslint": "8.55.0", + "eslint": "8.56.0", "eslint-config-airbnb-base": "15.0.0", "eslint-config-airbnb-typescript": "17.1.0", "eslint-config-prettier": "9.1.0", "eslint-import-resolver-webpack": "0.13.8", "eslint-plugin-disable": "2.0.3", - "eslint-plugin-import": "2.29.0", - "eslint-plugin-lit": "1.10.1", + "eslint-plugin-import": "2.29.1", + "eslint-plugin-lit": "1.11.0", "eslint-plugin-lit-a11y": "4.1.1", "eslint-plugin-unused-imports": "3.0.0", "eslint-plugin-wc": "2.0.4", @@ -217,25 +217,25 @@ "instant-mocha": "1.5.2", "jszip": "3.10.1", "lint-staged": "15.2.0", - "lit-analyzer": "2.0.1", + "lit-analyzer": "2.0.2", "lodash.template": "4.5.0", "magic-string": "0.30.5", "map-stream": "0.0.7", "mocha": "10.2.0", "object-hash": "3.0.0", - "open": "9.1.0", + "open": "10.0.2", "pinst": "3.0.0", "prettier": "3.1.1", "rollup": "2.79.1", "rollup-plugin-string": "3.0.0", "rollup-plugin-terser": "7.0.2", - "rollup-plugin-visualizer": "5.11.0", + "rollup-plugin-visualizer": "5.12.0", "serve-handler": "6.1.5", "sinon": "17.0.1", "source-map-url": "0.4.1", "systemjs": "6.14.2", "tar": "6.2.0", - "terser-webpack-plugin": "5.3.9", + "terser-webpack-plugin": "5.3.10", "ts-lit-plugin": "2.0.1", "typescript": "5.3.3", "vinyl-buffer": "1.0.1", @@ -245,7 +245,7 @@ "webpack-dev-server": "4.15.1", "webpack-manifest-plugin": "5.0.0", "webpack-stats-plugin": "1.1.3", - "webpackbar": "5.0.2", + "webpackbar": "6.0.0", "workbox-build": "7.0.0" }, "_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch", diff --git a/pyproject.toml b/pyproject.toml index afea7e45d6b0..7d09a1121ede 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20231208.2" +version = "20240102.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" diff --git a/src/common/const.ts b/src/common/const.ts index 66c14e64e140..68f4fa97b1c1 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -29,6 +29,7 @@ import { mdiFlash, mdiFlower, mdiFormatListBulleted, + mdiFormatListCheckbox, mdiFormTextbox, mdiGauge, mdiGoogleAssistant, @@ -64,6 +65,7 @@ import { mdiTransmissionTower, mdiWater, mdiWaterPercent, + mdiWeatherPartlyCloudy, mdiWeatherPouring, mdiWeatherRainy, mdiWeatherWindy, @@ -128,6 +130,7 @@ export const FIXED_DOMAIN_ICONS = { updater: mdiCloudUpload, vacuum: mdiRobotVacuum, wake_word: mdiChatSleep, + weather: mdiWeatherPartlyCloudy, zone: mdiMapMarkerRadius, }; @@ -166,6 +169,7 @@ export const FIXED_DEVICE_CLASS_ICONS = { precipitation_intensity: mdiWeatherPouring, pressure: mdiGauge, reactive_power: mdiFlash, + shopping_List: mdiFormatListCheckbox, signal_strength: mdiWifi, sound_pressure: mdiEarHearing, speed: mdiSpeedometer, diff --git a/src/common/datetime/localize_date.ts b/src/common/datetime/localize_date.ts new file mode 100644 index 000000000000..428261801d58 --- /dev/null +++ b/src/common/datetime/localize_date.ts @@ -0,0 +1,31 @@ +import memoizeOne from "memoize-one"; + +export const localizeWeekdays = memoizeOne( + (language: string, short: boolean): string[] => { + const days: string[] = []; + const format = new Intl.DateTimeFormat(language, { + weekday: short ? "short" : "long", + timeZone: "UTC", + }); + for (let i = 0; i < 7; i++) { + const date = new Date(Date.UTC(1970, 0, 1 + 3 + i)); + days.push(format.format(date)); + } + return days; + } +); + +export const localizeMonths = memoizeOne( + (language: string, short: boolean): string[] => { + const months: string[] = []; + const format = new Intl.DateTimeFormat(language, { + month: short ? "short" : "long", + timeZone: "UTC", + }); + for (let i = 0; i < 12; i++) { + const date = new Date(Date.UTC(1970, 0 + i, 1)); + months.push(format.format(date)); + } + return months; + } +); diff --git a/src/common/entity/domain_icon.ts b/src/common/entity/domain_icon.ts index 565358e9e409..dfbbc69a5e17 100644 --- a/src/common/entity/domain_icon.ts +++ b/src/common/entity/domain_icon.ts @@ -28,10 +28,12 @@ import { mdiLockAlert, mdiLockClock, mdiLockOpen, + mdiMeterGas, mdiMotionSensor, mdiPackage, mdiPackageDown, mdiPackageUp, + mdiPipeValve, mdiPowerPlug, mdiPowerPlugOff, mdiRestart, @@ -274,6 +276,16 @@ export const domainIconWithoutDefault = ( : mdiPackageUp : mdiPackage; + case "valve": + switch (stateObj?.attributes.device_class) { + case "water": + return mdiPipeValve; + case "gas": + return mdiMeterGas; + default: + return mdiPipeValve; + } + case "water_heater": return compareState === "off" ? mdiWaterBoilerOff : mdiWaterBoiler; diff --git a/src/common/entity/state_active.ts b/src/common/entity/state_active.ts index 7c304f03890e..16ca41c9c19f 100644 --- a/src/common/entity/state_active.ts +++ b/src/common/entity/state_active.ts @@ -42,6 +42,8 @@ export function stateActive(stateObj: HassEntity, state?: string): boolean { return compareState !== "standby"; case "vacuum": return !["idle", "docked", "paused"].includes(compareState); + case "valve": + return compareState !== "closed"; case "plant": return compareState === "problem"; case "group": diff --git a/src/common/entity/state_color.ts b/src/common/entity/state_color.ts index 0abaca4c17c8..09145eed83c7 100644 --- a/src/common/entity/state_color.ts +++ b/src/common/entity/state_color.ts @@ -37,6 +37,7 @@ const STATE_COLORED_DOMAIN = new Set([ "timer", "update", "vacuum", + "valve", "water_heater", ]); diff --git a/src/components/chart/statistics-chart.ts b/src/components/chart/statistics-chart.ts index 1914849be492..a0fc6ca53ba5 100644 --- a/src/components/chart/statistics-chart.ts +++ b/src/components/chart/statistics-chart.ts @@ -101,7 +101,8 @@ export class StatisticsChart extends LitElement { changedProps.has("unit") || changedProps.has("period") || changedProps.has("chartType") || - changedProps.has("logarithmicScale") + changedProps.has("logarithmicScale") || + changedProps.has("hideLegend") ) { this._createOptions(); } diff --git a/src/components/date-range-picker.ts b/src/components/date-range-picker.ts index b60ce14763e3..237576a89ce3 100644 --- a/src/components/date-range-picker.ts +++ b/src/components/date-range-picker.ts @@ -5,6 +5,10 @@ import DateRangePicker from "vue2-daterange-picker"; // @ts-ignore import dateRangePickerStyles from "vue2-daterange-picker/dist/vue2-daterange-picker.css"; import { fireEvent } from "../common/dom/fire_event"; +import { + localizeWeekdays, + localizeMonths, +} from "../common/datetime/localize_date"; // Set the current date to the left picker instead of the right picker because the right is hidden const CustomDateRangePicker = Vue.extend({ @@ -63,6 +67,10 @@ const Component = Vue.extend({ type: Boolean, default: false, }, + language: { + type: String, + default: "en", + }, }, render(createElement) { // @ts-expect-error @@ -77,6 +85,8 @@ const Component = Vue.extend({ ranges: this.ranges ? {} : false, "locale-data": { firstDay: this.firstDay, + daysOfWeek: localizeWeekdays(this.language, true), + monthNames: localizeMonths(this.language, false), }, }, model: { @@ -145,6 +155,8 @@ class DateRangePickerElement extends WrappedElement { ); color: var(--primary-text-color); min-width: initial !important; + max-height: var(--date-range-picker-max-height); + overflow-y: auto; } .daterangepicker:before { display: none; @@ -162,7 +174,7 @@ class DateRangePickerElement extends WrappedElement { color: var(--secondary-text-color); border-radius: 0; outline: none; - width: 32px; + min-width: 32px; height: 32px; } .daterangepicker td.off, @@ -238,6 +250,9 @@ class DateRangePickerElement extends WrappedElement { } .daterangepicker .drp-calendar.left { padding: 8px; + width: unset; + max-width: unset; + min-width: 270px; } .daterangepicker.show-calendar .ranges { margin-top: 0; diff --git a/src/components/ha-area-picker.ts b/src/components/ha-area-picker.ts index d2a0f689fb75..423de3df7a88 100644 --- a/src/components/ha-area-picker.ts +++ b/src/components/ha-area-picker.ts @@ -446,6 +446,7 @@ export class HaAreaPicker extends LitElement { cancel: () => { this._setValue(undefined); this._suggestion = undefined; + this.comboBox.setInputValue(""); }, }); } diff --git a/src/components/ha-big-number.ts b/src/components/ha-big-number.ts index ee0a5cf75977..85a7783c87c1 100644 --- a/src/components/ha-big-number.ts +++ b/src/components/ha-big-number.ts @@ -86,6 +86,7 @@ export class HaBigNumber extends LitElement { .value .decimal { font-size: 0.42em; line-height: 1.33; + min-height: 1.33em; } .value .unit { font-size: 0.33em; diff --git a/src/components/ha-check-list-item.ts b/src/components/ha-check-list-item.ts index 96e62a475eae..19f04feda9cd 100644 --- a/src/components/ha-check-list-item.ts +++ b/src/components/ha-check-list-item.ts @@ -3,9 +3,15 @@ import { CheckListItemBase } from "@material/mwc-list/mwc-check-list-item-base"; import { styles as controlStyles } from "@material/mwc-list/mwc-control-list-item.css"; import { styles } from "@material/mwc-list/mwc-list-item.css"; import { customElement } from "lit/decorators"; +import { fireEvent } from "../common/dom/fire_event"; @customElement("ha-check-list-item") export class HaCheckListItem extends CheckListItemBase { + async onChange(event) { + super.onChange(event); + fireEvent(this, event.type); + } + static override styles = [ styles, controlStyles, @@ -22,6 +28,15 @@ export class HaCheckListItem extends CheckListItemBase { margin-inline-start: 0px; direction: var(--direction); } + .mdc-deprecated-list-item__meta { + flex-shrink: 0; + direction: var(--direction); + margin-inline-start: auto; + margin-inline-end: 0; + } + .mdc-deprecated-list-item__graphic { + margin-top: var(--check-list-item-graphic-margin-top); + } `, ]; } diff --git a/src/components/ha-combo-box.ts b/src/components/ha-combo-box.ts index 9c50d0a4bbb2..ce6d54f41565 100644 --- a/src/components/ha-combo-box.ts +++ b/src/components/ha-combo-box.ts @@ -180,7 +180,7 @@ export class HaComboBox extends LitElement { >`} .icon=${this.icon} .invalid=${this.invalid} - helper=${ifDefined(this.helper)} + .helper=${this.helper} helperPersistent > diff --git a/src/components/ha-date-input.ts b/src/components/ha-date-input.ts index d3b5a0607eb3..d4d9922639d9 100644 --- a/src/components/ha-date-input.ts +++ b/src/components/ha-date-input.ts @@ -18,7 +18,8 @@ export interface datePickerDialogParams { max?: string; locale?: string; firstWeekday?: number; - onChange: (value: string) => void; + canClear?: boolean; + onChange: (value: string | undefined) => void; } const showDatePickerDialog = ( @@ -49,6 +50,8 @@ export class HaDateInput extends LitElement { @property() public helper?: string; + @property({ type: Boolean }) public canClear?: boolean; + render() { return html` this._valueChanged(value), locale: this.locale.language, firstWeekday: firstWeekdayIndex(this.locale), }); } - private _valueChanged(value: string) { + private _keyDown(ev: KeyboardEvent) { + if (!this.canClear) { + return; + } + if (["Backspace", "Delete"].includes(ev.key)) { + this._valueChanged(undefined); + } + } + + private _valueChanged(value: string | undefined) { if (this.value !== value) { this.value = value; fireEvent(this, "change"); diff --git a/src/components/ha-date-range-picker.ts b/src/components/ha-date-range-picker.ts index 29b43c697918..7e16fecd22db 100644 --- a/src/components/ha-date-range-picker.ts +++ b/src/components/ha-date-range-picker.ts @@ -253,6 +253,7 @@ export class HaDateRangePicker extends LitElement { opening-direction=${this.openingDirection || this._calcedOpeningDirection} first-day=${firstWeekdayIndex(this.hass.locale)} + language=${this.hass.locale.language} >
${!this.minimal diff --git a/src/components/ha-dialog-date-picker.ts b/src/components/ha-dialog-date-picker.ts index 2422754cfb15..b71e063ae410 100644 --- a/src/components/ha-dialog-date-picker.ts +++ b/src/components/ha-dialog-date-picker.ts @@ -50,6 +50,15 @@ export class HaDialogDatePicker extends LitElement { @datepicker-value-updated=${this._valueChanged} .firstDayOfWeek=${this._params.firstWeekday} > + ${this._params.canClear + ? html` + ${this.hass.localize("ui.dialogs.date-picker.clear")} + ` + : nothing} ${this.hass.localize("ui.dialogs.date-picker.today")} @@ -66,6 +75,11 @@ export class HaDialogDatePicker extends LitElement { this._value = ev.detail.value; } + private _clear() { + this._params?.onChange(undefined); + this.closeDialog(); + } + private _setToday() { const today = new Date(); this._value = format(today, "yyyy-MM-dd"); diff --git a/src/components/ha-dialog.ts b/src/components/ha-dialog.ts index feaceec93daf..9cf199dbe52b 100644 --- a/src/components/ha-dialog.ts +++ b/src/components/ha-dialog.ts @@ -13,13 +13,15 @@ export const createCloseHeading = ( hass: HomeAssistant | undefined, title: string | TemplateResult ) => html` -
${title}
- +
+ ${title} + +
`; @customElement("ha-dialog") @@ -94,15 +96,12 @@ export class HaDialog extends DialogBase { } .mdc-dialog__title { padding: 24px 24px 0 24px; - text-overflow: ellipsis; - overflow: hidden; } .mdc-dialog__actions { padding: 12px 24px 12px 24px; } .mdc-dialog__title::before { - display: block; - height: 0px; + content: unset; } .mdc-dialog .mdc-dialog__content { position: var(--dialog-content-position, relative); @@ -126,19 +125,26 @@ export class HaDialog extends DialogBase { flex-direction: column; } .header_title { - margin-right: 32px; - margin-inline-end: 32px; - margin-inline-start: initial; + position: relative; + padding-right: 40px; + padding-inline-end: 40px; + padding-inline-start: initial; direction: var(--direction); } + .header_title span { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + display: block; + } .header_button { position: absolute; - right: 16px; - top: 14px; + right: -8px; + top: -8px; text-decoration: none; color: inherit; inset-inline-start: initial; - inset-inline-end: 16px; + inset-inline-end: -8px; direction: var(--direction); } .dialog-actions { diff --git a/src/components/ha-labeled-slider.ts b/src/components/ha-labeled-slider.ts index 366eb4f5555c..5faf7a8b96b2 100644 --- a/src/components/ha-labeled-slider.ts +++ b/src/components/ha-labeled-slider.ts @@ -10,9 +10,9 @@ class HaLabeledSlider extends LitElement { @property() public caption?: string; - @property() public disabled?: boolean; + @property({ type: Boolean }) public disabled = false; - @property() public required?: boolean; + @property({ type: Boolean }) public required = true; @property() public min: number = 0; diff --git a/src/components/ha-list-item.ts b/src/components/ha-list-item.ts index a5179008b5b5..dcd13f0f7074 100644 --- a/src/components/ha-list-item.ts +++ b/src/components/ha-list-item.ts @@ -36,16 +36,24 @@ export class HaListItem extends ListItemBase { --mdc-list-item-graphic-margin, 16px ) !important; - direction: var(--direction); + direction: var(--direction) !important; } span.material-icons:last-of-type { margin-inline-start: auto !important; margin-inline-end: 0px !important; - direction: var(--direction); + direction: var(--direction) !important; } .mdc-deprecated-list-item__meta { display: var(--mdc-list-item-meta-display); align-items: center; + flex-shrink: 0; + } + :host([graphic="icon"]:not([twoline])) + .mdc-deprecated-list-item__graphic { + margin-inline-end: var( + --mdc-list-item-graphic-margin, + 20px + ) !important; } :host([multiline-secondary]) { height: auto; @@ -78,6 +86,15 @@ export class HaListItem extends ListItemBase { pointer-events: unset; } `, + // safari workaround - must be explicit + document.dir === "rtl" + ? css` + span.material-icons:first-of-type, + span.material-icons:last-of-type { + direction: rtl !important; + } + ` + : css``, ]; } } diff --git a/src/components/ha-markdown-element.ts b/src/components/ha-markdown-element.ts index e00bfceb9477..0e806b7c7dcf 100644 --- a/src/components/ha-markdown-element.ts +++ b/src/components/ha-markdown-element.ts @@ -95,6 +95,15 @@ class HaMarkdownElement extends ReactiveElement { } node.firstElementChild!.replaceWith(alertNote); } + } else if ( + node instanceof HTMLElement && + ["ha-alert", "ha-qr-code", "ha-icon", "ha-svg-icon"].includes( + node.localName + ) + ) { + import( + /* webpackInclude: /(ha-alert)|(ha-qr-code)|(ha-icon)|(ha-svg-icon)/ */ `./${node.localName}` + ); } } } diff --git a/src/components/ha-markdown.ts b/src/components/ha-markdown.ts index c248a320e819..f81ddd286037 100644 --- a/src/components/ha-markdown.ts +++ b/src/components/ha-markdown.ts @@ -2,11 +2,6 @@ import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property } from "lit/decorators"; import "./ha-markdown-element"; -// Import components that are allwoed to be defined. -import "./ha-alert"; -import "./ha-icon"; -import "./ha-svg-icon"; - @customElement("ha-markdown") export class HaMarkdown extends LitElement { @property() public content?; diff --git a/src/components/ha-qr-code.ts b/src/components/ha-qr-code.ts new file mode 100644 index 000000000000..f6a686d06823 --- /dev/null +++ b/src/components/ha-qr-code.ts @@ -0,0 +1,114 @@ +import { LitElement, PropertyValues, css, html, nothing } from "lit"; +import { customElement, property, query, state } from "lit/decorators"; +import QRCode from "qrcode"; + +@customElement("ha-qr-code") +export class HaQrCode extends LitElement { + @property() public data?: string; + + @property({ attribute: "error-correction-level" }) + public errorCorrectionLevel: "low" | "medium" | "quartile" | "high" = + "medium"; + + @property({ type: Number }) + public width = 4; + + @property({ type: Number }) + public scale = 4; + + @property({ type: Number }) + public margin = 4; + + @property({ type: Number }) public maskPattern?: + | 0 + | 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7; + + @property({ attribute: "center-image" }) public centerImage?: string; + + @state() private _error?: string; + + @query("canvas") private _canvas?: HTMLCanvasElement; + + protected willUpdate(changedProperties: PropertyValues): void { + super.willUpdate(changedProperties); + if ( + (changedProperties.has("data") || + changedProperties.has("scale") || + changedProperties.has("width") || + changedProperties.has("margin") || + changedProperties.has("maskPattern") || + changedProperties.has("errorCorrectionLevel")) && + this._error + ) { + this._error = undefined; + } + } + + updated(changedProperties: PropertyValues) { + const canvas = this._canvas; + if ( + canvas && + this.data && + (changedProperties.has("data") || + changedProperties.has("scale") || + changedProperties.has("width") || + changedProperties.has("margin") || + changedProperties.has("maskPattern") || + changedProperties.has("errorCorrectionLevel") || + changedProperties.has("centerImage")) + ) { + const computedStyles = getComputedStyle(this); + + QRCode.toCanvas(canvas, this.data, { + errorCorrectionLevel: this.errorCorrectionLevel, + width: this.width, + scale: this.scale, + margin: this.margin, + maskPattern: this.maskPattern, + color: { + light: computedStyles.getPropertyValue("--card-background-color"), + dark: computedStyles.getPropertyValue("--primary-text-color"), + }, + }).catch((err) => { + this._error = err.message; + }); + + if (this.centerImage) { + const context = this._canvas!.getContext("2d"); + const imageObj = new Image(); + imageObj.src = this.centerImage; + imageObj.onload = () => { + context?.drawImage( + imageObj, + canvas.width * 0.375, + canvas.height * 0.375, + canvas.width / 4, + canvas.height / 4 + ); + }; + } + } + } + + render() { + if (!this.data) { + return nothing; + } + if (this._error) { + return html`${this._error}`; + } + return html``; + } + + static styles = css` + :host { + display: block; + } + `; +} diff --git a/src/components/ha-selector/ha-selector-number.ts b/src/components/ha-selector/ha-selector-number.ts index 3bc9451e1807..1d4d2b98d4d5 100644 --- a/src/components/ha-selector/ha-selector-number.ts +++ b/src/components/ha-selector/ha-selector-number.ts @@ -43,6 +43,22 @@ export class HaNumberSelector extends LitElement { this.selector.number?.min === undefined || this.selector.number?.max === undefined; + let sliderStep; + + if (!isBox) { + sliderStep = this.selector.number!.step ?? 1; + if (sliderStep === "any") { + sliderStep = 1; + // divide the range of the slider by 100 steps + const step = + (this.selector.number!.max! - this.selector.number!.min!) / 100; + // biggest step size is 1, round the step size to a division of 1 + while (sliderStep > step) { + sliderStep /= 10; + } + } + } + return html`
${!isBox @@ -52,12 +68,10 @@ export class HaNumberSelector extends LitElement { : ""} + return html`${this.hidePicker + ? nothing + : html``}
${description ? html`

${description}

` : ""} ${this._manifest @@ -522,6 +533,14 @@ export class HaServiceControl extends LitElement { defaultValue = field.selector.constant?.value; } + if ( + defaultValue == null && + field?.selector && + "boolean" in field.selector + ) { + defaultValue = false; + } + if (defaultValue != null) { data = { ...this._value?.data, @@ -727,6 +746,9 @@ export class HaServiceControl extends LitElement { margin: var(--service-control-padding, 0 16px); padding: 16px 0; } + :host([hidePicker]) p { + padding-top: 0; + } .checkbox-spacer { width: 32px; } diff --git a/src/components/ha-settings-row.ts b/src/components/ha-settings-row.ts index 5d97d39b9556..cae4ca158d4d 100644 --- a/src/components/ha-settings-row.ts +++ b/src/components/ha-settings-row.ts @@ -35,7 +35,12 @@ export class HaSettingsRow extends LitElement { align-items: center; } .body { - padding: 8px 16px 8px 0; + padding-top: 8px; + padding-bottom: 8px; + padding-left: 0; + padding-inline-start: 0; + padding-right: 16x; + padding-inline-end: 16px; overflow: hidden; display: var(--layout-vertical_-_display); flex-direction: var(--layout-vertical_-_flex-direction); diff --git a/src/components/ha-slider.ts b/src/components/ha-slider.ts index c3fb87005b20..5ea8d50b3321 100644 --- a/src/components/ha-slider.ts +++ b/src/components/ha-slider.ts @@ -11,6 +11,7 @@ export class HaSlider extends MdSlider { :host { --md-sys-color-primary: var(--primary-color); --md-sys-color-outline: var(--outline-color); + --md-sys-color-on-surface: var(--primary-text-color); --md-slider-handle-width: 14px; --md-slider-handle-height: 14px; min-width: 100px; diff --git a/src/components/ha-two-pane-top-app-bar-fixed.ts b/src/components/ha-two-pane-top-app-bar-fixed.ts index 995079aec0f8..df6477534c54 100644 --- a/src/components/ha-two-pane-top-app-bar-fixed.ts +++ b/src/components/ha-two-pane-top-app-bar-fixed.ts @@ -280,6 +280,8 @@ export abstract class TopAppBarBaseBase extends BaseElement { } #title { border-right: 1px solid rgba(255, 255, 255, 0.12); + border-inline-end: 1px solid rgba(255, 255, 255, 0.12); + border-inline-start: initial; box-sizing: border-box; flex: 0 0 var(--sidepane-width, 250px); width: var(--sidepane-width, 250px); @@ -290,6 +292,8 @@ export abstract class TopAppBarBaseBase extends BaseElement { } .pane { border-right: 1px solid var(--divider-color); + border-inline-end: 1px solid var(--divider-color); + border-inline-start: initial; box-sizing: border-box; display: flex; flex: 0 0 var(--sidepane-width, 250px); diff --git a/src/components/ha-valve-controls.ts b/src/components/ha-valve-controls.ts new file mode 100644 index 000000000000..ae3779595120 --- /dev/null +++ b/src/components/ha-valve-controls.ts @@ -0,0 +1,102 @@ +import { mdiStop, mdiValveClosed, mdiValveOpen } from "@mdi/js"; +import { CSSResultGroup, LitElement, html, css, nothing } from "lit"; +import { customElement, property } from "lit/decorators"; +import { classMap } from "lit/directives/class-map"; +import { supportsFeature } from "../common/entity/supports-feature"; +import { + ValveEntity, + ValveEntityFeature, + canClose, + canOpen, + canStop, +} from "../data/valve"; +import type { HomeAssistant } from "../types"; +import "./ha-icon-button"; + +@customElement("ha-valve-controls") +class HaValveControls extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public stateObj!: ValveEntity; + + protected render() { + if (!this.stateObj) { + return nothing; + } + + return html` +
+ + + + + +
+ `; + } + + private _onOpenTap(ev): void { + ev.stopPropagation(); + this.hass.callService("valve", "open_valve", { + entity_id: this.stateObj.entity_id, + }); + } + + private _onCloseTap(ev): void { + ev.stopPropagation(); + this.hass.callService("valve", "close_valve", { + entity_id: this.stateObj.entity_id, + }); + } + + private _onStopTap(ev): void { + ev.stopPropagation(); + this.hass.callService("valve", "stop_valve", { + entity_id: this.stateObj.entity_id, + }); + } + + static get styles(): CSSResultGroup { + return css` + :host { + display: block; + } + .state { + white-space: nowrap; + } + .hidden { + visibility: hidden !important; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-valve-controls": HaValveControls; + } +} diff --git a/src/components/media-player/ha-browse-media-tts.ts b/src/components/media-player/ha-browse-media-tts.ts index 39e36b60b7b5..cb10b053c421 100644 --- a/src/components/media-player/ha-browse-media-tts.ts +++ b/src/components/media-player/ha-browse-media-tts.ts @@ -62,7 +62,7 @@ class BrowseMediaTTS extends LitElement { this.hass.localize( "ui.components.media-browser.tts.example_message", { - name: this.hass.user?.name || "", + name: this.hass.user?.name || "Alice", } )} > diff --git a/src/components/trace/ha-trace-path-details.ts b/src/components/trace/ha-trace-path-details.ts index 46f4a7a23e1b..514377e61f4f 100644 --- a/src/components/trace/ha-trace-path-details.ts +++ b/src/components/trace/ha-trace-path-details.ts @@ -1,5 +1,12 @@ import { dump } from "js-yaml"; -import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { + css, + CSSResultGroup, + html, + LitElement, + nothing, + TemplateResult, +} from "lit"; import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time"; @@ -18,6 +25,12 @@ import { traceTabStyles } from "./trace-tab-styles"; import { HomeAssistant } from "../../types"; import type { NodeInfo } from "./hat-script-graph"; +const TRACE_PATH_TABS = [ + "step_config", + "changed_variables", + "logbook", +] as const; + @customElement("ha-trace-path-details") export class HaTracePathDetails extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -34,7 +47,7 @@ export class HaTracePathDetails extends LitElement { @property() public trackedNodes!: Record; - @state() private _view: "config" | "changed_variables" | "logbook" = "config"; + @state() private _view: (typeof TRACE_PATH_TABS)[number] = "step_config"; protected render(): TemplateResult { return html` @@ -43,23 +56,21 @@ export class HaTracePathDetails extends LitElement {
- ${[ - ["config", "Step Config"], - ["changed_variables", "Changed Variables"], - ["logbook", "Related logbook entries"], - ].map( - ([view, label]) => html` + ${TRACE_PATH_TABS.map( + (view) => html` ` )}
- ${this._view === "config" + ${this._view === "step_config" ? this._renderSelectedConfig() : this._view === "changed_variables" ? this._renderChangedVars() @@ -71,7 +82,9 @@ export class HaTracePathDetails extends LitElement { const paths = this.trace.trace; if (!this.selected?.path) { - return "Select a node on the left for more information."; + return this.hass!.localize( + "ui.panel.config.automation.trace.path.choose" + ); } // HACK: default choice node is not part of paths. We filter them out here by checking parent. @@ -82,12 +95,16 @@ export class HaTracePathDetails extends LitElement { ] as ChooseActionTraceStep[]; if (parentTraceInfo && parentTraceInfo[0]?.result?.choice === "default") { - return "The default action was executed because no options matched."; + return this.hass!.localize( + "ui.panel.config.automation.trace.path.default_action_executed" + ); } } if (!(this.selected.path in paths)) { - return "This node was not executed and so no further trace information is available."; + return this.hass!.localize( + "ui.panel.config.automation.trace.path.no_further_execution" + ); } const parts: TemplateResult[][] = []; @@ -115,29 +132,53 @@ export class HaTracePathDetails extends LitElement { trace as any; if (result?.enabled === false) { - return html`This node was disabled and skipped during execution so - no further trace information is available.`; + return html`${this.hass!.localize( + "ui.panel.config.automation.trace.path.disabled_step" + )}`; } return html` ${curPath === this.selected.path ? "" - : html`

${curPath.substr(this.selected.path.length + 1)}

`} - ${data.length === 1 ? "" : html`

Iteration ${idx + 1}

`} - Executed: - ${formatDateTimeWithSeconds( - new Date(timestamp), - this.hass.locale, - this.hass.config - )}
+ : html`

+ ${curPath.substring(this.selected.path.length + 1)} +

`} + ${data.length === 1 + ? nothing + : html`

+ ${this.hass!.localize( + "ui.panel.config.automation.trace.path.iteration", + { number: idx + 1 } + )} +

`} + ${this.hass!.localize( + "ui.panel.config.automation.trace.path.executed", + { + time: formatDateTimeWithSeconds( + new Date(timestamp), + this.hass.locale, + this.hass.config + ), + } + )} +
${result - ? html`Result: + ? html`${this.hass!.localize( + "ui.panel.config.automation.trace.path.result" + )}
${dump(result)}
` : error - ? html`
Error: ${error}
` - : ""} + ? html`
+ ${this.hass!.localize( + "ui.panel.config.automation.trace.path.error", + { + error: error, + } + )} +
` + : nothing} ${Object.keys(rest).length === 0 - ? "" + ? nothing : html`
${dump(rest)}
`} `; }) @@ -149,30 +190,49 @@ export class HaTracePathDetails extends LitElement { private _renderSelectedConfig() { if (!this.selected?.path) { - return ""; + return nothing; } const config = getDataFromPath(this.trace!.config, this.selected.path); return config ? html`` - : "Unable to find config"; + : this.hass!.localize( + "ui.panel.config.automation.trace.path.unable_to_find_config" + ); } private _renderChangedVars() { const paths = this.trace.trace; const data: ActionTraceStep[] = paths[this.selected.path]; + if (data === undefined) { + return html`
+ ${this.hass!.localize( + "ui.panel.config.automation.trace.path.step_not_executed" + )} +
`; + } + return html`
${data.map( (trace, idx) => html` - ${idx > 0 ? html`

Iteration ${idx + 1}

` : ""} + ${data.length > 1 + ? html`

+ ${this.hass!.localize( + "ui.panel.config.automation.trace.path.iteration", + { number: idx + 1 } + )} +

` + : ""} ${Object.keys(trace.changed_variables || {}).length === 0 - ? "No variables changed" - : html`
${dump(trace.changed_variables).trimRight()}
`} + ? this.hass!.localize( + "ui.panel.config.automation.trace.path.no_variables_changed" + ) + : html`
${dump(trace.changed_variables).trimEnd()}
`} ` )}
@@ -186,7 +246,11 @@ export class HaTracePathDetails extends LitElement { const index = trackedPaths.indexOf(this.selected.path); if (index === -1) { - return html`
Node not tracked.
`; + return html`
+ ${this.hass!.localize( + "ui.panel.config.automation.trace.path.step_not_executed" + )} +
`; } let entries: LogbookEntry[]; @@ -234,7 +298,9 @@ export class HaTracePathDetails extends LitElement { ` : html`
- No Logbook entries found for this step. + ${this.hass!.localize( + "ui.panel.config.automation.trace.path.no_logbook_entries" + )}
`; } diff --git a/src/data/action.ts b/src/data/action.ts index 6dea0b308fe0..2c5f2aa12578 100644 --- a/src/data/action.ts +++ b/src/data/action.ts @@ -5,6 +5,8 @@ import { mdiCallSplit, mdiCodeBraces, mdiDevices, + mdiDotsHorizontal, + mdiExcavator, mdiGestureDoubleTap, mdiHandBackRight, mdiPalette, @@ -13,10 +15,12 @@ import { mdiRoomService, mdiShuffleDisabled, mdiTimerOutline, + mdiTools, mdiTrafficLight, } from "@mdi/js"; +import { AutomationElementGroup } from "./automation"; -export const ACTION_TYPES = { +export const ACTION_ICONS = { condition: mdiAbTesting, delay: mdiTimerOutline, event: mdiGestureDoubleTap, @@ -34,6 +38,44 @@ export const ACTION_TYPES = { variables: mdiApplicationVariableOutline, } as const; -export const YAML_ONLY_ACTION_TYPES = new Set([ +export const YAML_ONLY_ACTION_TYPES = new Set([ "variables", ]); + +export const ACTION_GROUPS: AutomationElementGroup = { + device_id: {}, + helpers: { + icon: mdiTools, + members: {}, + }, + building_blocks: { + icon: mdiExcavator, + members: { + condition: {}, + delay: {}, + wait_template: {}, + wait_for_trigger: {}, + repeat: {}, + choose: {}, + if: {}, + stop: {}, + parallel: {}, + variables: {}, + }, + }, + other: { + icon: mdiDotsHorizontal, + members: { + event: {}, + service: {}, + }, + }, +} as const; + +export const SERVICE_PREFIX = "__SERVICE__"; + +export const isService = (key: string | undefined): boolean | undefined => + key?.startsWith(SERVICE_PREFIX); + +export const getService = (key: string): string => + key.substring(SERVICE_PREFIX.length); diff --git a/src/data/automation.ts b/src/data/automation.ts index f2cc6802a17e..1527822e7196 100644 --- a/src/data/automation.ts +++ b/src/data/automation.ts @@ -275,6 +275,10 @@ export interface ShorthandNotCondition extends ShorthandBaseCondition { not: Condition[]; } +export interface AutomationElementGroup { + [key: string]: { icon?: string; members?: AutomationElementGroup }; +} + export type Condition = | StateCondition | NumericStateCondition diff --git a/src/data/automation_i18n.ts b/src/data/automation_i18n.ts index 6cb4ec807011..aec2965cdf10 100644 --- a/src/data/automation_i18n.ts +++ b/src/data/automation_i18n.ts @@ -766,48 +766,38 @@ const tryDescribeCondition = ( // State Condition if (condition.condition === "state") { - let base = "Confirm"; if (!condition.entity_id) { - return `${base} state`; + return hass.localize( + `${conditionsTranslationBaseKey}.state.description.no_entity` + ); } + let attribute = ""; if (condition.attribute) { const stateObj = Array.isArray(condition.entity_id) ? hass.states[condition.entity_id[0]] : hass.states[condition.entity_id]; - base += ` ${computeAttributeNameDisplay( + attribute = computeAttributeNameDisplay( hass.localize, stateObj, hass.entities, condition.attribute - )} of`; + ); } + const entities: string[] = []; if (Array.isArray(condition.entity_id)) { - const entities: string[] = []; for (const entity of condition.entity_id.values()) { if (hass.states[entity]) { entities.push(computeStateName(hass.states[entity]) || entity); } } - if (entities.length !== 0) { - const entitiesString = - condition.match === "any" - ? formatListWithOrs(hass.locale, entities) - : formatListWithAnds(hass.locale, entities); - base += ` ${entitiesString} ${ - condition.entity_id.length > 1 ? "are" : "is" - }`; - } else { - // no entity_id or empty array - base += " an entity"; - } } else if (condition.entity_id) { - base += ` ${ + entities.push( hass.states[condition.entity_id] ? computeStateName(hass.states[condition.entity_id]) : condition.entity_id - } is`; + ); } const states: string[] = []; @@ -845,21 +835,27 @@ const tryDescribeCondition = ( ); } - if (states.length === 0) { - states.push("a state"); - } - - const statesString = formatListWithOrs(hass.locale, states); - base += ` ${statesString}`; - + let duration = ""; if (condition.for) { - const duration = describeDuration(hass.locale, condition.for); - if (duration) { - base += ` for ${duration}`; - } + duration = describeDuration(hass.locale, condition.for) || ""; } - return base; + return hass.localize( + `${conditionsTranslationBaseKey}.state.description.full`, + { + hasAttribute: attribute !== "" ? "true" : "false", + attribute: attribute, + numberOfEntities: entities.length, + entities: + condition.match === "any" + ? formatListWithOrs(hass.locale, entities) + : formatListWithAnds(hass.locale, entities), + numberOfStates: states.length, + states: formatListWithOrs(hass.locale, states), + hasDuration: duration !== "" ? "true" : "false", + duration: duration, + } + ); } // Numeric State Condition diff --git a/src/data/condition.ts b/src/data/condition.ts index 6e63cd58506c..d8c7af44fecc 100644 --- a/src/data/condition.ts +++ b/src/data/condition.ts @@ -3,16 +3,21 @@ import { mdiClockOutline, mdiCodeBraces, mdiDevices, + mdiDotsHorizontal, + mdiExcavator, mdiGateOr, mdiIdentifier, + mdiMapClock, mdiMapMarkerRadius, mdiNotEqualVariant, mdiNumeric, + mdiShape, mdiStateMachine, mdiWeatherSunny, } from "@mdi/js"; +import { AutomationElementGroup } from "./automation"; -export const CONDITION_TYPES = { +export const CONDITION_ICONS = { device: mdiDevices, and: mdiAmpersand, or: mdiGateOr, @@ -25,3 +30,22 @@ export const CONDITION_TYPES = { trigger: mdiIdentifier, zone: mdiMapMarkerRadius, }; + +export const CONDITION_GROUPS: AutomationElementGroup = { + device: {}, + entity: { icon: mdiShape, members: { state: {}, numeric_state: {} } }, + time_location: { + icon: mdiMapClock, + members: { sun: {}, time: {}, zone: {} }, + }, + building_blocks: { + icon: mdiExcavator, + members: { and: {}, or: {}, not: {} }, + }, + other: { + icon: mdiDotsHorizontal, + members: { + template: {}, + }, + }, +} as const; diff --git a/src/data/cover.ts b/src/data/cover.ts index 28ab3ebe1d52..046da65aa3b3 100644 --- a/src/data/cover.ts +++ b/src/data/cover.ts @@ -65,7 +65,7 @@ export function canOpen(stateObj: CoverEntity) { return false; } const assumedState = stateObj.attributes.assumed_state === true; - return (!isFullyOpen(stateObj) && !isOpening(stateObj)) || assumedState; + return assumedState || (!isFullyOpen(stateObj) && !isOpening(stateObj)); } export function canClose(stateObj: CoverEntity): boolean { @@ -73,7 +73,7 @@ export function canClose(stateObj: CoverEntity): boolean { return false; } const assumedState = stateObj.attributes.assumed_state === true; - return (!isFullyClosed(stateObj) && !isClosing(stateObj)) || assumedState; + return assumedState || (!isFullyClosed(stateObj) && !isClosing(stateObj)); } export function canStop(stateObj: CoverEntity): boolean { @@ -85,7 +85,7 @@ export function canOpenTilt(stateObj: CoverEntity): boolean { return false; } const assumedState = stateObj.attributes.assumed_state === true; - return !isFullyOpenTilt(stateObj) || assumedState; + return assumedState || !isFullyOpenTilt(stateObj); } export function canCloseTilt(stateObj: CoverEntity): boolean { @@ -93,7 +93,7 @@ export function canCloseTilt(stateObj: CoverEntity): boolean { return false; } const assumedState = stateObj.attributes.assumed_state === true; - return !isFullyClosedTilt(stateObj) || assumedState; + return assumedState || !isFullyClosedTilt(stateObj); } export function canStopTilt(stateObj: CoverEntity): boolean { diff --git a/src/data/entity_attributes.ts b/src/data/entity_attributes.ts index 3a07ae022a72..d7782e1dbfb2 100644 --- a/src/data/entity_attributes.ts +++ b/src/data/entity_attributes.ts @@ -75,6 +75,9 @@ export const DOMAIN_ATTRIBUTES_UNITS = { vacuum: { battery_level: "%", }, + valve: { + current_position: "%", + }, sensor: { battery_level: "%", }, diff --git a/src/data/integration.ts b/src/data/integration.ts index 151140bebd37..5c331c814a60 100644 --- a/src/data/integration.ts +++ b/src/data/integration.ts @@ -16,7 +16,9 @@ export type IntegrationType = | "helper" | "hub" | "service" - | "hardware"; + | "hardware" + | "entity" + | "system"; export interface IntegrationManifest { is_built_in: boolean; diff --git a/src/data/media-player.ts b/src/data/media-player.ts index deccb121dd41..ce869bfde5da 100644 --- a/src/data/media-player.ts +++ b/src/data/media-player.ts @@ -90,7 +90,7 @@ export const enum MediaPlayerEntityFeature { TURN_ON = 128, TURN_OFF = 256, PLAY_MEDIA = 512, - VOLUME_BUTTONS = 1024, + VOLUME_STEP = 1024, SELECT_SOURCE = 2048, STOP = 4096, CLEAR_PLAYLIST = 8192, diff --git a/src/data/script.ts b/src/data/script.ts index f0b5e7151b51..08910dc88fcb 100644 --- a/src/data/script.ts +++ b/src/data/script.ts @@ -52,6 +52,7 @@ export const serviceActionStruct: Describe = assign( target: optional(targetStruct), data: optional(object()), response_variable: optional(string()), + metadata: optional(object()), }) ); @@ -133,6 +134,7 @@ export interface ServiceAction extends BaseAction { target?: HassServiceTarget; data?: Record; response_variable?: string; + metadata?: Record; } export interface DeviceAction extends BaseAction { diff --git a/src/data/script_i18n.ts b/src/data/script_i18n.ts index 1ba30198bd3e..40c823bc862f 100644 --- a/src/data/script_i18n.ts +++ b/src/data/script_i18n.ts @@ -168,6 +168,18 @@ const tryDescribeAction = ( const service = hass.localize(`component.${domain}.services.${serviceName}.name`) || hass.services[domain][serviceName]?.name; + + if (config.metadata) { + return hass.localize( + `${actionTranslationBaseKey}.service.description.service_name`, + { + domain: domainToName(hass.localize, domain), + name: service || config.service, + targets: formatListWithAnds(hass.locale, targets), + } + ); + } + return hass.localize( `${actionTranslationBaseKey}.service.description.service_based_on_name`, { @@ -404,7 +416,9 @@ const tryDescribeAction = ( if (actionType === "device_action") { const config = action as DeviceAction; if (!config.device_id) { - return "Device action"; + return hass.localize( + `${actionTranslationBaseKey}.device_id.description.no_device` + ); } const localized = localizeDeviceAutomationAction( hass, diff --git a/src/data/todo.ts b/src/data/todo.ts index 15a13970665f..9af8ef0f4cc6 100644 --- a/src/data/todo.ts +++ b/src/data/todo.ts @@ -18,6 +18,8 @@ export interface TodoItem { uid: string; summary: string; status: TodoItemStatus; + description?: string | null; + due?: string | null; } export const enum TodoListEntityFeature { @@ -25,6 +27,9 @@ export const enum TodoListEntityFeature { DELETE_TODO_ITEM = 2, UPDATE_TODO_ITEM = 4, MOVE_TODO_ITEM = 8, + SET_DUE_DATE_ON_ITEM = 16, + SET_DUE_DATETIME_ON_ITEM = 32, + SET_DESCRIPTION_ON_ITEM = 64, } export const getTodoLists = (hass: HomeAssistant): TodoList[] => @@ -74,20 +79,30 @@ export const updateItem = ( hass.callService( "todo", "update_item", - { item: item.uid, rename: item.summary, status: item.status }, + { + item: item.uid, + rename: item.summary, + status: item.status, + description: item.description || null, + due_datetime: item.due?.includes("T") ? item.due : undefined, + due_date: item.due?.includes("T") ? undefined : item.due || null, + }, { entity_id } ); export const createItem = ( hass: HomeAssistant, entity_id: string, - summary: string + item: Omit ): Promise => hass.callService( "todo", "add_item", { - item: summary, + item: item.summary, + description: item.description || undefined, + due_datetime: item.due?.includes("T") ? item.due : undefined, + due_date: item.due?.includes("T") ? undefined : item.due, }, { entity_id } ); diff --git a/src/data/trigger.ts b/src/data/trigger.ts index 859595a78a65..c68fed612bce 100644 --- a/src/data/trigger.ts +++ b/src/data/trigger.ts @@ -4,13 +4,16 @@ import { mdiClockOutline, mdiCodeBraces, mdiDevices, + mdiDotsHorizontal, mdiGestureDoubleTap, + mdiMapClock, mdiMapMarker, mdiMapMarkerRadius, mdiMessageAlert, mdiMicrophoneMessage, mdiNfcVariant, mdiNumeric, + mdiShape, mdiStateMachine, mdiSwapHorizontal, mdiWeatherSunny, @@ -18,8 +21,9 @@ import { } from "@mdi/js"; import { mdiHomeAssistant } from "../resources/home-assistant-logo-svg"; +import { AutomationElementGroup } from "./automation"; -export const TRIGGER_TYPES = { +export const TRIGGER_ICONS = { calendar: mdiCalendar, device: mdiDevices, event: mdiGestureDoubleTap, @@ -38,3 +42,26 @@ export const TRIGGER_TYPES = { persistent_notification: mdiMessageAlert, zone: mdiMapMarkerRadius, }; + +export const TRIGGER_GROUPS: AutomationElementGroup = { + device: {}, + entity: { icon: mdiShape, members: { state: {}, numeric_state: {} } }, + time_location: { + icon: mdiMapClock, + members: { calendar: {}, sun: {}, time: {}, time_pattern: {}, zone: {} }, + }, + other: { + icon: mdiDotsHorizontal, + members: { + event: {}, + geo_location: {}, + homeassistant: {}, + mqtt: {}, + conversation: {}, + tag: {}, + template: {}, + webhook: {}, + persistent_notification: {}, + }, + }, +} as const; diff --git a/src/data/update.ts b/src/data/update.ts index cf13f58daf74..01443b522179 100644 --- a/src/data/update.ts +++ b/src/data/update.ts @@ -13,11 +13,13 @@ import { showAlertDialog } from "../dialogs/generic/show-dialog-box"; import { HomeAssistant } from "../types"; import { showToast } from "../util/toast"; -export const UPDATE_SUPPORT_INSTALL = 1; -export const UPDATE_SUPPORT_SPECIFIC_VERSION = 2; -export const UPDATE_SUPPORT_PROGRESS = 4; -export const UPDATE_SUPPORT_BACKUP = 8; -export const UPDATE_SUPPORT_RELEASE_NOTES = 16; +export enum UpdateEntityFeature { + INSTALL = 1, + SPECIFIC_VERSION = 2, + PROGRESS = 4, + BACKUP = 8, + RELEASE_NOTES = 16, +} interface UpdateEntityAttributes extends HassEntityAttributeBase { auto_update: boolean | null; @@ -35,7 +37,7 @@ export interface UpdateEntity extends HassEntityBase { } export const updateUsesProgress = (entity: UpdateEntity): boolean => - supportsFeature(entity, UPDATE_SUPPORT_PROGRESS) && + supportsFeature(entity, UpdateEntityFeature.PROGRESS) && typeof entity.attributes.in_progress === "number"; export const updateCanInstall = ( @@ -44,7 +46,7 @@ export const updateCanInstall = ( ): boolean => (entity.state === BINARY_STATE_ON || (showSkipped && Boolean(entity.attributes.skipped_version))) && - supportsFeature(entity, UPDATE_SUPPORT_INSTALL); + supportsFeature(entity, UpdateEntityFeature.INSTALL); export const updateIsInstalling = (entity: UpdateEntity): boolean => updateUsesProgress(entity) || !!entity.attributes.in_progress; @@ -176,7 +178,7 @@ export const computeUpdateStateDisplay = ( if (state === "on") { if (updateIsInstalling(stateObj)) { const supportsProgress = - supportsFeature(stateObj, UPDATE_SUPPORT_PROGRESS) && + supportsFeature(stateObj, UpdateEntityFeature.PROGRESS) && typeof attributes.in_progress === "number"; if (supportsProgress) { return hass.localize("ui.card.update.installing_with_progress", { diff --git a/src/data/valve.ts b/src/data/valve.ts new file mode 100644 index 000000000000..73f5d428ae18 --- /dev/null +++ b/src/data/valve.ts @@ -0,0 +1,85 @@ +import { + HassEntityAttributeBase, + HassEntityBase, +} from "home-assistant-js-websocket"; +import { UNAVAILABLE } from "./entity"; +import { stateActive } from "../common/entity/state_active"; +import { HomeAssistant } from "../types"; + +export const enum ValveEntityFeature { + OPEN = 1, + CLOSE = 2, + SET_POSITION = 4, + STOP = 8, +} + +export function isFullyOpen(stateObj: ValveEntity) { + if (stateObj.attributes.current_position !== undefined) { + return stateObj.attributes.current_position === 100; + } + return stateObj.state === "open"; +} + +export function isFullyClosed(stateObj: ValveEntity) { + if (stateObj.attributes.current_position !== undefined) { + return stateObj.attributes.current_position === 0; + } + return stateObj.state === "closed"; +} + +export function isOpening(stateObj: ValveEntity) { + return stateObj.state === "opening"; +} + +export function isClosing(stateObj: ValveEntity) { + return stateObj.state === "closing"; +} + +export function canOpen(stateObj: ValveEntity) { + if (stateObj.state === UNAVAILABLE) { + return false; + } + const assumedState = stateObj.attributes.assumed_state === true; + return assumedState || (!isFullyOpen(stateObj) && !isOpening(stateObj)); +} + +export function canClose(stateObj: ValveEntity): boolean { + if (stateObj.state === UNAVAILABLE) { + return false; + } + const assumedState = stateObj.attributes.assumed_state === true; + return assumedState || (!isFullyClosed(stateObj) && !isClosing(stateObj)); +} + +export function canStop(stateObj: ValveEntity): boolean { + return stateObj.state !== UNAVAILABLE; +} + +interface ValveEntityAttributes extends HassEntityAttributeBase { + current_position?: number; + position?: number; +} + +export interface ValveEntity extends HassEntityBase { + attributes: ValveEntityAttributes; +} + +export function computeValvePositionStateDisplay( + stateObj: ValveEntity, + hass: HomeAssistant, + position?: number +) { + const statePosition = stateActive(stateObj) + ? stateObj.attributes.current_position + : undefined; + + const currentPosition = position ?? statePosition; + + return currentPosition && currentPosition !== 100 + ? hass.formatEntityAttributeValue( + stateObj, + "current_position", + Math.round(currentPosition) + ) + : ""; +} diff --git a/src/data/zha.ts b/src/data/zha.ts index b3f7b084a708..560538497388 100644 --- a/src/data/zha.ts +++ b/src/data/zha.ts @@ -383,11 +383,13 @@ export const removeMembersFromGroup = ( export const addGroup = ( hass: HomeAssistant, groupName: string, + groupId?: number, membersToAdd?: ZHAGroupMember[] ): Promise => hass.callWS({ type: "zha/group/add", group_name: groupName, + group_id: groupId, members: membersToAdd, }); diff --git a/src/dialogs/area-filter/area-filter-dialog.ts b/src/dialogs/area-filter/area-filter-dialog.ts index 0a62bfbf275b..2dc7cacadcb2 100644 --- a/src/dialogs/area-filter/area-filter-dialog.ts +++ b/src/dialogs/area-filter/area-filter-dialog.ts @@ -207,7 +207,8 @@ export class DialogAreaFilter color: var(--disabled-text-color); } .handle { - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; } .actions { display: flex; diff --git a/src/dialogs/more-info/const.ts b/src/dialogs/more-info/const.ts index 80c5d5994fd8..65375a6f6d3d 100644 --- a/src/dialogs/more-info/const.ts +++ b/src/dialogs/more-info/const.ts @@ -27,6 +27,7 @@ export const DOMAINS_WITH_NEW_MORE_INFO = [ "lock", "siren", "switch", + "valve", "water_heater", ]; /** Domains with separate more info dialog. */ @@ -61,6 +62,7 @@ export const DOMAINS_WITH_MORE_INFO = [ "timer", "update", "vacuum", + "valve", "water_heater", "weather", ]; diff --git a/src/dialogs/more-info/controls/more-info-cover.ts b/src/dialogs/more-info/controls/more-info-cover.ts index f1f5e06e386c..a352002e4adb 100644 --- a/src/dialogs/more-info/controls/more-info-cover.ts +++ b/src/dialogs/more-info/controls/more-info-cover.ts @@ -42,7 +42,9 @@ class MoreInfoCover extends LitElement { protected willUpdate(changedProps: PropertyValues): void { super.willUpdate(changedProps); if (changedProps.has("stateObj") && this.stateObj) { - if (!this._mode) { + const entityId = this.stateObj.entity_id; + const oldEntityId = changedProps.get("stateObj")?.entity_id; + if (!this._mode || entityId !== oldEntityId) { this._mode = supportsFeature(this.stateObj, CoverEntityFeature.SET_POSITION) || supportsFeature(this.stateObj, CoverEntityFeature.SET_TILT_POSITION) diff --git a/src/dialogs/more-info/controls/more-info-media_player.ts b/src/dialogs/more-info/controls/more-info-media_player.ts index c779299333b8..c33dab198b19 100644 --- a/src/dialogs/more-info/controls/more-info-media_player.ts +++ b/src/dialogs/more-info/controls/more-info-media_player.ts @@ -81,7 +81,7 @@ class MoreInfoMediaPlayer extends LitElement { : ""}
${(supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_SET) || - supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_BUTTONS)) && + supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_STEP)) && stateActive(stateObj) ? html`
@@ -104,8 +104,9 @@ class MoreInfoMediaPlayer extends LitElement { : ""} ${supportsFeature( stateObj, - MediaPlayerEntityFeature.VOLUME_BUTTONS - ) + MediaPlayerEntityFeature.VOLUME_SET + ) || + supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_STEP) ? html`
` : ""} - ${supportsFeature(this.stateObj!, UPDATE_SUPPORT_RELEASE_NOTES) && + ${supportsFeature(this.stateObj!, UpdateEntityFeature.RELEASE_NOTES) && !this._error ? !this._releaseNotes ? html`
@@ -117,7 +113,7 @@ class MoreInfoUpdate extends LitElement { .content=${this.stateObj.attributes.release_summary} >` : ""} - ${supportsFeature(this.stateObj, UPDATE_SUPPORT_BACKUP) + ${supportsFeature(this.stateObj, UpdateEntityFeature.BACKUP) ? html`
`} - ${supportsFeature(this.stateObj, UPDATE_SUPPORT_INSTALL) + ${supportsFeature(this.stateObj, UpdateEntityFeature.INSTALL) ? html` { this._releaseNotes = result; @@ -186,7 +182,7 @@ class MoreInfoUpdate extends LitElement { } get _shouldCreateBackup(): boolean | null { - if (!supportsFeature(this.stateObj!, UPDATE_SUPPORT_BACKUP)) { + if (!supportsFeature(this.stateObj!, UpdateEntityFeature.BACKUP)) { return null; } const checkbox = this.shadowRoot?.querySelector("ha-checkbox"); @@ -206,7 +202,7 @@ class MoreInfoUpdate extends LitElement { } if ( - supportsFeature(this.stateObj!, UPDATE_SUPPORT_SPECIFIC_VERSION) && + supportsFeature(this.stateObj!, UpdateEntityFeature.SPECIFIC_VERSION) && this.stateObj!.attributes.latest_version ) { installData.version = this.stateObj!.attributes.latest_version; diff --git a/src/dialogs/more-info/controls/more-info-valve.ts b/src/dialogs/more-info/controls/more-info-valve.ts new file mode 100644 index 000000000000..f7bae2a9bef5 --- /dev/null +++ b/src/dialogs/more-info/controls/more-info-valve.ts @@ -0,0 +1,192 @@ +import { mdiMenu, mdiSwapVertical } from "@mdi/js"; +import { + CSSResultGroup, + LitElement, + PropertyValues, + css, + html, + nothing, +} from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { supportsFeature } from "../../../common/entity/supports-feature"; +import "../../../components/ha-attributes"; +import "../../../components/ha-icon-button-group"; +import "../../../components/ha-icon-button-toggle"; +import { + ValveEntity, + ValveEntityFeature, + computeValvePositionStateDisplay, +} from "../../../data/valve"; +import "../../../state-control/valve/ha-state-control-valve-buttons"; +import "../../../state-control/valve/ha-state-control-valve-position"; +import "../../../state-control/valve/ha-state-control-valve-toggle"; +import type { HomeAssistant } from "../../../types"; +import "../components/ha-more-info-state-header"; +import { moreInfoControlStyle } from "../components/more-info-control-style"; + +type Mode = "position" | "button"; + +@customElement("more-info-valve") +class MoreInfoValve extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public stateObj?: ValveEntity; + + @state() private _mode?: Mode; + + private _setMode(ev) { + this._mode = ev.currentTarget.mode; + } + + protected willUpdate(changedProps: PropertyValues): void { + super.willUpdate(changedProps); + if (changedProps.has("stateObj") && this.stateObj) { + const entityId = this.stateObj.entity_id; + const oldEntityId = changedProps.get("stateObj")?.entity_id; + if (!this._mode || entityId !== oldEntityId) { + this._mode = supportsFeature( + this.stateObj, + ValveEntityFeature.SET_POSITION + ) + ? "position" + : "button"; + } + } + } + + private get _stateOverride() { + const stateDisplay = this.hass.formatEntityState(this.stateObj!); + + const positionStateDisplay = computeValvePositionStateDisplay( + this.stateObj!, + this.hass + ); + + if (positionStateDisplay) { + return `${stateDisplay} ⸱ ${positionStateDisplay}`; + } + return stateDisplay; + } + + protected render() { + if (!this.hass || !this.stateObj) { + return nothing; + } + + const supportsPosition = supportsFeature( + this.stateObj, + ValveEntityFeature.SET_POSITION + ); + + const supportsOpenClose = + supportsFeature(this.stateObj, ValveEntityFeature.OPEN) || + supportsFeature(this.stateObj, ValveEntityFeature.CLOSE) || + supportsFeature(this.stateObj, ValveEntityFeature.STOP); + + const supportsOpenCloseWithoutStop = + supportsFeature(this.stateObj, ValveEntityFeature.OPEN) && + supportsFeature(this.stateObj, ValveEntityFeature.CLOSE) && + !supportsFeature(this.stateObj, ValveEntityFeature.STOP); + + return html` + +
+
+ ${ + this._mode === "position" + ? html` + ${supportsPosition + ? html` + + ` + : nothing} + ` + : nothing + } + ${ + this._mode === "button" + ? html` + ${supportsOpenCloseWithoutStop + ? html` + + ` + : supportsOpenClose + ? html` + + ` + : nothing} + ` + : nothing + } +
+ ${ + supportsPosition && supportsOpenClose + ? html` + + + + + ` + : nothing + } +
+
+ + `; + } + + static get styles(): CSSResultGroup { + return [ + moreInfoControlStyle, + css` + .main-control { + display: flex; + flex-direction: row; + align-items: center; + } + .main-control > * { + margin: 0 8px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "more-info-valve": MoreInfoValve; + } +} diff --git a/src/dialogs/more-info/state_more_info_control.ts b/src/dialogs/more-info/state_more_info_control.ts index 65a2e0a1a0d4..2be9b0877b89 100644 --- a/src/dialogs/more-info/state_more_info_control.ts +++ b/src/dialogs/more-info/state_more_info_control.ts @@ -35,6 +35,7 @@ const LAZY_LOADED_MORE_INFO_CONTROL = { timer: () => import("./controls/more-info-timer"), update: () => import("./controls/more-info-update"), vacuum: () => import("./controls/more-info-vacuum"), + valve: () => import("./controls/more-info-valve"), water_heater: () => import("./controls/more-info-water_heater"), weather: () => import("./controls/more-info-weather"), }; diff --git a/src/dialogs/update_backup/dialog-update-backup.ts b/src/dialogs/update_backup/dialog-update-backup.ts new file mode 100644 index 000000000000..5caa9a58417b --- /dev/null +++ b/src/dialogs/update_backup/dialog-update-backup.ts @@ -0,0 +1,92 @@ +import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { fireEvent } from "../../common/dom/fire_event"; +import "../../components/ha-button"; +import { createCloseHeading } from "../../components/ha-dialog"; +import { HomeAssistant } from "../../types"; +import { UpdateBackupDialogParams } from "./show-update-backup-dialog"; + +@customElement("dialog-update-backup") +class DialogBox extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @state() private _params?: UpdateBackupDialogParams; + + public async showDialog(params: UpdateBackupDialogParams): Promise { + this._params = params; + } + + protected render() { + if (!this._params) { + return nothing; + } + + return html` + +

${this.hass.localize("ui.dialogs.update_backup.text")}

+ + ${this.hass!.localize("ui.common.no")} + + + ${this.hass.localize("ui.dialogs.update_backup.create")} + +
+ `; + } + + private _no(): void { + if (this._params!.submit) { + this._params!.submit(false); + } + this.closeDialog(); + } + + private _yes(): void { + if (this._params!.submit) { + this._params!.submit(true); + } + this.closeDialog(); + } + + private _cancel(): void { + this._params?.cancel?.(); + this.closeDialog(); + } + + public closeDialog(): void { + this._params = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + static get styles(): CSSResultGroup { + return css` + p { + margin: 0; + color: var(--primary-text-color); + } + ha-dialog { + /* Place above other dialogs */ + --dialog-z-index: 104; + } + @media all and (min-width: 600px) { + ha-dialog { + --mdc-dialog-min-width: 400px; + } + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-update-backup": DialogBox; + } +} diff --git a/src/dialogs/update_backup/show-update-backup-dialog.ts b/src/dialogs/update_backup/show-update-backup-dialog.ts new file mode 100644 index 000000000000..fcb0aa7a4156 --- /dev/null +++ b/src/dialogs/update_backup/show-update-backup-dialog.ts @@ -0,0 +1,35 @@ +import { fireEvent } from "../../common/dom/fire_event"; + +export interface UpdateBackupDialogParams { + submit?: (response: boolean) => void; + cancel?: () => void; +} + +export const showUpdateBackupDialogParams = ( + element: HTMLElement, + dialogParams: UpdateBackupDialogParams +) => + new Promise((resolve) => { + const origCancel = dialogParams.cancel; + const origSubmit = dialogParams.submit; + + fireEvent(element, "show-dialog", { + dialogTag: "dialog-update-backup", + dialogImport: () => import("./dialog-update-backup"), + dialogParams: { + ...dialogParams, + cancel: () => { + resolve(null); + if (origCancel) { + origCancel(); + } + }, + submit: (response: boolean) => { + resolve(response); + if (origSubmit) { + origSubmit(response); + } + }, + }, + }); + }); diff --git a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts index 8f164875b72c..700c6e8ea977 100644 --- a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts +++ b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts @@ -668,7 +668,12 @@ export class HaVoiceCommandDialog extends LitElement { ha-button-menu { --mdc-theme-on-primary: var(--text-primary-color); --mdc-theme-primary: var(--primary-color); - margin: -8px 0 0 -8px; + margin-top: -8px; + margin-bottom: 0; + margin-right: 0; + margin-inline-end: 0; + margin-left: -8px; + margin-inline-start: -8px; } ha-button-menu ha-button { --mdc-theme-primary: var(--secondary-text-color); @@ -689,7 +694,7 @@ export class HaVoiceCommandDialog extends LitElement { height: 28px; margin-left: 4px; margin-inline-start: 4px; - margin-inline-end: 4px; + margin-inline-end: initial; direction: var(--direction); } ha-list-item { @@ -698,7 +703,7 @@ export class HaVoiceCommandDialog extends LitElement { ha-list-item ha-svg-icon { margin-left: 4px; margin-inline-start: 4px; - margin-inline-end: 4px; + margin-inline-end: initial; direction: var(--direction); display: block; } diff --git a/src/layouts/hass-tabs-subpage-data-table.ts b/src/layouts/hass-tabs-subpage-data-table.ts index f891f6b1f9b3..7d3e90d623f1 100644 --- a/src/layouts/hass-tabs-subpage-data-table.ts +++ b/src/layouts/hass-tabs-subpage-data-table.ts @@ -124,6 +124,12 @@ export class HaTabsSubpageDataTable extends LitElement { */ @property({ type: String }) public noDataText?: string; + /** + * Hides the data table and show an empty message. + * @type {Boolean} + */ + @property({ type: Boolean }) public empty = false; + @property() public route!: Route; /** @@ -198,56 +204,61 @@ export class HaTabsSubpageDataTable extends LitElement { .mainPage=${this.mainPage} .supervisor=${this.supervisor} > - ${!this.hideFilterMenu - ? html` -
- ${this.narrow + ${this.empty + ? html`
+ ${this.noDataText} +
` + : html`${!this.hideFilterMenu + ? html` +
+ ${this.narrow + ? html` +
+ ${this.numHidden || this.activeFilters + ? html`${this.numHidden || "!"}` + : ""} + +
+ ` + : ""} +
+ ` + : ""} + ${this.narrow + ? html` +
+ +
${headerToolbar}
+
+
+ ` + : ""} + + ${!this.narrow ? html` -
- ${this.numHidden || this.activeFilters - ? html`${this.numHidden || "!"}` - : ""} - +
+ +
${headerToolbar}
+
` - : ""} -
- ` - : ""} - ${this.narrow - ? html` -
- -
${headerToolbar}
-
-
- ` - : ""} - - ${!this.narrow - ? html` -
- -
${headerToolbar}
-
-
- ` - : html`
`} -
+ : html`
`} +
`} +
`; @@ -374,6 +385,16 @@ export class HaTabsSubpageDataTable extends LitElement { .filter-menu { position: relative; } + .center { + display: flex; + align-items: center; + justify-content: center; + text-align: center; + box-sizing: border-box; + height: 100%; + width: 100%; + padding: 16px; + } `; } } diff --git a/src/panels/calendar/dialog-calendar-event-detail.ts b/src/panels/calendar/dialog-calendar-event-detail.ts index 6172e79b4ca8..ee091eac1652 100644 --- a/src/panels/calendar/dialog-calendar-event-detail.ts +++ b/src/panels/calendar/dialog-calendar-event-detail.ts @@ -1,8 +1,8 @@ import "@material/mwc-button"; -import { mdiCalendarClock, mdiClose } from "@mdi/js"; +import { mdiCalendarClock } from "@mdi/js"; import { toDate } from "date-fns-tz"; import { addDays, isSameDay } from "date-fns/esm"; -import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { property, state } from "lit/decorators"; import { formatDate } from "../../common/datetime/format_date"; import { formatDateTime } from "../../common/datetime/format_date_time"; @@ -11,6 +11,7 @@ import { fireEvent } from "../../common/dom/fire_event"; import { isDate } from "../../common/string/is_date"; import "../../components/entity/state-info"; import "../../components/ha-date-input"; +import { createCloseHeading } from "../../components/ha-dialog"; import "../../components/ha-time-input"; import { CalendarEventMutableParams, @@ -65,15 +66,7 @@ class DialogCalendarEventDetail extends LitElement { @closed=${this.closeDialog} scrimClickAction escapeKeyAction - .heading=${html` -
${this._data!.summary}
- - `} + .heading=${createCloseHeading(this.hass, this._data!.summary)} >
${this._error diff --git a/src/panels/calendar/dialog-calendar-event-editor.ts b/src/panels/calendar/dialog-calendar-event-editor.ts index 2cd0bb0f5d36..e5925b1243e2 100644 --- a/src/panels/calendar/dialog-calendar-event-editor.ts +++ b/src/panels/calendar/dialog-calendar-event-editor.ts @@ -1,5 +1,4 @@ import "@material/mwc-button"; -import { mdiClose } from "@mdi/js"; import { formatInTimeZone, toDate } from "date-fns-tz"; import { addDays, @@ -9,7 +8,7 @@ import { startOfHour, } from "date-fns/esm"; import { HassEntity } from "home-assistant-js-websocket"; -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,23 +17,24 @@ import { supportsFeature } from "../../common/entity/supports-feature"; import { isDate } from "../../common/string/is_date"; import "../../components/entity/ha-entity-picker"; import "../../components/ha-date-input"; +import { createCloseHeading } from "../../components/ha-dialog"; import "../../components/ha-textarea"; import "../../components/ha-time-input"; import { CalendarEntityFeature, CalendarEventMutableParams, + RecurrenceRange, createCalendarEvent, deleteCalendarEvent, - RecurrenceRange, updateCalendarEvent, } from "../../data/calendar"; +import { TimeZone } from "../../data/translation"; import { haStyleDialog } from "../../resources/styles"; import { HomeAssistant } from "../../types"; import "../lovelace/components/hui-generic-entity-row"; import "./ha-recurrence-rule-editor"; import { showConfirmEventDialog } from "./show-confirm-event-dialog-box"; import { CalendarEventEditDialogParams } from "./show-dialog-calendar-event-editor"; -import { TimeZone } from "../../data/translation"; const CALENDAR_DOMAINS = ["calendar"]; @@ -142,19 +142,12 @@ class DialogCalendarEventEditor extends LitElement { @closed=${this.closeDialog} scrimClickAction escapeKeyAction - .heading=${html` -
- ${isCreate - ? this.hass.localize("ui.components.calendar.event.add") - : this._summary} -
- - `} + .heading=${createCloseHeading( + this.hass, + this.hass.localize( + `ui.components.calendar.event.${isCreate ? "add" : "edit"}` + ) + )} >
${this._error @@ -584,9 +577,11 @@ class DialogCalendarEventEditor extends LitElement { return [ haStyleDialog, css` - ha-dialog { - --mdc-dialog-min-width: min(600px, 95vw); - --mdc-dialog-max-width: min(600px, 95vw); + @media all and (min-width: 450px and min-height: 500px) { + ha-dialog { + --mdc-dialog-min-width: min(600px, 95vw); + --mdc-dialog-max-width: min(600px, 95vw); + } } state-info { line-height: 40px; diff --git a/src/panels/config/automation/action/ha-automation-action-row.ts b/src/panels/config/automation/action/ha-automation-action-row.ts index 2c114cd946a3..0e58c0e8b2b5 100644 --- a/src/panels/config/automation/action/ha-automation-action-row.ts +++ b/src/panels/config/automation/action/ha-automation-action-row.ts @@ -29,6 +29,8 @@ import { classMap } from "lit/directives/class-map"; import { storage } from "../../../../common/decorators/storage"; import { dynamicElement } from "../../../../common/dom/dynamic-element-directive"; import { fireEvent } from "../../../../common/dom/fire_event"; +import { computeDomain } from "../../../../common/entity/compute_domain"; +import { domainIconWithoutDefault } from "../../../../common/entity/domain_icon"; import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter"; import { handleStructError } from "../../../../common/structs/handle-errors"; import "../../../../components/ha-alert"; @@ -37,7 +39,7 @@ import "../../../../components/ha-card"; import "../../../../components/ha-expansion-panel"; import "../../../../components/ha-icon-button"; import type { HaYamlEditor } from "../../../../components/ha-yaml-editor"; -import { ACTION_TYPES, YAML_ONLY_ACTION_TYPES } from "../../../../data/action"; +import { ACTION_ICONS, YAML_ONLY_ACTION_TYPES } from "../../../../data/action"; import { AutomationClipboard } from "../../../../data/automation"; import { validateConfig } from "../../../../data/config"; import { fullEntitiesContext } from "../../../../data/context"; @@ -82,9 +84,9 @@ export const getType = (action: Action | undefined) => { if (["and", "or", "not"].some((key) => key in action)) { return "condition" as const; } - return Object.keys(ACTION_TYPES).find( + return Object.keys(ACTION_ICONS).find( (option) => option in action - ) as keyof typeof ACTION_TYPES; + ) as keyof typeof ACTION_ICONS; }; export interface ActionElement extends LitElement { @@ -190,7 +192,13 @@ export default class HaAutomationActionRow extends LitElement {

${capitalizeFirstLetter( describeAction(this.hass, this._entityReg, this.action) diff --git a/src/panels/config/automation/action/ha-automation-action.ts b/src/panels/config/automation/action/ha-automation-action.ts index 5c85b509c137..ce312a7bd399 100644 --- a/src/panels/config/automation/action/ha-automation-action.ts +++ b/src/panels/config/automation/action/ha-automation-action.ts @@ -1,57 +1,26 @@ import "@material/mwc-button"; -import type { ActionDetail } from "@material/mwc-list"; -import { - mdiArrowDown, - mdiArrowUp, - mdiContentPaste, - mdiDrag, - mdiPlus, -} from "@mdi/js"; +import { mdiArrowDown, mdiArrowUp, mdiDrag, mdiPlus } from "@mdi/js"; import deepClone from "deep-clone-simple"; -import { - CSSResultGroup, - LitElement, - PropertyValues, - css, - html, - nothing, -} from "lit"; +import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import memoizeOne from "memoize-one"; import type { SortableEvent } from "sortablejs"; import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { stringCompare } from "../../../../common/string/compare"; -import { LocalizeFunc } from "../../../../common/translations/localize"; import "../../../../components/ha-button"; -import "../../../../components/ha-button-menu"; -import type { HaSelect } from "../../../../components/ha-select"; import "../../../../components/ha-svg-icon"; -import { ACTION_TYPES } from "../../../../data/action"; -import { AutomationClipboard } from "../../../../data/automation"; +import { getService, isService } from "../../../../data/action"; +import type { AutomationClipboard } from "../../../../data/automation"; import { Action } from "../../../../data/script"; import { sortableStyles } from "../../../../resources/ha-sortable-style"; import type { SortableInstance } from "../../../../resources/sortable"; -import { Entries, HomeAssistant } from "../../../../types"; +import { HomeAssistant } from "../../../../types"; +import { + PASTE_VALUE, + showAddAutomationElementDialog, +} from "../show-add-automation-element-dialog"; import type HaAutomationActionRow from "./ha-automation-action-row"; import { getType } from "./ha-automation-action-row"; -import "./types/ha-automation-action-activate_scene"; -import "./types/ha-automation-action-choose"; -import "./types/ha-automation-action-condition"; -import "./types/ha-automation-action-delay"; -import "./types/ha-automation-action-device_id"; -import "./types/ha-automation-action-event"; -import "./types/ha-automation-action-if"; -import "./types/ha-automation-action-parallel"; -import "./types/ha-automation-action-play_media"; -import "./types/ha-automation-action-repeat"; -import "./types/ha-automation-action-service"; -import "./types/ha-automation-action-stop"; -import "./types/ha-automation-action-wait_for_trigger"; -import "./types/ha-automation-action-wait_template"; - -const PASTE_VALUE = "__paste__"; @customElement("ha-automation-action") export default class HaAutomationAction extends LitElement { @@ -150,42 +119,27 @@ export default class HaAutomationAction extends LitElement { ` )}

- +
- ${this._clipboard?.action - ? html` - ${this.hass.localize( - "ui.panel.config.automation.editor.actions.paste" - )} - (${this.hass.localize( - `ui.panel.config.automation.editor.actions.type.${ - getType(this._clipboard.action) || "unknown" - }.label` - )}) - ` - : nothing} - ${this._processedTypes(this.hass.localize).map( - ([opt, label, icon]) => html` - - ${label} - ` - )} - + + + +
`; } @@ -213,6 +167,44 @@ export default class HaAutomationAction extends LitElement { } } + private _addActionDialog() { + showAddAutomationElementDialog(this, { + type: "action", + add: this._addAction, + clipboardItem: getType(this._clipboard?.action), + }); + } + + private _addActionBuildingBlockDialog() { + showAddAutomationElementDialog(this, { + type: "action", + add: this._addAction, + clipboardItem: getType(this._clipboard?.action), + group: "building_blocks", + }); + } + + private _addAction = (action: string) => { + let actions: Action[]; + if (action === PASTE_VALUE) { + actions = this.actions.concat(deepClone(this._clipboard!.action)); + } else if (isService(action)) { + actions = this.actions.concat({ + service: getService(action), + metadata: {}, + }); + } else { + const elClass = customElements.get( + `ha-automation-action-${action}` + ) as CustomElementConstructor & { defaultConfig: Action }; + actions = this.actions.concat( + elClass ? { ...elClass.defaultConfig } : { [action]: {} } + ); + } + this._focusLastActionOnChange = true; + fireEvent(this, "value-changed", { value: actions }); + }; + private async _enterReOrderMode(ev: CustomEvent) { if (this.nested) return; ev.stopPropagation(); @@ -258,25 +250,6 @@ export default class HaAutomationAction extends LitElement { return this._actionKeys.get(action)!; } - private _addAction(ev: CustomEvent) { - const action = (ev.currentTarget as HaSelect).items[ev.detail.index].value; - - let actions: Action[]; - if (action === PASTE_VALUE) { - actions = this.actions.concat(deepClone(this._clipboard!.action)); - } else { - const elClass = customElements.get( - `ha-automation-action-${action}` - ) as CustomElementConstructor & { defaultConfig: Action }; - - actions = this.actions.concat( - elClass ? { ...elClass.defaultConfig } : { [action]: {} } - ); - } - this._focusLastActionOnChange = true; - fireEvent(this, "value-changed", { value: actions }); - } - private _moveUp(ev) { const index = (ev.target as any).index; const newIndex = index - 1; @@ -328,22 +301,6 @@ export default class HaAutomationAction extends LitElement { }); } - private _processedTypes = memoizeOne( - (localize: LocalizeFunc): [string, string, string][] => - (Object.entries(ACTION_TYPES) as Entries) - .map( - ([action, icon]) => - [ - action, - localize( - `ui.panel.config.automation.editor.actions.type.${action}.label` - ), - icon, - ] as [string, string, string] - ) - .sort((a, b) => stringCompare(a[1], b[1], this.hass.locale.language)) - ); - static get styles(): CSSResultGroup { return [ sortableStyles, @@ -363,13 +320,19 @@ export default class HaAutomationAction extends LitElement { overflow: hidden; } .handle { - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; padding: 12px; } .handle ha-svg-icon { pointer-events: none; height: 24px; } + .buttons { + display: flex; + flex-wrap: wrap; + gap: 8px; + } `, ]; } 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 9051fbb75cd0..5c0ee0763790 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 @@ -543,7 +543,8 @@ export class HaChooseAction extends LitElement implements ActionElement { padding: 0 16px 16px 16px; } .handle { - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; padding: 12px; } .handle ha-svg-icon { diff --git a/src/panels/config/automation/action/types/ha-automation-action-condition.ts b/src/panels/config/automation/action/types/ha-automation-action-condition.ts index c72da97aac7e..d62176812d8b 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-condition.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-condition.ts @@ -7,7 +7,7 @@ import type { LocalizeFunc } from "../../../../../common/translations/localize"; import "../../../../../components/ha-select"; import type { HaSelect } from "../../../../../components/ha-select"; import type { Condition } from "../../../../../data/automation"; -import { CONDITION_TYPES } from "../../../../../data/condition"; +import { CONDITION_ICONS } from "../../../../../data/condition"; import { Entries, HomeAssistant } from "../../../../../types"; import "../../condition/ha-automation-condition-editor"; import type { ActionElement } from "../ha-automation-action-row"; @@ -55,7 +55,7 @@ export class HaConditionAction extends LitElement implements ActionElement { private _processedTypes = memoizeOne( (localize: LocalizeFunc): [string, string, string][] => - (Object.entries(CONDITION_TYPES) as Entries) + (Object.entries(CONDITION_ICONS) as Entries) .map( ([condition, icon]) => [ diff --git a/src/panels/config/automation/action/types/ha-automation-action-repeat.ts b/src/panels/config/automation/action/types/ha-automation-action-repeat.ts index 890133d25019..7a1ad36e8156 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-repeat.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-repeat.ts @@ -9,6 +9,7 @@ import type { HomeAssistant } from "../../../../../types"; import "../ha-automation-action"; import type { ActionElement } from "../ha-automation-action-row"; +import { isTemplate } from "../../../../../common/string/has-template"; import type { LocalizeFunc } from "../../../../../common/translations/localize"; import "../../../../../components/ha-form/ha-form"; import type { SchemaUnion } from "../../../../../components/ha-form/types"; @@ -32,7 +33,12 @@ export class HaRepeatAction extends LitElement implements ActionElement { } private _schema = memoizeOne( - (localize: LocalizeFunc, type: string, reOrderMode: boolean) => + ( + localize: LocalizeFunc, + type: string, + reOrderMode: boolean, + template: boolean + ) => [ { name: "type", @@ -53,7 +59,9 @@ export class HaRepeatAction extends LitElement implements ActionElement { { name: "count", required: true, - selector: { number: { mode: "box", min: 1 } }, + selector: template + ? ({ template: {} } as const) + : ({ number: { mode: "box", min: 1 } } as const), }, ] as const) : []), @@ -89,10 +97,13 @@ export class HaRepeatAction extends LitElement implements ActionElement { const schema = this._schema( this.hass.localize, type ?? "count", - this.reOrderMode + this.reOrderMode, + "count" in action && typeof action.count === "string" + ? isTemplate(action.count) + : false ); const data = { ...action, type }; - return html` ; + + @query("ha-dialog") private _dialog?: HaDialog; + + private _fullScreen = false; + + @state() private _width?: number; + + @state() private _height?: number; + + public showDialog(params): void { + this._params = params; + this._group = params.group; + if (this._params?.type === "action") { + this.hass.loadBackendTranslation("services"); + this._fetchManifests(); + } + this._fullScreen = matchMedia( + "all and (max-width: 450px), all and (max-height: 500px)" + ).matches; + } + + public closeDialog(): void { + if (this._params) { + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + this._height = undefined; + this._width = undefined; + this._params = undefined; + this._group = undefined; + this._prev = undefined; + this._filter = ""; + this._manifests = undefined; + this._domains = undefined; + } + + private _convertToItem = ( + key: string, + options, + type: AddAutomationElementDialogParams["type"], + localize: LocalizeFunc + ): ListItem => ({ + group: Boolean(options.members), + key, + name: localize( + // @ts-ignore + `ui.panel.config.automation.editor.${type}s.${ + options.members ? "groups" : "type" + }.${key}.label` + ), + description: localize( + // @ts-ignore + `ui.panel.config.automation.editor.${type}s.${ + options.members ? "groups" : "type" + }.${key}.description${options.members ? "" : ".picker"}` + ), + icon: options.icon || TYPES[type].icons[key], + }); + + private _getFilteredItems = memoizeOne( + ( + type: AddAutomationElementDialogParams["type"], + root: AddAutomationElementDialogParams["root"], + group: string | undefined, + filter: string, + localize: LocalizeFunc, + services: HomeAssistant["services"], + manifests?: DomainManifestLookup + ): ListItem[] => { + const groups: AutomationElementGroup = group + ? isService(group) + ? {} + : TYPES[type].groups[group].members! + : TYPES[type].groups; + + if (type === "condition" && group === "other" && !root) { + groups.trigger = {}; + } + + const flattenGroups = (grp: AutomationElementGroup) => + Object.entries(grp).map(([key, options]) => + options.members + ? flattenGroups(options.members) + : this._convertToItem(key, options, type, localize) + ); + + const items = flattenGroups(groups).flat(); + + if (type === "action") { + items.push(...this._services(localize, services, manifests, group)); + } + + const options: IFuseOptions = { + keys: ["key", "name", "description"], + isCaseSensitive: false, + minMatchCharLength: Math.min(filter.length, 2), + threshold: 0.2, + }; + const fuse = new Fuse(items, options); + return fuse.search(filter).map((result) => result.item); + } + ); + + private _getGroupItems = memoizeOne( + ( + type: AddAutomationElementDialogParams["type"], + root: AddAutomationElementDialogParams["root"], + group: string | undefined, + domains: Set | undefined, + localize: LocalizeFunc, + services: HomeAssistant["services"], + manifests?: DomainManifestLookup + ): ListItem[] => { + if (type === "action" && isService(group)) { + const result = this._services(localize, services, manifests, group); + if (group === `${SERVICE_PREFIX}media_player`) { + result.unshift(this._convertToItem("play_media", {}, type, localize)); + } + return result; + } + + const groups: AutomationElementGroup = group + ? TYPES[type].groups[group].members! + : TYPES[type].groups; + + if (type === "condition" && group === "other" && !root) { + groups.trigger = {}; + } + + const result = Object.entries(groups).map(([key, options]) => + this._convertToItem(key, options, type, localize) + ); + + if (type === "action") { + if (!this._group) { + result.unshift( + ...this._serviceGroups( + localize, + services, + manifests, + domains, + undefined + ) + ); + } else if (this._group === "helpers") { + result.unshift( + ...this._serviceGroups( + localize, + services, + manifests, + domains, + "helper" + ) + ); + } else if (this._group === "other") { + result.unshift( + ...this._serviceGroups( + localize, + services, + manifests, + domains, + "other" + ) + ); + } + } + + return result.sort((a, b) => { + if (a.group && b.group) { + return 0; + } + if (a.group && !b.group) { + return 1; + } + if (!a.group && b.group) { + return -1; + } + return stringCompare(a.name, b.name, this.hass.locale.language); + }); + } + ); + + private _serviceGroups = ( + localize: LocalizeFunc, + services: HomeAssistant["services"], + manifests: DomainManifestLookup | undefined, + domains: Set | undefined, + type: "helper" | "other" | undefined + ): ListItem[] => { + if (!services || !manifests) { + return []; + } + const result: ListItem[] = []; + Object.keys(services).forEach((domain) => { + const manifest = manifests[domain]; + const domainUsed = !domains ? true : domains.has(domain); + if ( + (type === undefined && + (ENTITY_DOMAINS_MAIN.has(domain) || + (manifest?.integration_type === "entity" && + domainUsed && + !ENTITY_DOMAINS_OTHER.has(domain)))) || + (type === "helper" && manifest?.integration_type === "helper") || + (type === "other" && + !ENTITY_DOMAINS_MAIN.has(domain) && + (ENTITY_DOMAINS_OTHER.has(domain) || + (!domainUsed && manifest?.integration_type === "entity") || + !["helper", "entity"].includes(manifest?.integration_type || ""))) + ) { + const icon = domainIconWithoutDefault(domain); + result.push({ + group: true, + icon, + image: !icon + ? brandsUrl({ + domain, + type: "icon", + darkOptimized: this.hass.themes?.darkMode, + }) + : undefined, + key: `${SERVICE_PREFIX}${domain}`, + name: domainToName(localize, domain, manifest), + description: "", + }); + } + }); + return result.sort((a, b) => + stringCompare(a.name, b.name, this.hass.locale.language) + ); + }; + + private _services = memoizeOne( + ( + localize: LocalizeFunc, + services: HomeAssistant["services"], + manifests: DomainManifestLookup | undefined, + group?: string + ): ListItem[] => { + if (!services) { + return []; + } + const result: ListItem[] = []; + + let domain: string | undefined; + + if (isService(group)) { + domain = getService(group!); + } + + const addDomain = (dmn: string) => { + const services_keys = Object.keys(services[dmn]); + + for (const service of services_keys) { + const icon = domainIconWithoutDefault(dmn); + result.push({ + group: false, + icon, + image: !icon + ? brandsUrl({ + domain: dmn, + type: "icon", + darkOptimized: this.hass.themes?.darkMode, + }) + : undefined, + key: `${SERVICE_PREFIX}${dmn}.${service}`, + name: `${domain ? "" : `${domainToName(localize, dmn)}: `}${ + this.hass.localize(`component.${dmn}.services.${service}.name`) || + services[dmn][service]?.name || + service + }`, + description: + this.hass.localize( + `component.${domain}.services.${service}.description` + ) || services[dmn][service]?.description, + }); + } + }; + + if (domain) { + addDomain(domain); + return result.sort((a, b) => + stringCompare(a.name, b.name, this.hass.locale.language) + ); + } + + if (group && !["helpers", "other"].includes(group)) { + return []; + } + + Object.keys(services) + .sort() + .forEach((dmn) => { + const manifest = manifests?.[dmn]; + if (group === "helpers" && manifest?.integration_type !== "helper") { + return; + } + if ( + group === "other" && + (ENTITY_DOMAINS_OTHER.has(dmn) || + ["helper", "entity"].includes(manifest?.integration_type || "")) + ) { + return; + } + addDomain(dmn); + }); + + return result; + } + ); + + private async _fetchManifests() { + const manifests = {}; + const fetched = await fetchIntegrationManifests(this.hass); + for (const manifest of fetched) { + manifests[manifest.domain] = manifest; + } + this._manifests = manifests; + } + + protected _opened(): void { + // Store the width and height so that when we search, box doesn't jump + const boundingRect = + this.shadowRoot!.querySelector("mwc-list")?.getBoundingClientRect(); + this._width = boundingRect?.width; + this._height = boundingRect?.height; + } + + protected willUpdate(changedProperties: PropertyValues): void { + if ( + this._params?.type === "action" && + changedProperties.has("hass") && + changedProperties.get("hass")?.states !== this.hass.states + ) { + const domains = new Set(Object.keys(this.hass.states).map(computeDomain)); + if (!deepEqual(domains, this._domains)) { + this._domains = domains; + } + } + } + + protected render() { + if (!this._params) { + return nothing; + } + + const items = this._filter + ? this._getFilteredItems( + this._params.type, + this._params.root, + this._group, + this._filter, + this.hass.localize, + this.hass.services, + this._manifests + ) + : this._getGroupItems( + this._params.type, + this._params.root, + this._group, + this._domains, + this.hass.localize, + this.hass.services, + this._manifests + ); + + const groupName = isService(this._group) + ? domainToName( + this.hass.localize, + getService(this._group!), + this._manifests?.[getService(this._group!)] + ) + : this.hass.localize( + // @ts-ignore + `ui.panel.config.automation.editor.${this._params.type}s.groups.${this._group}.label` + ); + + return html` + +
+ + ${this._group + ? groupName + : this.hass.localize( + `ui.panel.config.automation.editor.${this._params.type}s.add` + )} + ${this._group && this._group !== this._params.group + ? html`` + : html``} + + +
+ + ${this._params.clipboardItem && + !this._filter && + (!this._group || + items.find((item) => item.key === this._params!.clipboardItem)) + ? html` + ${this.hass.localize( + `ui.panel.config.automation.editor.${this._params.type}s.paste` + )} + ${this.hass.localize( + // @ts-ignore + `ui.panel.config.automation.editor.${this._params.type}s.type.${this._params.clipboardItem}.label` + )} + + +
  • ` + : ""} + ${repeat( + items, + (item) => item.key, + (item) => html` + + ${item.name} + ${item.description} + ${item.icon + ? html`` + : html``} + ${item.group + ? html`` + : html``} + + ` + )} +
    +
    + `; + } + + private _back() { + this._dialog!.scrollToPos(0, 0); + if (this._filter) { + this._filter = ""; + return; + } + if (this._prev) { + this._group = this._prev; + this._prev = undefined; + return; + } + this._group = undefined; + } + + private _selected(ev) { + if (!shouldHandleRequestSelectedEvent(ev)) { + return; + } + this._dialog!.scrollToPos(0, 0); + const item = ev.currentTarget; + if (item.group) { + this._prev = this._group; + this._group = item.value; + return; + } + this._params!.add(item.value); + this.closeDialog(); + } + + private _filterChanged(ev) { + this._filter = ev.detail.value; + } + + static get styles(): CSSResultGroup { + return [ + haStyle, + haStyleDialog, + css` + ha-dialog { + --dialog-content-padding: 0; + --mdc-dialog-max-height: 60vh; + } + @media all and (min-width: 550px) { + ha-dialog { + --mdc-dialog-min-width: 500px; + } + } + ha-icon-next { + width: 24px; + } + mwc-list { + max-height: 670px; + max-width: 100vw; + } + search-input { + display: block; + margin: 0 16px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "add-automation-element-dialog": DialogAddAutomationElement; + } +} diff --git a/src/panels/config/automation/condition/ha-automation-condition-row.ts b/src/panels/config/automation/condition/ha-automation-condition-row.ts index 7e8bb4e270a3..1b51a9d278c1 100644 --- a/src/panels/config/automation/condition/ha-automation-condition-row.ts +++ b/src/panels/config/automation/condition/ha-automation-condition-row.ts @@ -29,7 +29,7 @@ import "../../../../components/ha-icon-button"; import type { AutomationClipboard } from "../../../../data/automation"; import { Condition, testCondition } from "../../../../data/automation"; import { describeCondition } from "../../../../data/automation_i18n"; -import { CONDITION_TYPES } from "../../../../data/condition"; +import { CONDITION_ICONS } from "../../../../data/condition"; import { validateConfig } from "../../../../data/config"; import { fullEntitiesContext } from "../../../../data/context"; import { EntityRegistryEntry } from "../../../../data/entity_registry"; @@ -123,7 +123,7 @@ export default class HaAutomationConditionRow extends LitElement {

    ${capitalizeFirstLetter( describeCondition(this.condition, this.hass, this._entityReg) diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts index f562d1220354..ecf4f8823770 100644 --- a/src/panels/config/automation/condition/ha-automation-condition.ts +++ b/src/panels/config/automation/condition/ha-automation-condition.ts @@ -1,25 +1,18 @@ import "@material/mwc-button"; -import type { ActionDetail } from "@material/mwc-list"; -import { - mdiArrowDown, - mdiArrowUp, - mdiContentPaste, - mdiDrag, - mdiPlus, -} from "@mdi/js"; +import { mdiArrowDown, mdiArrowUp, mdiDrag, mdiPlus } from "@mdi/js"; import deepClone from "deep-clone-simple"; import { - css, CSSResultGroup, - html, LitElement, - nothing, PropertyValues, + css, + html, + nothing, } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import memoizeOne from "memoize-one"; import type { SortableEvent } from "sortablejs"; +import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-button"; import "../../../../components/ha-button-menu"; @@ -28,30 +21,15 @@ import type { AutomationClipboard, Condition, } from "../../../../data/automation"; -import type { Entries, HomeAssistant } from "../../../../types"; -import "./ha-automation-condition-row"; -import type HaAutomationConditionRow from "./ha-automation-condition-row"; -// Uncommenting these and this element doesn't load -// import "./types/ha-automation-condition-not"; -// import "./types/ha-automation-condition-or"; -import { storage } from "../../../../common/decorators/storage"; -import { stringCompare } from "../../../../common/string/compare"; -import type { LocalizeFunc } from "../../../../common/translations/localize"; -import type { HaSelect } from "../../../../components/ha-select"; -import { CONDITION_TYPES } from "../../../../data/condition"; import { sortableStyles } from "../../../../resources/ha-sortable-style"; import type { SortableInstance } from "../../../../resources/sortable"; -import "./types/ha-automation-condition-and"; -import "./types/ha-automation-condition-device"; -import "./types/ha-automation-condition-numeric_state"; -import "./types/ha-automation-condition-state"; -import "./types/ha-automation-condition-sun"; -import "./types/ha-automation-condition-template"; -import "./types/ha-automation-condition-time"; -import "./types/ha-automation-condition-trigger"; -import "./types/ha-automation-condition-zone"; - -const PASTE_VALUE = "__paste__"; +import type { HomeAssistant } from "../../../../types"; +import { + PASTE_VALUE, + showAddAutomationElementDialog, +} from "../show-add-automation-element-dialog"; +import "./ha-automation-condition-row"; +import type HaAutomationConditionRow from "./ha-automation-condition-row"; @customElement("ha-automation-condition") export default class HaAutomationCondition extends LitElement { @@ -197,43 +175,70 @@ export default class HaAutomationCondition extends LitElement { ` )}

    - +
    - ${this._clipboard?.condition - ? html` - ${this.hass.localize( - "ui.panel.config.automation.editor.conditions.paste" - )} - (${this.hass.localize( - `ui.panel.config.automation.editor.conditions.type.${this._clipboard.condition.condition}.label` - )}) - ` - : nothing} - ${this._processedTypes(this.hass.localize).map( - ([opt, label, icon]) => html` - - ${label} - ` - )} - + + + +
    `; } + private _addConditionDialog() { + showAddAutomationElementDialog(this, { + type: "condition", + add: this._addCondition, + root: !this.nested, + clipboardItem: this._clipboard?.condition?.condition, + }); + } + + private _addConditionBuildingBlockDialog() { + showAddAutomationElementDialog(this, { + type: "condition", + add: this._addCondition, + clipboardItem: this._clipboard?.condition?.condition, + group: "building_blocks", + }); + } + + private _addCondition = (value) => { + let conditions: Condition[]; + if (value === PASTE_VALUE) { + conditions = this.conditions.concat( + deepClone(this._clipboard!.condition) + ); + } else { + const condition = value as Condition["condition"]; + const elClass = customElements.get( + `ha-automation-condition-${condition}` + ) as CustomElementConstructor & { + defaultConfig: Omit; + }; + conditions = this.conditions.concat({ + condition: condition as any, + ...elClass.defaultConfig, + }); + } + this._focusLastConditionOnChange = true; + fireEvent(this, "value-changed", { value: conditions }); + }; + private async _enterReOrderMode(ev: CustomEvent) { if (this.nested) return; ev.stopPropagation(); @@ -282,32 +287,6 @@ export default class HaAutomationCondition extends LitElement { return this._conditionKeys.get(condition)!; } - private _addCondition(ev: CustomEvent) { - const value = (ev.currentTarget as HaSelect).items[ev.detail.index].value; - - let conditions: Condition[]; - if (value === PASTE_VALUE) { - conditions = this.conditions.concat( - deepClone(this._clipboard!.condition) - ); - } else { - const condition = value as Condition["condition"]; - - const elClass = customElements.get( - `ha-automation-condition-${condition}` - ) as CustomElementConstructor & { - defaultConfig: Omit; - }; - - conditions = this.conditions.concat({ - condition: condition as any, - ...elClass.defaultConfig, - }); - } - this._focusLastConditionOnChange = true; - fireEvent(this, "value-changed", { value: conditions }); - } - private _moveUp(ev) { const index = (ev.target as any).index; const newIndex = index - 1; @@ -361,22 +340,6 @@ export default class HaAutomationCondition extends LitElement { }); } - private _processedTypes = memoizeOne( - (localize: LocalizeFunc): [string, string, string][] => - (Object.entries(CONDITION_TYPES) as Entries) - .map( - ([condition, icon]) => - [ - condition, - localize( - `ui.panel.config.automation.editor.conditions.type.${condition}.label` - ), - icon, - ] as [string, string, string] - ) - .sort((a, b) => stringCompare(a[1], b[1], this.hass.locale.language)) - ); - static get styles(): CSSResultGroup { return [ sortableStyles, @@ -396,13 +359,19 @@ export default class HaAutomationCondition extends LitElement { overflow: hidden; } .handle { - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; padding: 12px; } .handle ha-svg-icon { pointer-events: none; height: 24px; } + .buttons { + display: flex; + flex-wrap: wrap; + gap: 8px; + } `, ]; } diff --git a/src/panels/config/automation/condition/types/ha-automation-condition-device.ts b/src/panels/config/automation/condition/types/ha-automation-condition-device.ts index 71568fe02c10..4593a5f70123 100644 --- a/src/panels/config/automation/condition/types/ha-automation-condition-device.ts +++ b/src/panels/config/automation/condition/types/ha-automation-condition-device.ts @@ -168,6 +168,7 @@ export class HaDeviceCondition extends LitElement { } ha-form { + display: block; margin-top: 24px; } `; diff --git a/src/panels/config/automation/ha-automation-editor.ts b/src/panels/config/automation/ha-automation-editor.ts index 2c6429d642e1..c8ca54c3d7ee 100644 --- a/src/panels/config/automation/ha-automation-editor.ts +++ b/src/panels/config/automation/ha-automation-editor.ts @@ -486,7 +486,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { value.valid ? "" : html`${this.hass.localize( - `ui.panel.config.automation.editor.${key}s.header` + `ui.panel.config.automation.editor.${key}s.name` )}: ${value.error}
    ` ); diff --git a/src/panels/config/automation/ha-automation-picker.ts b/src/panels/config/automation/ha-automation-picker.ts index 2e0c91708691..7fe54ec1f818 100644 --- a/src/panels/config/automation/ha-automation-picker.ts +++ b/src/panels/config/automation/ha-automation-picker.ts @@ -7,11 +7,19 @@ import { mdiPlay, mdiPlayCircleOutline, mdiPlus, + mdiRobotHappy, mdiStopCircleOutline, mdiTransitConnection, } from "@mdi/js"; import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; -import { CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { + css, + CSSResultGroup, + html, + LitElement, + nothing, + TemplateResult, +} from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { differenceInDays } from "date-fns/esm"; @@ -295,6 +303,7 @@ class HaAutomationPicker extends LitElement { .activeFilters=${this._activeFilters} .columns=${this._columns(this.narrow, this.hass.locale)} .data=${this._automations(this.automations, this._filteredAutomations)} + .empty=${!this.automations.length} @row-click=${this._handleRowClicked} .noDataText=${this.hass.localize( "ui.panel.config.automation.picker.no_automations" @@ -318,6 +327,36 @@ class HaAutomationPicker extends LitElement { @related-changed=${this._relatedFilterChanged} > + ${!this.automations.length + ? html`
    + +

    + ${this.hass.localize( + "ui.panel.config.automation.picker.empty_header" + )} +

    +

    + ${this.hass.localize( + "ui.panel.config.automation.picker.empty_text_1" + )} +

    +

    + ${this.hass.localize( + "ui.panel.config.automation.picker.empty_text_2", + { user: this.hass.user?.name || "Alice" } + )} +

    + + + ${this.hass.localize("ui.panel.config.common.learn_more")} + + +
    ` + : nothing} ${this._traces === undefined - ? html`
    Loading…
    ` + ? html`
    + ${this.hass!.localize("ui.common.loading")} +
    ` : this._traces.length === 0 - ? html`
    No traces found
    ` + ? html`
    + ${this.hass!.localize( + "ui.panel.config.automation.trace.no_traces_found" + )} +
    ` : this._trace === undefined ? "" : html` @@ -230,20 +240,17 @@ export class HaAutomationTrace extends LitElement {
    - ${[ - ["details", "Step Details"], - ["timeline", "Trace Timeline"], - ["logbook", "Related logbook entries"], - ["config", "Automation Config"], - ].map( - ([view, label]) => html` + ${TABS.map( + (view) => html` ` )} @@ -257,7 +264,9 @@ export class HaAutomationTrace extends LitElement { })} @click=${this._showTab} > - Blueprint Config + ${this.hass!.localize( + `ui.panel.config.automation.trace.tabs.blueprint_config` + )} ` : ""} @@ -265,7 +274,7 @@ export class HaAutomationTrace extends LitElement { ${this._selected === undefined || this._logbookEntries === undefined || trackedNodes === undefined - ? "" + ? nothing : this._view === "details" ? html` ` - : this._view === "config" + : this._view === "automation_config" ? html`
    + ${!ensureArray(this.config.trigger)?.length + ? html`

    + ${this.hass.localize( + "ui.panel.config.automation.editor.triggers.description" + )} +

    ` + : nothing} (${this.hass.localize("ui.common.optional")})
    + ${!ensureArray(this.config.condition)?.length + ? html`

    + ${this.hass.localize( + "ui.panel.config.automation.editor.conditions.description", + { user: this.hass.user?.name || "Alice" } + )} +

    ` + : nothing}
    + ${!ensureArray(this.config.action)?.length + ? html`

    + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.description" + )} +

    ` + : nothing} void; + clipboardItem: string | undefined; + root?: boolean; + group?: string; +} +const loadDialog = () => import("./add-automation-element-dialog"); + +export const showAddAutomationElementDialog = ( + element: HTMLElement, + dialogParams: AddAutomationElementDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "add-automation-element-dialog", + dialogImport: loadDialog, + dialogParams, + }); +}; diff --git a/src/panels/config/automation/trigger/ha-automation-trigger-row.ts b/src/panels/config/automation/trigger/ha-automation-trigger-row.ts index 128f7288befd..5a4acb43c6c4 100644 --- a/src/panels/config/automation/trigger/ha-automation-trigger-row.ts +++ b/src/panels/config/automation/trigger/ha-automation-trigger-row.ts @@ -37,7 +37,7 @@ import { describeTrigger } from "../../../../data/automation_i18n"; import { validateConfig } from "../../../../data/config"; import { fullEntitiesContext } from "../../../../data/context"; import { EntityRegistryEntry } from "../../../../data/entity_registry"; -import { TRIGGER_TYPES } from "../../../../data/trigger"; +import { TRIGGER_ICONS } from "../../../../data/trigger"; import { showAlertDialog, showConfirmationDialog, @@ -150,7 +150,7 @@ export default class HaAutomationTriggerRow extends LitElement {

    ${describeTrigger(this.trigger, this.hass, this._entityReg)}

    diff --git a/src/panels/config/automation/trigger/ha-automation-trigger.ts b/src/panels/config/automation/trigger/ha-automation-trigger.ts index 3be0e591619e..90467f61e0b8 100644 --- a/src/panels/config/automation/trigger/ha-automation-trigger.ts +++ b/src/panels/config/automation/trigger/ha-automation-trigger.ts @@ -1,59 +1,25 @@ import "@material/mwc-button"; -import type { ActionDetail } from "@material/mwc-list"; -import { - mdiArrowDown, - mdiArrowUp, - mdiContentPaste, - mdiDrag, - mdiPlus, -} from "@mdi/js"; +import { mdiArrowDown, mdiArrowUp, mdiDrag, mdiPlus } from "@mdi/js"; import deepClone from "deep-clone-simple"; -import { - CSSResultGroup, - LitElement, - PropertyValues, - css, - html, - nothing, -} from "lit"; +import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import memoizeOne from "memoize-one"; import type { SortableEvent } from "sortablejs"; import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { stringCompare } from "../../../../common/string/compare"; -import type { LocalizeFunc } from "../../../../common/translations/localize"; import "../../../../components/ha-button"; import "../../../../components/ha-button-menu"; -import type { HaSelect } from "../../../../components/ha-select"; import "../../../../components/ha-svg-icon"; import { AutomationClipboard, Trigger } from "../../../../data/automation"; -import { TRIGGER_TYPES } from "../../../../data/trigger"; import { sortableStyles } from "../../../../resources/ha-sortable-style"; import type { SortableInstance } from "../../../../resources/sortable"; -import { Entries, HomeAssistant } from "../../../../types"; +import { HomeAssistant } from "../../../../types"; import "./ha-automation-trigger-row"; import type HaAutomationTriggerRow from "./ha-automation-trigger-row"; -import "./types/ha-automation-trigger-calendar"; -import "./types/ha-automation-trigger-conversation"; -import "./types/ha-automation-trigger-device"; -import "./types/ha-automation-trigger-event"; -import "./types/ha-automation-trigger-geo_location"; -import "./types/ha-automation-trigger-homeassistant"; -import "./types/ha-automation-trigger-mqtt"; -import "./types/ha-automation-trigger-numeric_state"; -import "./types/ha-automation-trigger-persistent_notification"; -import "./types/ha-automation-trigger-state"; -import "./types/ha-automation-trigger-sun"; -import "./types/ha-automation-trigger-tag"; -import "./types/ha-automation-trigger-template"; -import "./types/ha-automation-trigger-time"; -import "./types/ha-automation-trigger-time_pattern"; -import "./types/ha-automation-trigger-webhook"; -import "./types/ha-automation-trigger-zone"; - -const PASTE_VALUE = "__paste__"; +import { + PASTE_VALUE, + showAddAutomationElementDialog, +} from "../show-add-automation-element-dialog"; @customElement("ha-automation-trigger") export default class HaAutomationTrigger extends LitElement { @@ -147,47 +113,48 @@ export default class HaAutomationTrigger extends LitElement { ` )} - - - - - ${this._clipboard?.trigger - ? html` - ${this.hass.localize( - "ui.panel.config.automation.editor.triggers.paste" - )} - (${this.hass.localize( - `ui.panel.config.automation.editor.triggers.type.${this._clipboard.trigger.platform}.label` - )}) - ` - : nothing} - ${this._processedTypes(this.hass.localize).map( - ([opt, label, icon]) => html` - - ${label} - ` - )} - + + `; } + private _addTriggerDialog() { + showAddAutomationElementDialog(this, { + type: "trigger", + add: this._addTrigger, + clipboardItem: this._clipboard?.trigger?.platform, + }); + } + + private _addTrigger = (value: string) => { + let triggers: Trigger[]; + if (value === PASTE_VALUE) { + triggers = this.triggers.concat(deepClone(this._clipboard!.trigger)); + } else { + const platform = value as Trigger["platform"]; + const elClass = customElements.get( + `ha-automation-trigger-${platform}` + ) as CustomElementConstructor & { + defaultConfig: Omit; + }; + triggers = this.triggers.concat({ + platform: platform as any, + ...elClass.defaultConfig, + }); + } + this._focusLastTriggerOnChange = true; + fireEvent(this, "value-changed", { value: triggers }); + }; + protected updated(changedProps: PropertyValues) { super.updated(changedProps); @@ -261,30 +228,6 @@ export default class HaAutomationTrigger extends LitElement { return this._triggerKeys.get(action)!; } - private _addTrigger(ev: CustomEvent) { - const value = (ev.currentTarget as HaSelect).items[ev.detail.index].value; - - let triggers: Trigger[]; - if (value === PASTE_VALUE) { - triggers = this.triggers.concat(deepClone(this._clipboard!.trigger)); - } else { - const platform = value as Trigger["platform"]; - - const elClass = customElements.get( - `ha-automation-trigger-${platform}` - ) as CustomElementConstructor & { - defaultConfig: Omit; - }; - - triggers = this.triggers.concat({ - platform: platform as any, - ...elClass.defaultConfig, - }); - } - this._focusLastTriggerOnChange = true; - fireEvent(this, "value-changed", { value: triggers }); - } - private _moveUp(ev) { const index = (ev.target as any).index; const newIndex = index - 1; @@ -336,22 +279,6 @@ export default class HaAutomationTrigger extends LitElement { }); } - private _processedTypes = memoizeOne( - (localize: LocalizeFunc): [string, string, string][] => - (Object.entries(TRIGGER_TYPES) as Entries) - .map( - ([action, icon]) => - [ - action, - localize( - `ui.panel.config.automation.editor.triggers.type.${action}.label` - ), - icon, - ] as [string, string, string] - ) - .sort((a, b) => stringCompare(a[1], b[1], this.hass.locale.language)) - ); - static get styles(): CSSResultGroup { return [ sortableStyles, @@ -371,7 +298,8 @@ export default class HaAutomationTrigger extends LitElement { overflow: hidden; } .handle { - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; padding: 12px; } .handle ha-svg-icon { diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts index 8b3a63575220..1b94ff6138b2 100644 --- a/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts +++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts @@ -174,6 +174,7 @@ export class HaDeviceTrigger extends LitElement { } ha-form { + display: block; margin-top: 24px; } `; diff --git a/src/panels/config/dashboard/ha-config-updates.ts b/src/panels/config/dashboard/ha-config-updates.ts index 9b654a5b3185..e12e77609626 100644 --- a/src/panels/config/dashboard/ha-config-updates.ts +++ b/src/panels/config/dashboard/ha-config-updates.ts @@ -109,9 +109,11 @@ class HaConfigUpdates extends SubscribeMixin(LitElement) { ${this.narrow && entity.attributes.in_progress ? html`` : ""} ` : html`` : ""} @@ -191,6 +196,8 @@ class HaConfigUpdates extends SubscribeMixin(LitElement) { } ha-circular-progress.absolute { position: absolute; + width: 40px; + height: 40px; } state-badge.updating { opacity: 0.5; diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index c586252c7d13..ca7c4fde9847 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -363,8 +363,8 @@ export class HaConfigDeviceDashboard extends LitElement { sortable: true, filterable: true, type: "numeric", - width: narrow ? "95px" : "15%", - maxWidth: "95px", + width: narrow ? "105px" : "15%", + maxWidth: "105px", valueColumn: "battery_level", template: (device) => { const batteryEntityPair = device.battery_entity; diff --git a/src/panels/config/entities/entity-registry-settings-editor.ts b/src/panels/config/entities/entity-registry-settings-editor.ts index 86e1405aa438..9e7213e41475 100644 --- a/src/panels/config/entities/entity-registry-settings-editor.ts +++ b/src/panels/config/entities/entity-registry-settings-editor.ts @@ -118,10 +118,12 @@ const OVERRIDE_DEVICE_CLASSES = { "carbon_monoxide", "moisture", ], // Alarm + ["connectivity"], // Connectivity + ["update"], // Update ], }; -const SWITCH_AS_DOMAINS = ["cover", "fan", "light", "lock", "siren"]; +const SWITCH_AS_DOMAINS = ["cover", "fan", "light", "lock", "siren", "valve"]; const PRECISIONS = [0, 1, 2, 3, 4, 5, 6]; diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index 76cb5e43c91f..f2e121e4ce08 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -74,7 +74,7 @@ export interface EntityRow extends StateEntity { entity?: HassEntity; unavailable: boolean; restored: boolean; - status: string; + status: string | undefined; area?: string; localized_platform: string; } @@ -429,7 +429,13 @@ export class HaConfigEntities extends LitElement { ? localize("ui.panel.config.entities.picker.status.unavailable") : entry.disabled_by ? localize("ui.panel.config.entities.picker.status.disabled") - : localize("ui.panel.config.entities.picker.status.ok"), + : entry.hidden_by + ? localize("ui.panel.config.entities.picker.status.hidden") + : entry.readonly + ? localize( + "ui.panel.config.entities.picker.status.readonly" + ) + : undefined, }); } diff --git a/src/panels/config/helpers/forms/ha-input_select-form.ts b/src/panels/config/helpers/forms/ha-input_select-form.ts index e65f951e4bb2..e8be0fe50418 100644 --- a/src/panels/config/helpers/forms/ha-input_select-form.ts +++ b/src/panels/config/helpers/forms/ha-input_select-form.ts @@ -285,7 +285,8 @@ class HaInputSelectForm extends LitElement { margin-bottom: 8px; } .handle { - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; padding-right: 12px; } .handle ha-svg-icon { diff --git a/src/panels/config/integrations/dialog-add-integration.ts b/src/panels/config/integrations/dialog-add-integration.ts index 14b1ed581c01..65edfbfccf67 100644 --- a/src/panels/config/integrations/dialog-add-integration.ts +++ b/src/panels/config/integrations/dialog-add-integration.ts @@ -3,21 +3,22 @@ import "@material/mwc-list/mwc-list"; import Fuse, { IFuseOptions } from "fuse.js"; import { HassConfig } from "home-assistant-js-websocket"; import { - css, - html, LitElement, PropertyValues, TemplateResult, + css, + html, nothing, } from "lit"; import { customElement, state } from "lit/decorators"; +import { ifDefined } from "lit/directives/if-defined"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { fireEvent } from "../../../common/dom/fire_event"; import { - protocolIntegrationPicked, PROTOCOL_INTEGRATIONS, + protocolIntegrationPicked, } from "../../../common/integrations/protocolIntegrationPicked"; import { navigate } from "../../../common/navigate"; import { caseInsensitiveStringCompare } from "../../../common/string/compare"; @@ -34,10 +35,10 @@ import { import { Brand, Brands, - findIntegration, - getIntegrationDescriptions, Integration, Integrations, + findIntegration, + getIntegrationDescriptions, } from "../../../data/integrations"; import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow"; import { @@ -339,7 +340,9 @@ class AddIntegrationDialog extends LitElement { !("integrations" in integration) && !this._flowsInProgress?.length ) { - return "What type of device is it?"; + return this.hass.localize( + "ui.panel.config.integrations.what_device_type" + ); } if ( integration && @@ -347,9 +350,11 @@ class AddIntegrationDialog extends LitElement { !("integrations" in integration) && this._flowsInProgress?.length ) { - return "Want to add these discovered devices?"; + return this.hass.localize( + "ui.panel.config.integrations.confirm_add_discovered" + ); } - return "What do you want to add?"; + return this.hass.localize("ui.panel.config.integrations.what_to_add"); } private _renderIntegration( @@ -424,8 +429,7 @@ class AddIntegrationDialog extends LitElement { private _renderAll(integrations?: IntegrationListItem[]): TemplateResult { return html` ${integrations - ? html` + ? html` ${this._manifest?.integration_type ? this.hass.localize( - `ui.panel.config.integrations.integration_page.entries_${this._manifest?.integration_type}` + `ui.panel.config.integrations.integration_page.entries_${this._manifest.integration_type}` ) : this.hass.localize( `ui.panel.config.integrations.integration_page.entries` @@ -507,7 +507,7 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { ${this._manifest?.integration_type ? this.hass.localize( - `ui.panel.config.integrations.integration_page.add_${this._manifest?.integration_type}` + `ui.panel.config.integrations.integration_page.add_${this._manifest.integration_type}` ) : this.hass.localize( `ui.panel.config.integrations.integration_page.add_entry` diff --git a/src/panels/config/integrations/integration-panels/zha/zha-add-devices-page.ts b/src/panels/config/integrations/integration-panels/zha/zha-add-devices-page.ts index 0201e8e4fc1e..baae1a21cf75 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-add-devices-page.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-add-devices-page.ts @@ -1,5 +1,4 @@ import "@material/mwc-button"; -import "@polymer/paper-input/paper-textarea"; import { css, CSSResultGroup, @@ -20,6 +19,7 @@ import { haStyle } from "../../../../../resources/styles"; import { HomeAssistant, Route } from "../../../../../types"; import { zhaTabs } from "./zha-config-dashboard"; import "./zha-device-pairing-status-card"; +import "../../../../../components/ha-textarea"; @customElement("zha-add-devices-page") class ZHAAddDevicesPage extends LitElement { @@ -146,13 +146,13 @@ class ZHAAddDevicesPage extends LitElement { `} ${this._showLogs - ? html` - ` + ` : ""} `; @@ -165,13 +165,6 @@ class ZHAAddDevicesPage extends LitElement { private _handleMessage(message: any): void { if (message.type === LOG_OUTPUT) { this._formattedEvents += message.log_entry.message + "\n"; - if (this.shadowRoot) { - const paperTextArea = this.shadowRoot.querySelector("paper-textarea"); - if (paperTextArea) { - const textArea = (paperTextArea.inputElement as any).textarea; - textArea.scrollTop = textArea.scrollHeight; - } - } } if (message.type && DEVICE_MESSAGE_TYPES.includes(message.type)) { this._discoveredDevices[message.device_info.ieee] = message.device_info; @@ -266,6 +259,9 @@ class ZHAAddDevicesPage extends LitElement { color: grey; padding-left: 16px; } + ha-textarea { + width: 100%; + } `, ]; } diff --git a/src/panels/config/integrations/integration-panels/zha/zha-add-group-page.ts b/src/panels/config/integrations/integration-panels/zha/zha-add-group-page.ts index 5cd32c78da32..367485563c1b 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-add-group-page.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-add-group-page.ts @@ -1,6 +1,4 @@ import "@material/mwc-button"; -import "@polymer/paper-input/paper-input"; -import type { PaperInputElement } from "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; import { customElement, property, state, query } from "lit/decorators"; import type { HASSDomEvent } from "../../../../../common/dom/fire_event"; @@ -14,8 +12,9 @@ import { ZHAGroup, } from "../../../../../data/zha"; import "../../../../../layouts/hass-subpage"; -import type { ValueChangedEvent, HomeAssistant } from "../../../../../types"; +import type { HomeAssistant } from "../../../../../types"; import "../../../ha-config-section"; +import "../../../../../components/ha-textfield"; import "./zha-device-endpoint-data-table"; import type { ZHADeviceEndpointDataTable } from "./zha-device-endpoint-data-table"; @@ -31,6 +30,8 @@ export class ZHAAddGroupPage extends LitElement { @state() private _groupName = ""; + @state() private _groupId?: string; + @query("zha-device-endpoint-data-table", true) private _zhaDevicesDataTable!: ZHADeviceEndpointDataTable; @@ -66,14 +67,23 @@ export class ZHAAddGroupPage extends LitElement { "ui.panel.config.zha.groups.create_group_details" )}

    - + >
    + +
    ${this.hass.localize("ui.panel.config.zha.groups.add_members")} @@ -131,7 +141,15 @@ export class ZHAAddGroupPage extends LitElement { const memberParts = member.split("_"); return { ieee: memberParts[0], endpoint_id: memberParts[1] }; }); - const group: ZHAGroup = await addGroup(this.hass, this._groupName, members); + const groupId = this._groupId + ? parseInt(this._groupId as string, 10) + : undefined; + const group: ZHAGroup = await addGroup( + this.hass, + this._groupName, + groupId, + members + ); this._selectedDevicesToAdd = []; this._processingAdd = false; this._groupName = ""; @@ -139,9 +157,12 @@ export class ZHAAddGroupPage extends LitElement { navigate(`/config/zha/group/${group.group_id}`, { replace: true }); } - private _handleNameChange(ev: ValueChangedEvent) { - const target = ev.currentTarget as PaperInputElement; - this._groupName = target.value || ""; + private _handleGroupIdChange(event) { + this._groupId = event.target.value; + } + + private _handleNameChange(event) { + this._groupName = event.target.value || ""; } static get styles(): CSSResultGroup { diff --git a/src/panels/config/integrations/integration-panels/zha/zha-cluster-attributes.ts b/src/panels/config/integrations/integration-panels/zha/zha-cluster-attributes.ts index b5b408794031..b0575c42f9c7 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-cluster-attributes.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-cluster-attributes.ts @@ -1,5 +1,4 @@ import "@material/mwc-list/mwc-list-item"; -import "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, @@ -15,6 +14,7 @@ import "../../../../../components/buttons/ha-call-service-button"; import "../../../../../components/buttons/ha-progress-button"; import "../../../../../components/ha-card"; import "../../../../../components/ha-select"; +import "../../../../../components/ha-textfield"; import { forwardHaptic } from "../../../../../data/haptics"; import { Attribute, @@ -27,11 +27,7 @@ import { import { haStyle } from "../../../../../resources/styles"; import { HomeAssistant } from "../../../../../types"; import { formatAsPaddedHex } from "./functions"; -import { - ChangeEvent, - ItemSelectedEvent, - SetAttributeServiceData, -} from "./types"; +import { ItemSelectedEvent, SetAttributeServiceData } from "./types"; @customElement("zha-cluster-attributes") export class ZHAClusterAttributes extends LitElement { @@ -101,24 +97,28 @@ export class ZHAClusterAttributes extends LitElement { private _renderAttributeInteractions(): TemplateResult { return html`
    - + @change=${this._onAttributeValueChanged} + .placeholder=${this.hass!.localize( + "ui.panel.config.zha.common.value" + )} + >
    - + @change=${this._onManufacturerCodeOverrideChanged} + .placeholder=${this.hass!.localize( + "ui.panel.config.zha.common.value" + )} + >
    - + >
    - + > - -
    - ${this.hass.localize("ui.panel.config.zwave_js.dashboard.header")} -
    - -
    - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.introduction" - )} -
    - ${this._network && - this._status === "connected" && - (this._network?.controller.inclusion_state === - InclusionState.Including || - this._network?.controller.inclusion_state === - InclusionState.Excluding) - ? html` - - ${this.hass.localize( - `ui.panel.config.zwave_js.common.in_progress_inclusion_exclusion` + ${this._network && + this._status === "connected" && + (this._network?.controller.inclusion_state === + InclusionState.Including || + this._network?.controller.inclusion_state === + InclusionState.Excluding) + ? html` + + ${this.hass.localize( + `ui.panel.config.zwave_js.common.in_progress_inclusion_exclusion` + )} + - - - ` - : ""} - ${this._network - ? html` - -
    -
    -
    - ${this._status === "disconnected" - ? html`` - : html` - - `} -
    - ${this._status !== "disconnected" - ? html` -
    - ${this.hass.localize( - "ui.panel.config.zwave_js.common.network" - )} - ${this.hass.localize( - `ui.panel.config.zwave_js.network_status.${this._status}` - )}
    - - ${this.hass.localize( - `ui.panel.config.zwave_js.dashboard.devices`, - { - count: - this._network.controller.nodes.length, - } - )} - ${notReadyDevices > 0 - ? html`(${this.hass.localize( - `ui.panel.config.zwave_js.dashboard.not_ready`, - { count: notReadyDevices } - )})` - : ""} - -
    - ` - : ``} -
    -
    - -
    - -
    -
    - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.driver_version" - )}: - - ${this._network.client.driver_version} -
    -
    - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.server_version" - )}: - - ${this._network.client.server_version} -
    -
    - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.home_id" - )}: - - ${this._network.controller.home_id} -
    -
    - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.server_url" - )}: - - ${this._network.client.ws_server_url} + @click=${this._network?.controller.inclusion_state === + InclusionState.Including + ? this._cancelInclusion + : this._cancelExclusion} + > + + + ` + : ""} + ${this._network + ? html` + +
    +
    +
    + ${this._status === "disconnected" + ? html`` + : html` + + `}
    -
    - - - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.messages_tx.label" - )} - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.messages_tx.tooltip" - )} - - ${this._statistics?.messages_tx ?? 0} - - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.messages_rx.label" - )} - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.messages_rx.tooltip" - )} - - ${this._statistics?.messages_rx ?? 0} - - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.messages_dropped_tx.label" - )} - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.messages_dropped_tx.tooltip" - )} - - ${this._statistics?.messages_dropped_tx ?? 0} - - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.messages_dropped_rx.label" - )} - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.messages_dropped_rx.tooltip" - )} - - ${this._statistics?.messages_dropped_rx ?? 0} - - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.nak.label" - )} - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.nak.tooltip" - )} - - ${this._statistics?.nak ?? 0} - - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.can.label" - )} - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.can.tooltip" - )} - - ${this._statistics?.can ?? 0} - - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.timeout_ack.label" - )} - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.timeout_ack.tooltip" - )} - - ${this._statistics?.timeout_ack ?? 0} - - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.timeout_response.label" - )} - - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.timeout_response.tooltip" - )} - - ${this._statistics?.timeout_response ?? 0} - - - + ${this._status !== "disconnected" + ? html` +
    + Z-Wave ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.timeout_callback.label" + "ui.panel.config.zwave_js.common.network" )} - - ${this.hass.localize( - "ui.panel.config.zwave_js.dashboard.statistics.timeout_callback.tooltip" - )} - - ${this._statistics?.timeout_callback ?? 0} - - - + `ui.panel.config.zwave_js.network_status.${this._status}` + )}
    + + ${this.hass.localize( + `ui.panel.config.zwave_js.dashboard.devices`, + { + count: this._network.controller.nodes.length, + } + )} + ${notReadyDevices > 0 + ? html`(${this.hass.localize( + `ui.panel.config.zwave_js.dashboard.not_ready`, + { count: notReadyDevices } + )})` + : ""} + +
    + ` + : ``}
    -
    - - ${this.hass.localize( - "ui.panel.config.zwave_js.common.remove_node" - )} +
    + + + +
    +
    + ${this.hass.localize( - "ui.panel.config.zwave_js.common.reconfigure_server" - )} - + "ui.panel.config.zwave_js.dashboard.driver_version" + )}: + + ${this._network.client.driver_version}
    - - -
    -

    Third-Party Data Reporting

    - ${this._dataCollectionOptIn !== undefined - ? html` - - ` - : html` - - `} +
    + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.server_version" + )}: + + ${this._network.client.server_version} +
    +
    + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.home_id" + )}: + + ${this._network.controller.home_id}
    -
    -

    - Enable the reporting of anonymized telemetry and - statistics to the Z-Wave JS organization. This - data will be used to focus development efforts and improve - the user experience. Information about the data that is - collected and how it is used, including an example of the - data collected, can be found in the - Z-Wave JS data collection documentation. -

    +
    + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.server_url" + )}: + + ${this._network.client.ws_server_url}
    - - ` - : ``} - +
    + + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.messages_tx.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.messages_tx.tooltip" + )} + + ${this._statistics?.messages_tx ?? 0} + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.messages_rx.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.messages_rx.tooltip" + )} + + ${this._statistics?.messages_rx ?? 0} + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.messages_dropped_tx.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.messages_dropped_tx.tooltip" + )} + + ${this._statistics?.messages_dropped_tx ?? 0} + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.messages_dropped_rx.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.messages_dropped_rx.tooltip" + )} + + ${this._statistics?.messages_dropped_rx ?? 0} + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.nak.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.nak.tooltip" + )} + + ${this._statistics?.nak ?? 0} + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.can.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.can.tooltip" + )} + + ${this._statistics?.can ?? 0} + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.timeout_ack.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.timeout_ack.tooltip" + )} + + ${this._statistics?.timeout_ack ?? 0} + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.timeout_response.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.timeout_response.tooltip" + )} + + ${this._statistics?.timeout_response ?? 0} + + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.timeout_callback.label" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.dashboard.statistics.timeout_callback.tooltip" + )} + + ${this._statistics?.timeout_callback ?? 0} + + + +
    +
    + + ${this.hass.localize( + "ui.panel.config.zwave_js.common.remove_node" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.common.rebuild_network_routes" + )} + + + ${this.hass.localize( + "ui.panel.config.zwave_js.common.reconfigure_server" + )} + +
    + + +
    +

    Third-Party Data Reporting

    + ${this._dataCollectionOptIn !== undefined + ? html` + + ` + : html` + + `} +
    +
    +

    + Enable the reporting of anonymized telemetry and statistics + to the Z-Wave JS organization. This data will be + used to focus development efforts and improve the user + experience. Information about the data that is collected and + how it is used, including an example of the data collected, + can be found in the + Z-Wave JS data collection documentation. +

    +
    +
    + ` + : ``} + ${!this.scenes.length + ? html`
    + +

    + ${this.hass.localize( + "ui.panel.config.scene.picker.empty_header" + )} +

    +

    + ${this.hass.localize("ui.panel.config.scene.picker.empty_text")} +

    + + + ${this.hass.localize("ui.panel.config.common.learn_more")} + + +
    ` + : nothing} ` ); diff --git a/src/panels/config/script/ha-script-picker.ts b/src/panels/config/script/ha-script-picker.ts index 59a05f6b9e8b..ac2ace77675e 100644 --- a/src/panels/config/script/ha-script-picker.ts +++ b/src/panels/config/script/ha-script-picker.ts @@ -5,10 +5,18 @@ import { mdiInformationOutline, mdiPlay, mdiPlus, + mdiScriptText, mdiTransitConnection, } from "@mdi/js"; import { differenceInDays } from "date-fns/esm"; -import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit"; +import { + CSSResultGroup, + LitElement, + TemplateResult, + css, + html, + nothing, +} from "lit"; import { customElement, property, state } from "lit/decorators"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; @@ -241,6 +249,7 @@ class HaScriptPicker extends LitElement { .tabs=${configSections.automations} .columns=${this._columns(this.narrow, this.hass.locale)} .data=${this._scripts(this.scripts, this._filteredScripts)} + .empty=${!this.scripts.length} .activeFilters=${this._activeFilters} id="entity_id" .noDataText=${this.hass.localize( @@ -266,6 +275,30 @@ class HaScriptPicker extends LitElement { @related-changed=${this._relatedFilterChanged} > + ${!this.scripts.length + ? html` ` + : nothing}
    - ${this._qrCode - ? html`
    ${this._qrCode}
    ` - : ""} +
    + + +
    ` : ``}
    @@ -158,7 +151,7 @@ class DialogTagDetail : this.hass!.localize("ui.panel.config.tag.detail.create")} ${this._params.openWrite && !this._params.entry - ? html` { - imageObj.onload = resolve; - }); - context?.drawImage( - imageObj, - canvas.width / 3, - canvas.height / 3, - canvas.width / 3, - canvas.height / 3 - ); - - this._qrCode = html`${this.hass.localize("ui.panel.config.tag.qr_code_image",`; - } - static get styles(): CSSResultGroup { return [ haStyleDialog, @@ -270,6 +228,9 @@ class DialogTagDetail display: block; margin: 8px 0; } + ::slotted(img) { + height: 100%; + } `, ]; } 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 5e23835ad495..77e167c45608 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 @@ -110,7 +110,10 @@ export class AssistPipelineDetailWakeWord extends LitElement { `ui.panel.config.voice_assistants.assistants.pipeline.detail.steps.wakeword.no_wake_words` )} ${this.hass.localize( diff --git a/src/panels/developer-tools/state/developer-tools-state.ts b/src/panels/developer-tools/state/developer-tools-state.ts index 7d8a9a275db2..a2682f08632b 100644 --- a/src/panels/developer-tools/state/developer-tools-state.ts +++ b/src/panels/developer-tools/state/developer-tools-state.ts @@ -627,9 +627,6 @@ class HaPanelDevState extends LitElement { .entities th { padding: 0 8px; text-align: left; - font-size: var( - --paper-input-container-shared-input-style_-_font-size - ); } .filters th { diff --git a/src/panels/developer-tools/statistics/developer-tools-statistics.ts b/src/panels/developer-tools/statistics/developer-tools-statistics.ts index cdf0abe75c13..878a4fa73978 100644 --- a/src/panels/developer-tools/statistics/developer-tools-statistics.ts +++ b/src/panels/developer-tools/statistics/developer-tools-statistics.ts @@ -423,9 +423,6 @@ class HaPanelDevStatistics extends SubscribeMixin(LitElement) { th { padding: 0 8px; text-align: left; - font-size: var( - --paper-input-container-shared-input-style_-_font-size - ); } :host([rtl]) th { diff --git a/src/panels/energy/ha-panel-energy.ts b/src/panels/energy/ha-panel-energy.ts index 2c0bcf146c3f..26cdc9428405 100644 --- a/src/panels/energy/ha-panel-energy.ts +++ b/src/panels/energy/ha-panel-energy.ts @@ -141,6 +141,7 @@ class PanelEnergy extends LitElement { padding-inline-start: 32px; --disabled-text-color: rgba(var(--rgb-text-primary-color), 0.5); direction: var(--direction); + --date-range-picker-max-height: calc(100vh - 80px); } :host([narrow]) hui-energy-period-selector { padding-left: 0px; diff --git a/src/panels/lovelace/card-features/hui-climate-fan-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-climate-fan-modes-card-feature.ts new file mode 100644 index 000000000000..bfdf039b94f6 --- /dev/null +++ b/src/panels/lovelace/card-features/hui-climate-fan-modes-card-feature.ts @@ -0,0 +1,217 @@ +import { mdiFan } from "@mdi/js"; +import { HassEntity } from "home-assistant-js-websocket"; +import { css, html, LitElement, PropertyValues, TemplateResult } 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 { supportsFeature } from "../../../common/entity/supports-feature"; +import "../../../components/ha-control-select"; +import type { ControlSelectOption } from "../../../components/ha-control-select"; +import "../../../components/ha-control-select-menu"; +import type { HaControlSelectMenu } from "../../../components/ha-control-select-menu"; +import { + ClimateEntity, + ClimateEntityFeature, + computeFanModeIcon, +} from "../../../data/climate"; +import { UNAVAILABLE } from "../../../data/entity"; +import { HomeAssistant } from "../../../types"; +import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; +import { ClimateFanModesCardFeatureConfig } from "./types"; + +export const supportsClimateFanModesCardFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return ( + domain === "climate" && + supportsFeature(stateObj, ClimateEntityFeature.FAN_MODE) + ); +}; + +@customElement("hui-climate-fan-modes-card-feature") +class HuiClimateFanModesCardFeature + extends LitElement + implements LovelaceCardFeature +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public stateObj?: ClimateEntity; + + @state() private _config?: ClimateFanModesCardFeatureConfig; + + @state() _currentFanMode?: string; + + @query("ha-control-select-menu", true) + private _haSelect?: HaControlSelectMenu; + + static getStubConfig( + _, + stateObj?: HassEntity + ): ClimateFanModesCardFeatureConfig { + return { + type: "climate-fan-modes", + style: "dropdown", + fan_modes: stateObj?.attributes.fan_modes || [], + }; + } + + public static async getConfigElement(): Promise { + await import( + "../editor/config-elements/hui-climate-fan-modes-card-feature-editor" + ); + return document.createElement("hui-climate-fan-modes-card-feature-editor"); + } + + public setConfig(config: ClimateFanModesCardFeatureConfig): 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._currentFanMode = this.stateObj.attributes.fan_mode; + } + } + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + if (this._haSelect && 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 fanMode = + (ev.detail as any).value ?? ((ev.target as any).value as string); + + const oldFanMode = this.stateObj!.attributes.fan_mode; + + if (fanMode === oldFanMode) return; + + this._currentFanMode = fanMode; + + try { + await this._setMode(fanMode); + } catch (err) { + this._currentFanMode = oldFanMode; + } + } + + private async _setMode(mode: string) { + await this.hass!.callService("climate", "set_fan_mode", { + entity_id: this.stateObj!.entity_id, + fan_mode: mode, + }); + } + + protected render(): TemplateResult | null { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsClimateFanModesCardFeature(this.stateObj) + ) { + return null; + } + + const stateObj = this.stateObj; + + const modes = stateObj.attributes.fan_modes || []; + + const options = modes + .filter((mode) => (this._config!.fan_modes || []).includes(mode)) + .map((mode) => ({ + value: mode, + label: this.hass!.formatEntityAttributeValue( + this.stateObj!, + "fan_mode", + mode + ), + path: computeFanModeIcon(mode), + })); + + if (this._config.style === "icons") { + return html` +
    + + +
    + `; + } + + return html` +
    + + + ${options.map( + (option) => html` + + + ${option.label} + + ` + )} + +
    + `; + } + + 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%; + } + ha-control-select { + --control-select-color: var(--feature-color); + --control-select-padding: 0; + --control-select-thickness: 40px; + --control-select-border-radius: 10px; + --control-select-button-border-radius: 10px; + } + .container { + padding: 0 12px 12px 12px; + width: auto; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-climate-fan-modes-card-feature": HuiClimateFanModesCardFeature; + } +} diff --git a/src/panels/lovelace/card-features/hui-update-actions-card-feature.ts b/src/panels/lovelace/card-features/hui-update-actions-card-feature.ts new file mode 100644 index 000000000000..a2f9ddb8adcc --- /dev/null +++ b/src/panels/lovelace/card-features/hui-update-actions-card-feature.ts @@ -0,0 +1,165 @@ +import { mdiCancel, mdiCellphoneArrowDown } from "@mdi/js"; +import { HassEntity } from "home-assistant-js-websocket"; +import { LitElement, css, html, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { computeDomain } from "../../../common/entity/compute_domain"; +import { stateActive } from "../../../common/entity/state_active"; +import { supportsFeature } from "../../../common/entity/supports-feature"; +import "../../../components/ha-control-button"; +import "../../../components/ha-control-button-group"; +import { UNAVAILABLE } from "../../../data/entity"; +import { + UpdateEntity, + UpdateEntityFeature, + updateIsInstalling, +} from "../../../data/update"; +import { showUpdateBackupDialogParams } from "../../../dialogs/update_backup/show-update-backup-dialog"; +import { HomeAssistant } from "../../../types"; +import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; +import { UpdateActionsCardFeatureConfig } from "./types"; + +export const DEFAULT_UPDATE_BACKUP_OPTION = "ask"; + +export const supportsUpdateActionsCardFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return ( + domain === "update" && + supportsFeature(stateObj, UpdateEntityFeature.INSTALL) + ); +}; + +@customElement("hui-update-actions-card-feature") +class HuiUpdateActionsCardFeature + extends LitElement + implements LovelaceCardFeature +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public stateObj?: HassEntity; + + @state() private _config?: UpdateActionsCardFeatureConfig; + + public static async getConfigElement(): Promise { + await import( + "../editor/config-elements/hui-update-actions-card-feature-editor" + ); + return document.createElement("hui-update-actions-card-feature-editor"); + } + + static getStubConfig(): UpdateActionsCardFeatureConfig { + return { + type: "update-actions", + backup: DEFAULT_UPDATE_BACKUP_OPTION, + }; + } + + public setConfig(config: UpdateActionsCardFeatureConfig): void { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + } + + private get _installDisabled(): boolean { + const stateObj = this.stateObj as UpdateEntity; + + if (stateObj.state === UNAVAILABLE) return true; + + const skippedVersion = + stateObj.attributes.latest_version && + stateObj.attributes.skipped_version === + stateObj.attributes.latest_version; + return ( + (!stateActive(stateObj) && !skippedVersion) || + updateIsInstalling(stateObj) + ); + } + + private get _skipDisabled(): boolean { + const stateObj = this.stateObj as UpdateEntity; + + if (stateObj.state === UNAVAILABLE) return true; + + const skippedVersion = + stateObj.attributes.latest_version && + stateObj.attributes.skipped_version === + stateObj.attributes.latest_version; + return ( + skippedVersion || !stateActive(stateObj) || updateIsInstalling(stateObj) + ); + } + + private async _install(): Promise { + const supportsBackup = supportsFeature( + this.stateObj!, + UpdateEntityFeature.BACKUP + ); + let backup = supportsBackup && this._config?.backup === "yes"; + + if (supportsBackup && this._config?.backup === "ask") { + const response = await showUpdateBackupDialogParams(this, {}); + if (response === null) return; + backup = response; + } + + this.hass!.callService("update", "install", { + entity_id: this.stateObj!.entity_id, + backup: backup, + }); + } + + private async _skip(): Promise { + this.hass!.callService("update", "skip", { + entity_id: this.stateObj!.entity_id, + }); + } + + protected render() { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsUpdateActionsCardFeature(this.stateObj) + ) { + return nothing; + } + + return html` + + + + + + + + + `; + } + + static get styles() { + return css` + ha-control-button-group { + margin: 0 12px 12px 12px; + --control-button-group-spacing: 12px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-update-actions-card-feature": HuiUpdateActionsCardFeature; + } +} diff --git a/src/panels/lovelace/card-features/types.ts b/src/panels/lovelace/card-features/types.ts index bd8ef53443a6..e5c4d388583b 100644 --- a/src/panels/lovelace/card-features/types.ts +++ b/src/panels/lovelace/card-features/types.ts @@ -35,6 +35,12 @@ export interface AlarmModesCardFeatureConfig { modes?: AlarmMode[]; } +export interface ClimateFanModesCardFeatureConfig { + type: "climate-fan-modes"; + style?: "dropdown" | "icons"; + fan_modes?: string[]; +} + export interface ClimateHvacModesCardFeatureConfig { type: "climate-hvac-modes"; style?: "dropdown" | "icons"; @@ -103,8 +109,14 @@ export interface LawnMowerCommandsCardFeatureConfig { commands?: LawnMowerCommand[]; } +export interface UpdateActionsCardFeatureConfig { + type: "update-actions"; + backup?: "yes" | "no" | "ask"; +} + export type LovelaceCardFeatureConfig = | AlarmModesCardFeatureConfig + | ClimateFanModesCardFeatureConfig | ClimateHvacModesCardFeatureConfig | ClimatePresetModesCardFeatureConfig | CoverOpenCloseCardFeatureConfig @@ -122,7 +134,8 @@ export type LovelaceCardFeatureConfig = | TargetTemperatureCardFeatureConfig | WaterHeaterOperationModesCardFeatureConfig | SelectOptionsCardFeatureConfig - | NumericInputCardFeatureConfig; + | NumericInputCardFeatureConfig + | UpdateActionsCardFeatureConfig; export type LovelaceCardFeatureContext = { entity_id?: string; diff --git a/src/panels/lovelace/cards/energy/common/energy-chart-options.ts b/src/panels/lovelace/cards/energy/common/energy-chart-options.ts new file mode 100644 index 000000000000..ef6c04677e7e --- /dev/null +++ b/src/panels/lovelace/cards/energy/common/energy-chart-options.ts @@ -0,0 +1,168 @@ +import { ChartOptions } from "chart.js"; +import { HassConfig } from "home-assistant-js-websocket"; +import { + addHours, + subHours, + differenceInDays, + differenceInHours, +} from "date-fns/esm"; +import { FrontendLocaleData } from "../../../../../data/translation"; +import { + formatNumber, + numberFormatToLocale, +} from "../../../../../common/number/format_number"; +import { formatDateVeryShort } from "../../../../../common/datetime/format_date"; +import { formatTime } from "../../../../../common/datetime/format_time"; + +export function getSuggestedMax(dayDifference: number, end: Date): number { + let suggestedMax = new Date(end); + + // Sometimes around DST we get a time of 0:59 instead of 23:59 as expected. + // Correct for this when showing days/months so we don't get an extra day. + if (dayDifference > 2 && suggestedMax.getHours() === 0) { + suggestedMax = subHours(suggestedMax, 1); + } + + suggestedMax.setMinutes(0, 0, 0); + if (dayDifference > 35) { + suggestedMax.setDate(1); + } + if (dayDifference > 2) { + suggestedMax.setHours(0); + } + return suggestedMax.getTime(); +} + +export function getCommonOptions( + start: Date, + end: Date, + locale: FrontendLocaleData, + config: HassConfig, + unit?: string, + compareStart?: Date, + compareEnd?: Date +): ChartOptions { + const dayDifference = differenceInDays(end, start); + const compare = compareStart !== undefined && compareEnd !== undefined; + if (compare && dayDifference <= 35) { + const difference = differenceInHours(end, start); + const differenceCompare = differenceInHours(compareEnd!, compareStart!); + // If the compare period doesn't match the main period, adjust them to match + if (differenceCompare > difference) { + end = addHours(end, differenceCompare - difference); + } else if (difference > differenceCompare) { + compareEnd = addHours(compareEnd!, difference - differenceCompare); + } + } + + const options: ChartOptions = { + parsing: false, + animation: false, + interaction: { + mode: "x", + }, + scales: { + x: { + type: "time", + suggestedMin: start.getTime(), + max: getSuggestedMax(dayDifference, end), + adapters: { + date: { + locale, + config, + }, + }, + ticks: { + maxRotation: 0, + sampleSize: 5, + autoSkipPadding: 20, + font: (context) => + context.tick && context.tick.major + ? ({ weight: "bold" } as any) + : {}, + }, + time: { + tooltipFormat: + dayDifference > 35 + ? "monthyear" + : dayDifference > 7 + ? "date" + : dayDifference > 2 + ? "weekday" + : dayDifference > 0 + ? "datetime" + : "hour", + minUnit: + dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour", + }, + }, + y: { + stacked: true, + type: "linear", + title: { + display: true, + text: unit, + }, + ticks: { + beginAtZero: true, + callback: (value) => formatNumber(Math.abs(value), locale), + }, + }, + }, + plugins: { + tooltip: { + position: "nearest", + filter: (val) => val.formattedValue !== "0", + itemSort: function (a, b) { + return b.datasetIndex - a.datasetIndex; + }, + callbacks: { + title: (datasets) => { + if (dayDifference > 0) { + return datasets[0].label; + } + const date = new Date(datasets[0].parsed.x); + return `${ + compare ? `${formatDateVeryShort(date, locale, config)}: ` : "" + }${formatTime(date, locale, config)} – ${formatTime( + addHours(date, 1), + locale, + config + )}`; + }, + label: (context) => + `${context.dataset.label}: ${formatNumber( + context.parsed.y, + locale + )} ${unit}`, + }, + }, + filler: { + propagate: false, + }, + legend: { + display: false, + labels: { + usePointStyle: true, + }, + }, + }, + elements: { + bar: { borderWidth: 1.5, borderRadius: 4 }, + point: { + hitRadius: 50, + }, + }, + // @ts-expect-error + locale: numberFormatToLocale(locale), + }; + if (compare) { + options.scales!.xAxisCompare = { + ...(options.scales!.x as Record), + suggestedMin: compareStart!.getTime(), + max: getSuggestedMax(dayDifference, compareEnd!), + display: false, + }; + } + return options; +} diff --git a/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts index 1ae6d1f730d5..5bb965b05249 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts @@ -4,14 +4,7 @@ import { ChartOptions, ScatterDataPoint, } from "chart.js"; -import { - addHours, - differenceInDays, - differenceInHours, - endOfToday, - isToday, - startOfToday, -} from "date-fns"; +import { endOfToday, isToday, startOfToday } from "date-fns"; import { HassConfig, UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, @@ -31,12 +24,7 @@ import { rgb2lab, } from "../../../../common/color/convert-color"; import { labBrighten, labDarken } from "../../../../common/color/lab"; -import { formatDateVeryShort } from "../../../../common/datetime/format_date"; -import { formatTime } from "../../../../common/datetime/format_time"; -import { - formatNumber, - numberFormatToLocale, -} from "../../../../common/number/format_number"; +import { formatNumber } from "../../../../common/number/format_number"; import "../../../../components/chart/ha-chart-base"; import "../../../../components/ha-card"; import { @@ -56,6 +44,7 @@ import { HomeAssistant } from "../../../../types"; import { LovelaceCard } from "../../types"; import { EnergyGasGraphCardConfig } from "../types"; import { hasConfigChanged } from "../../common/has-changed"; +import { getCommonOptions } from "./common/energy-chart-options"; @customElement("hui-energy-gas-graph-card") export class HuiEnergyGasGraphCard @@ -159,105 +148,23 @@ export class HuiEnergyGasGraphCard compareStart?: Date, compareEnd?: Date ): ChartOptions => { - const dayDifference = differenceInDays(end, start); - const compare = compareStart !== undefined && compareEnd !== undefined; - if (compare) { - const difference = differenceInHours(end, start); - const differenceCompare = differenceInHours(compareEnd!, compareStart!); - // If the compare period doesn't match the main period, adjust them to match - if (differenceCompare > difference) { - end = addHours(end, differenceCompare - difference); - } else if (difference > differenceCompare) { - compareEnd = addHours(compareEnd!, difference - differenceCompare); - } - } - + const commonOptions = getCommonOptions( + start, + end, + locale, + config, + unit, + compareStart, + compareEnd + ); const options: ChartOptions = { - parsing: false, - animation: false, - interaction: { - mode: "x", - }, - scales: { - x: { - type: "time", - suggestedMin: start.getTime(), - suggestedMax: end.getTime(), - adapters: { - date: { - locale, - config, - }, - }, - ticks: { - maxRotation: 0, - sampleSize: 5, - autoSkipPadding: 20, - font: (context) => - context.tick && context.tick.major - ? ({ weight: "bold" } as any) - : {}, - }, - time: { - tooltipFormat: - dayDifference > 35 - ? "monthyear" - : dayDifference > 7 - ? "date" - : dayDifference > 2 - ? "weekday" - : dayDifference > 0 - ? "datetime" - : "hour", - minUnit: - dayDifference > 35 - ? "month" - : dayDifference > 2 - ? "day" - : "hour", - }, - offset: true, - }, - y: { - stacked: true, - type: "linear", - title: { - display: true, - text: unit, - }, - ticks: { - beginAtZero: true, - }, - }, - }, + ...commonOptions, plugins: { + ...commonOptions.plugins, tooltip: { - position: "nearest", - filter: (val) => val.formattedValue !== "0", - itemSort: function (a, b) { - return b.datasetIndex - a.datasetIndex; - }, + ...commonOptions.plugins!.tooltip, callbacks: { - title: (datasets) => { - if (dayDifference > 0) { - return datasets[0].label; - } - const date = new Date(datasets[0].parsed.x); - return `${ - compare - ? `${formatDateVeryShort(date, locale, config)}: ` - : "" - }${formatTime(date, locale, config)} – ${formatTime( - addHours(date, 1), - locale, - config - )}`; - }, - label: (context) => - `${context.dataset.label}: ${formatNumber( - context.parsed.y, - locale - )} ${unit}`, + ...commonOptions.plugins!.tooltip!.callbacks, footer: (contexts) => { if (contexts.length < 2) { return []; @@ -278,33 +185,8 @@ export class HuiEnergyGasGraphCard }, }, }, - filler: { - propagate: false, - }, - legend: { - display: false, - labels: { - usePointStyle: true, - }, - }, }, - elements: { - bar: { borderWidth: 1.5, borderRadius: 4 }, - point: { - hitRadius: 50, - }, - }, - // @ts-expect-error - locale: numberFormatToLocale(locale), }; - if (compare) { - options.scales!.xAxisCompare = { - ...(options.scales!.x as Record), - suggestedMin: compareStart!.getTime(), - suggestedMax: compareEnd!.getTime(), - display: false, - }; - } return options; } ); diff --git a/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts index 78916e4e33ad..9da9393888b9 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts @@ -5,9 +5,7 @@ import { ScatterDataPoint, } from "chart.js"; import { - addHours, differenceInDays, - differenceInHours, endOfToday, isToday, startOfToday, @@ -31,12 +29,7 @@ import { rgb2lab, } from "../../../../common/color/convert-color"; import { labBrighten, labDarken } from "../../../../common/color/lab"; -import { formatDateVeryShort } from "../../../../common/datetime/format_date"; -import { formatTime } from "../../../../common/datetime/format_time"; -import { - formatNumber, - numberFormatToLocale, -} from "../../../../common/number/format_number"; +import { formatNumber } from "../../../../common/number/format_number"; import "../../../../components/chart/ha-chart-base"; import "../../../../components/ha-card"; import { @@ -57,6 +50,7 @@ import { HomeAssistant } from "../../../../types"; import { LovelaceCard } from "../../types"; import { EnergySolarGraphCardConfig } from "../types"; import { hasConfigChanged } from "../../common/has-changed"; +import { getCommonOptions } from "./common/energy-chart-options"; @customElement("hui-energy-solar-graph-card") export class HuiEnergySolarGraphCard @@ -156,104 +150,23 @@ export class HuiEnergySolarGraphCard compareStart?: Date, compareEnd?: Date ): ChartOptions => { - const dayDifference = differenceInDays(end, start); - const compare = compareStart !== undefined && compareEnd !== undefined; - if (compare) { - const difference = differenceInHours(end, start); - const differenceCompare = differenceInHours(compareEnd!, compareStart!); - // If the compare period doesn't match the main period, adjust them to match - if (differenceCompare > difference) { - end = addHours(end, differenceCompare - difference); - } else if (difference > differenceCompare) { - compareEnd = addHours(compareEnd!, difference - differenceCompare); - } - } - + const commonOptions = getCommonOptions( + start, + end, + locale, + config, + "kWh", + compareStart, + compareEnd + ); const options: ChartOptions = { - parsing: false, - animation: false, - interaction: { - mode: "x", - }, - scales: { - x: { - type: "time", - suggestedMin: start.getTime(), - suggestedMax: end.getTime(), - adapters: { - date: { - locale, - config, - }, - }, - ticks: { - maxRotation: 0, - sampleSize: 5, - autoSkipPadding: 20, - font: (context) => - context.tick && context.tick.major - ? ({ weight: "bold" } as any) - : {}, - }, - time: { - tooltipFormat: - dayDifference > 35 - ? "monthyear" - : dayDifference > 7 - ? "date" - : dayDifference > 2 - ? "weekday" - : dayDifference > 0 - ? "datetime" - : "hour", - minUnit: - dayDifference > 35 - ? "month" - : dayDifference > 2 - ? "day" - : "hour", - }, - }, - y: { - stacked: true, - type: "linear", - title: { - display: true, - text: "kWh", - }, - ticks: { - beginAtZero: true, - }, - }, - }, + ...commonOptions, plugins: { + ...commonOptions.plugins, tooltip: { - position: "nearest", - filter: (val) => val.formattedValue !== "0", - itemSort: function (a, b) { - return b.datasetIndex - a.datasetIndex; - }, + ...commonOptions.plugins!.tooltip, callbacks: { - title: (datasets) => { - if (dayDifference > 0) { - return datasets[0].label; - } - const date = new Date(datasets[0].parsed.x); - return `${ - compare - ? `${formatDateVeryShort(date, locale, config)}: ` - : "" - }${formatTime(date, locale, config)} – ${formatTime( - addHours(date, 1), - locale, - config - )}`; - }, - label: (context) => - `${context.dataset.label}: ${formatNumber( - context.parsed.y, - locale - )} kWh`, + ...commonOptions.plugins!.tooltip!.callbacks, footer: (contexts) => { const production_contexts = contexts.filter( (c) => c.dataset?.stack === "solar" @@ -277,15 +190,6 @@ export class HuiEnergySolarGraphCard }, }, }, - filler: { - propagate: false, - }, - legend: { - display: false, - labels: { - usePointStyle: true, - }, - }, }, elements: { line: { @@ -297,17 +201,7 @@ export class HuiEnergySolarGraphCard hitRadius: 5, }, }, - // @ts-expect-error - locale: numberFormatToLocale(locale), }; - if (compare) { - options.scales!.xAxisCompare = { - ...(options.scales!.x as Record), - suggestedMin: compareStart!.getTime(), - suggestedMax: compareEnd!.getTime(), - display: false, - }; - } return options; } ); diff --git a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts index 402798d7475a..e0be896b3648 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts @@ -4,14 +4,7 @@ import { ChartOptions, ScatterDataPoint, } from "chart.js"; -import { - addHours, - differenceInDays, - differenceInHours, - endOfToday, - isToday, - startOfToday, -} from "date-fns/esm"; +import { endOfToday, isToday, startOfToday } from "date-fns/esm"; import { HassConfig, UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, @@ -31,12 +24,7 @@ import { rgb2lab, } from "../../../../common/color/convert-color"; import { labBrighten, labDarken } from "../../../../common/color/lab"; -import { formatDateVeryShort } from "../../../../common/datetime/format_date"; -import { formatTime } from "../../../../common/datetime/format_time"; -import { - formatNumber, - numberFormatToLocale, -} from "../../../../common/number/format_number"; +import { formatNumber } from "../../../../common/number/format_number"; import "../../../../components/chart/ha-chart-base"; import "../../../../components/ha-card"; import { EnergyData, getEnergyDataCollection } from "../../../../data/energy"; @@ -51,6 +39,7 @@ import { HomeAssistant } from "../../../../types"; import { LovelaceCard } from "../../types"; import { EnergyUsageGraphCardConfig } from "../types"; import { hasConfigChanged } from "../../common/has-changed"; +import { getCommonOptions } from "./common/energy-chart-options"; interface ColorSet { base: string; @@ -155,81 +144,21 @@ export class HuiEnergyUsageGraphCard compareStart?: Date, compareEnd?: Date ): ChartOptions => { - const dayDifference = differenceInDays(end, start); - const compare = compareStart !== undefined && compareEnd !== undefined; - if (compare) { - const difference = differenceInHours(end, start); - const differenceCompare = differenceInHours(compareEnd!, compareStart!); - // If the compare period doesn't match the main period, adjust them to match - if (differenceCompare > difference) { - end = addHours(end, differenceCompare - difference); - } else if (difference > differenceCompare) { - compareEnd = addHours(compareEnd!, difference - differenceCompare); - } - } - + const commonOptions = getCommonOptions( + start, + end, + locale, + config, + "kWh", + compareStart, + compareEnd + ); const options: ChartOptions = { - parsing: false, - animation: false, - interaction: { - mode: "x", - }, - scales: { - x: { - type: "time", - suggestedMin: start.getTime(), - suggestedMax: end.getTime(), - adapters: { - date: { - locale, - config, - }, - }, - ticks: { - maxRotation: 0, - sampleSize: 5, - autoSkipPadding: 20, - font: (context) => - context.tick && context.tick.major - ? ({ weight: "bold" } as any) - : {}, - }, - time: { - tooltipFormat: - dayDifference > 35 - ? "monthyear" - : dayDifference > 7 - ? "date" - : dayDifference > 2 - ? "weekday" - : dayDifference > 0 - ? "datetime" - : "hour", - minUnit: - dayDifference > 35 - ? "month" - : dayDifference > 2 - ? "day" - : "hour", - }, - }, - y: { - stacked: true, - type: "linear", - title: { - display: true, - text: "kWh", - }, - ticks: { - beginAtZero: true, - callback: (value) => formatNumber(Math.abs(value), locale), - }, - }, - }, + ...commonOptions, plugins: { + ...commonOptions.plugins, tooltip: { - position: "nearest", - filter: (val) => val.formattedValue !== "0", + ...commonOptions.plugins!.tooltip, itemSort: function (a: any, b: any) { if (a.raw?.y > 0 && b.raw?.y < 0) { return -1; @@ -243,26 +172,7 @@ export class HuiEnergyUsageGraphCard return a.datasetIndex - b.datasetIndex; }, callbacks: { - title: (datasets) => { - if (dayDifference > 0) { - return datasets[0].label; - } - const date = new Date(datasets[0].parsed.x); - return `${ - compare - ? `${formatDateVeryShort(date, locale, config)}: ` - : "" - }${formatTime(date, locale, config)} – ${formatTime( - addHours(date, 1), - locale, - config - )}`; - }, - label: (context) => - `${context.dataset.label}: ${formatNumber( - Math.abs(context.parsed.y), - locale - )} kWh`, + ...commonOptions.plugins!.tooltip!.callbacks, footer: (contexts) => { let totalConsumed = 0; let totalReturned = 0; @@ -292,33 +202,8 @@ export class HuiEnergyUsageGraphCard }, }, }, - filler: { - propagate: false, - }, - legend: { - display: false, - labels: { - usePointStyle: true, - }, - }, - }, - elements: { - bar: { borderWidth: 1.5, borderRadius: 4 }, - point: { - hitRadius: 50, - }, }, - // @ts-expect-error - locale: numberFormatToLocale(locale), }; - if (compare) { - options.scales!.xAxisCompare = { - ...(options.scales!.x as Record), - suggestedMin: compareStart!.getTime(), - suggestedMax: compareEnd!.getTime(), - display: false, - }; - } return options; } ); @@ -662,7 +547,9 @@ export class HuiEnergyUsageGraphCard }); }); - const uniqueKeys = Array.from(new Set(allKeys)); + const uniqueKeys = Array.from(new Set(allKeys)).sort( + (a, b) => Number(a) - Number(b) + ); Object.entries(combinedData).forEach(([type, sources]) => { Object.entries(sources).forEach(([statId, source], idx) => { diff --git a/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts index 15942779f96f..2398b146a9ee 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts @@ -4,14 +4,7 @@ import { ChartOptions, ScatterDataPoint, } from "chart.js"; -import { - addHours, - differenceInDays, - differenceInHours, - endOfToday, - isToday, - startOfToday, -} from "date-fns"; +import { endOfToday, isToday, startOfToday } from "date-fns"; import { HassConfig, UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, @@ -31,12 +24,7 @@ import { rgb2lab, } from "../../../../common/color/convert-color"; import { labBrighten, labDarken } from "../../../../common/color/lab"; -import { formatDateVeryShort } from "../../../../common/datetime/format_date"; -import { formatTime } from "../../../../common/datetime/format_time"; -import { - formatNumber, - numberFormatToLocale, -} from "../../../../common/number/format_number"; +import { formatNumber } from "../../../../common/number/format_number"; import "../../../../components/chart/ha-chart-base"; import "../../../../components/ha-card"; import { @@ -56,6 +44,7 @@ import { HomeAssistant } from "../../../../types"; import { LovelaceCard } from "../../types"; import { EnergyWaterGraphCardConfig } from "../types"; import { hasConfigChanged } from "../../common/has-changed"; +import { getCommonOptions } from "./common/energy-chart-options"; @customElement("hui-energy-water-graph-card") export class HuiEnergyWaterGraphCard @@ -159,105 +148,23 @@ export class HuiEnergyWaterGraphCard compareStart?: Date, compareEnd?: Date ): ChartOptions => { - const dayDifference = differenceInDays(end, start); - const compare = compareStart !== undefined && compareEnd !== undefined; - if (compare) { - const difference = differenceInHours(end, start); - const differenceCompare = differenceInHours(compareEnd!, compareStart!); - // If the compare period doesn't match the main period, adjust them to match - if (differenceCompare > difference) { - end = addHours(end, differenceCompare - difference); - } else if (difference > differenceCompare) { - compareEnd = addHours(compareEnd!, difference - differenceCompare); - } - } - + const commonOptions = getCommonOptions( + start, + end, + locale, + config, + unit, + compareStart, + compareEnd + ); const options: ChartOptions = { - parsing: false, - animation: false, - interaction: { - mode: "x", - }, - scales: { - x: { - type: "time", - suggestedMin: start.getTime(), - suggestedMax: end.getTime(), - adapters: { - date: { - locale, - config, - }, - }, - ticks: { - maxRotation: 0, - sampleSize: 5, - autoSkipPadding: 20, - font: (context) => - context.tick && context.tick.major - ? ({ weight: "bold" } as any) - : {}, - }, - time: { - tooltipFormat: - dayDifference > 35 - ? "monthyear" - : dayDifference > 7 - ? "date" - : dayDifference > 2 - ? "weekday" - : dayDifference > 0 - ? "datetime" - : "hour", - minUnit: - dayDifference > 35 - ? "month" - : dayDifference > 2 - ? "day" - : "hour", - }, - offset: true, - }, - y: { - stacked: true, - type: "linear", - title: { - display: true, - text: unit, - }, - ticks: { - beginAtZero: true, - }, - }, - }, + ...commonOptions, plugins: { + ...commonOptions.plugins, tooltip: { - position: "nearest", - filter: (val) => val.formattedValue !== "0", - itemSort: function (a, b) { - return b.datasetIndex - a.datasetIndex; - }, + ...commonOptions.plugins!.tooltip, callbacks: { - title: (datasets) => { - if (dayDifference > 0) { - return datasets[0].label; - } - const date = new Date(datasets[0].parsed.x); - return `${ - compare - ? `${formatDateVeryShort(date, locale, config)}: ` - : "" - }${formatTime(date, locale, config)} – ${formatTime( - addHours(date, 1), - locale, - config - )}`; - }, - label: (context) => - `${context.dataset.label}: ${formatNumber( - context.parsed.y, - locale - )} ${unit}`, + ...commonOptions.plugins!.tooltip!.callbacks, footer: (contexts) => { if (contexts.length < 2) { return []; @@ -278,33 +185,8 @@ export class HuiEnergyWaterGraphCard }, }, }, - filler: { - propagate: false, - }, - legend: { - display: false, - labels: { - usePointStyle: true, - }, - }, }, - elements: { - bar: { borderWidth: 1.5, borderRadius: 4 }, - point: { - hitRadius: 50, - }, - }, - // @ts-expect-error - locale: numberFormatToLocale(locale), }; - if (compare) { - options.scales!.xAxisCompare = { - ...(options.scales!.x as Record), - suggestedMin: compareStart!.getTime(), - suggestedMax: compareEnd!.getTime(), - display: false, - }; - } return options; } ); diff --git a/src/panels/lovelace/cards/hui-humidifier-card.ts b/src/panels/lovelace/cards/hui-humidifier-card.ts index 445f02c935b8..990d0faaf7d7 100644 --- a/src/panels/lovelace/cards/hui-humidifier-card.ts +++ b/src/panels/lovelace/cards/hui-humidifier-card.ts @@ -128,7 +128,8 @@ export class HuiHumidifierCard extends LitElement implements LovelaceCard {

    ${name}

    diff --git a/src/panels/lovelace/cards/hui-thermostat-card.ts b/src/panels/lovelace/cards/hui-thermostat-card.ts index c9afb21227cc..cfa34d81e86f 100644 --- a/src/panels/lovelace/cards/hui-thermostat-card.ts +++ b/src/panels/lovelace/cards/hui-thermostat-card.ts @@ -120,7 +120,8 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {

    ${name}

    diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index f20eb2ecdee5..1c06426d1acb 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -251,6 +251,10 @@ export class HuiTileCard extends LitElement implements LovelaceCard { return this._renderStateContent(stateObj, ["state", "current_position"]); } + if (domain === "valve" && active) { + return this._renderStateContent(stateObj, ["state", "current_position"]); + } + if (domain === "humidifier") { return this._renderStateContent(stateObj, ["state", "current_humidity"]); } diff --git a/src/panels/lovelace/cards/hui-todo-list-card.ts b/src/panels/lovelace/cards/hui-todo-list-card.ts index c8ded0bcb074..3352f7a42b43 100644 --- a/src/panels/lovelace/cards/hui-todo-list-card.ts +++ b/src/panels/lovelace/cards/hui-todo-list-card.ts @@ -1,10 +1,15 @@ +import "@material/mwc-list/mwc-list"; +import type { List } from "@material/mwc-list/mwc-list"; import { + mdiClock, mdiDelete, + mdiDeleteSweep, + mdiDotsVertical, mdiDrag, - mdiNotificationClearAll, mdiPlus, mdiSort, } from "@mdi/js"; +import { endOfDay, isSameDay } from "date-fns"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { CSSResultGroup, @@ -22,11 +27,13 @@ import memoizeOne from "memoize-one"; import type { SortableEvent } from "sortablejs"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { supportsFeature } from "../../../common/entity/supports-feature"; -import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import "../../../components/ha-card"; +import "../../../components/ha-check-list-item"; import "../../../components/ha-checkbox"; import "../../../components/ha-icon-button"; import "../../../components/ha-list-item"; +import "../../../components/ha-markdown-element"; +import "../../../components/ha-relative-time"; import "../../../components/ha-select"; import "../../../components/ha-svg-icon"; import "../../../components/ha-textfield"; @@ -42,12 +49,15 @@ import { subscribeItems, updateItem, } from "../../../data/todo"; +import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import type { SortableInstance } from "../../../resources/sortable"; import { HomeAssistant } from "../../../types"; +import { showTodoItemEditDialog } from "../../todo/show-dialog-todo-item-editor"; import { findEntities } from "../common/find-entities"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { TodoListCardConfig } from "./types"; +import { sortableStyles } from "../../../resources/ha-sortable-style"; @customElement("hui-todo-list-card") export class HuiTodoListCard extends LitElement implements LovelaceCard { @@ -199,16 +209,6 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
    ${this.todoListSupportsFeature(TodoListEntityFeature.CREATE_TODO_ITEM) ? html` - - - ` - : nothing} - ${this.todoListSupportsFeature(TodoListEntityFeature.MOVE_TODO_ITEM) - ? html` ` : nothing}
    -
    - ${this._renderItems(uncheckedItems, unavailable)} -
    + ${uncheckedItems.length + ? html`
    + + ${this.hass!.localize( + "ui.panel.lovelace.cards.todo-list.unchecked_items" + )} + + ${this.todoListSupportsFeature( + TodoListEntityFeature.MOVE_TODO_ITEM + ) + ? html` + + + ${this.hass!.localize( + this._reordering + ? "ui.panel.lovelace.cards.todo-list.exit_reorder_items" + : "ui.panel.lovelace.cards.todo-list.reorder_items" + )} + + + + ` + : nothing} +
    + + ${this._renderItems(uncheckedItems, unavailable)} + ` + : html`

    + ${this.hass.localize( + "ui.panel.lovelace.cards.todo-list.no_unchecked_items" + )} +

    `} ${checkedItems.length ? html`
    -
    +
    ${this.hass!.localize( "ui.panel.lovelace.cards.todo-list.checked_items" @@ -249,65 +284,33 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { ${this.todoListSupportsFeature( TodoListEntityFeature.DELETE_TODO_ITEM ) - ? html` - ` - : nothing} -
    - ${repeat( - checkedItems, - (item) => item.uid, - (item) => html` -
    - ${this.todoListSupportsFeature( - TodoListEntityFeature.UPDATE_TODO_ITEM - ) - ? html` + + + ${this.hass!.localize( + "ui.panel.lovelace.cards.todo-list.clear_items" + )} + ` - : nothing} - - ${this.todoListSupportsFeature( - TodoListEntityFeature.DELETE_TODO_ITEM - ) && - !this.todoListSupportsFeature( - TodoListEntityFeature.UPDATE_TODO_ITEM - ) - ? html` - ` - : nothing} -
    - ` - )} + + + ` + : nothing} +
    + + ${this._renderItems(checkedItems, unavailable)} + ` : ""}
    @@ -319,59 +322,93 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { ${repeat( items, (item) => item.uid, - (item) => html` -
    - ${this.todoListSupportsFeature( + (item) => { + const showDelete = + this.todoListSupportsFeature( + TodoListEntityFeature.DELETE_TODO_ITEM + ) && + !this.todoListSupportsFeature( TodoListEntityFeature.UPDATE_TODO_ITEM - ) - ? html`` - : nothing} - - ${this._reordering - ? html` - - - ` - : this.todoListSupportsFeature( - TodoListEntityFeature.DELETE_TODO_ITEM - ) && - !this.todoListSupportsFeature( - TodoListEntityFeature.UPDATE_TODO_ITEM - ) - ? html` - ` - : nothing} -
    - ` + @change=${this._completeItem} + @click=${this._openItem} + @request-selected=${this._requestSelected} + @keydown=${this._handleKeydown} + > +
    + ${item.summary} + ${item.description + ? html`` + : nothing} + ${due + ? html`
    + ${today + ? this.hass!.localize( + "ui.panel.lovelace.cards.todo-list.today" + ) + : html``} +
    ` + : nothing} +
    + ${showReorder + ? html` + + + ` + : showDelete + ? html` + ` + : nothing} + + `; + } )} `; } @@ -401,37 +438,61 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { return this._items?.find((item) => item.uid === itemId); } - private _completeItem(ev): void { - const item = this._getItem(ev.target.itemId); - if (!item) { + private _requestSelected(ev: Event): void { + ev.stopPropagation(); + } + + private _handleKeydown(ev) { + if (ev.key === " ") { + this._completeItem(ev); return; } - updateItem(this.hass!, this._entityId!, { - ...item, - status: ev.target.checked - ? TodoItemStatus.Completed - : TodoItemStatus.NeedsAction, - }); + if (ev.key === "Enter") { + this._openItem(ev); + } } - private _saveEdit(ev): void { - // If name is not empty, update the item otherwise remove it - if (ev.target.value) { - const item = this._getItem(ev.target.itemId); - if (!item) { - return; - } - updateItem(this.hass!, this._entityId!, { - ...item, - summary: ev.target.value, - }); - } else if ( - this.todoListSupportsFeature(TodoListEntityFeature.DELETE_TODO_ITEM) + private _openItem(ev): void { + ev.stopPropagation(); + + if ( + ev + .composedPath() + .find((el) => ["input", "a", "button"].includes(el.localName)) ) { - deleteItems(this.hass!, this._entityId!, [ev.target.itemId]); + return; } - ev.target.blur(); + const item = this._getItem(ev.currentTarget.itemId); + showTodoItemEditDialog(this, { + entity: this._config!.entity!, + item, + }); + } + + private async _completeItem(ev): Promise { + const item = this._getItem(ev.currentTarget.itemId); + if (!item) { + return; + } + await updateItem(this.hass!, this._entityId!, { + ...item, + status: + item.status === TodoItemStatus.NeedsAction + ? TodoItemStatus.Completed + : TodoItemStatus.NeedsAction, + }); + await this.updateComplete; + const newList: List = this.shadowRoot!.querySelector( + item.status === TodoItemStatus.NeedsAction ? "#checked" : "#unchecked" + )!; + await newList.updateComplete; + const items = + item.status === TodoItemStatus.NeedsAction + ? this._getCheckedItems(this._items) + : this._getUncheckedItems(this._items); + const index = items.findIndex((itm) => itm.uid === item.uid); + newList.focusItemAtIndex(index); } private async _clearCompletedItems(): Promise { @@ -464,7 +525,9 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { private _addItem(ev): void { const newItem = this._newItem; if (newItem.value!.length > 0) { - createItem(this.hass!, this._entityId!, newItem.value!); + createItem(this.hass!, this._entityId!, { + summary: newItem.value!, + }); } newItem.value = ""; @@ -557,86 +620,165 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { } static get styles(): CSSResultGroup { - return css` - ha-card { - padding: 16px; - height: 100%; - box-sizing: border-box; - } + return [ + sortableStyles, + css` + ha-card { + height: 100%; + box-sizing: border-box; + } - .has-header { - padding-top: 0; - } + .has-header { + padding-top: 0; + } - .editRow, - .addRow, - .checked { - display: flex; - flex-direction: row; - align-items: center; - } + .addRow { + padding: 16px; + padding-bottom: 0; + position: relative; + } - .item { - margin-top: 8px; - } + .addRow ha-icon-button { + position: absolute; + right: 16px; + inset-inline-start: initial; + inset-inline-end: 16px; + } - .addButton { - margin-left: -12px; - margin-inline-start: -12px; - direction: var(--direction); - } + .addRow, + .header { + display: flex; + flex-direction: row; + align-items: center; + } - .deleteItemButton { - margin-right: -12px; - margin-inline-end: -12px; - direction: var(--direction); - } + .header { + padding-left: 30px; + padding-right: 16px; + padding-inline-start: 30px; + padding-inline-end: 16px; + margin-top: 8px; + justify-content: space-between; + direction: var(--direction); + } - .reorderButton { - margin-right: -12px; - margin-inline-end: -12px; - direction: var(--direction); - } + .header span { + color: var(--primary-text-color); + font-weight: 500; + } - .handle { - cursor: move; - } + .empty { + padding: 16px 32px; + } - ha-checkbox { - margin-left: -12px; - margin-inline-start: -12px; - direction: var(--direction); - } + .item { + margin-top: 8px; + } - ha-textfield { - flex-grow: 1; - } + ha-check-list-item { + --mdc-list-item-meta-size: 56px; + min-height: 56px; + height: auto; + } - .checked { - margin: 12px 0; - justify-content: space-between; - } + ha-check-list-item.multiline { + align-items: flex-start; + --check-list-item-graphic-margin-top: 8px; + } - .checked span { - color: var(--primary-text-color); - font-weight: 500; - } + .row { + display: flex; + justify-content: space-between; + } - .divider { - height: 1px; - background-color: var(--divider-color); - margin: 10px 0; - } + .multiline .column { + display: flex; + flex-direction: column; + margin-top: 18px; + margin-bottom: 12px; + } - .clearall { - cursor: pointer; - } + .completed .summary { + text-decoration: line-through; + } - .todoList { - display: block; - padding: 8px; - } - `; + .description, + .due { + font-size: 12px; + color: var(--secondary-text-color); + } + + .description { + white-space: initial; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 3; + line-clamp: 3; + -webkit-box-orient: vertical; + } + + .description p { + margin: 0; + } + + .description a { + color: var(--primary-color); + } + + .due { + display: flex; + align-items: center; + } + + .due ha-svg-icon { + margin-right: 4px; + --mdc-icon-size: 14px; + } + + .due.overdue { + color: var(--warning-color); + } + + .completed .due.overdue { + color: var(--secondary-text-color); + } + + .handle { + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; + height: 24px; + padding: 16px 4px; + } + + .deleteItemButton { + position: relative; + left: 8px; + } + + ha-textfield { + flex-grow: 1; + } + + .divider { + height: 1px; + background-color: var(--divider-color); + margin: 10px 0; + } + + .clearall { + cursor: pointer; + } + + .todoList { + display: block; + padding: 8px; + } + + .warning { + color: var(--error-color); + } + `, + ]; } } diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index 4dbe071b4523..6a8e6e7dd5ce 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -486,6 +486,8 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { align-items: center; min-width: 64px; margin-right: 16px; + margin-inline-end: 16px; + margin-inline-start: initial; } .icon-image > * { @@ -505,7 +507,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { } .temp-attribute { - text-align: right; + text-align: var(--float-end); } .temp-attribute .temp { @@ -535,6 +537,8 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { .name-state { overflow: hidden; padding-right: 12px; + padding-inline-end: 12px; + padding-inline-start: initial; width: 100%; } @@ -634,6 +638,8 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { :host([narrow]) .temp-attribute .temp { margin-right: 16px; + margin-inline-end: 16px; + margin-inline-start: initial; } :host([narrow]) .temp span { @@ -655,6 +661,8 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { :host([veryNarrow]) .name-state { padding-right: 0; + padding-inline-end: 0; + padding-inline-start: initial; } /* ============= VERY VERY NARROW ============= */ @@ -672,6 +680,8 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { :host([veryVeryNarrow]) .icon-image { margin-right: 0; + margin-inline-end: 0; + margin-inline-start: initial; } `, ]; diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index 0b4b6f04631c..cedd812916ef 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -262,6 +262,7 @@ export interface HumidifierCardConfig extends LovelaceCardConfig { entity: string; theme?: string; name?: string; + show_current_as_primary?: boolean; features?: LovelaceCardFeatureConfig[]; } @@ -455,6 +456,7 @@ export interface ThermostatCardConfig extends LovelaceCardConfig { entity: string; theme?: string; name?: string; + show_current_as_primary?: boolean; features?: LovelaceCardFeatureConfig[]; } diff --git a/src/panels/lovelace/components/hui-entity-editor.ts b/src/panels/lovelace/components/hui-entity-editor.ts index 42aed25312af..22ac4f8aa08d 100644 --- a/src/panels/lovelace/components/hui-entity-editor.ts +++ b/src/panels/lovelace/components/hui-entity-editor.ts @@ -181,7 +181,8 @@ export class HuiEntityEditor extends LitElement { } .entity .handle { padding-right: 8px; - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; padding-inline-end: 8px; padding-inline-start: initial; direction: var(--direction); diff --git a/src/panels/lovelace/create-element/create-card-feature-element.ts b/src/panels/lovelace/create-element/create-card-feature-element.ts index 875a6f357caa..550822143046 100644 --- a/src/panels/lovelace/create-element/create-card-feature-element.ts +++ b/src/panels/lovelace/create-element/create-card-feature-element.ts @@ -1,4 +1,5 @@ import "../card-features/hui-alarm-modes-card-feature"; +import "../card-features/hui-climate-fan-modes-card-feature"; import "../card-features/hui-climate-hvac-modes-card-feature"; import "../card-features/hui-climate-preset-modes-card-feature"; import "../card-features/hui-cover-open-close-card-feature"; @@ -17,6 +18,8 @@ import "../card-features/hui-target-temperature-card-feature"; import "../card-features/hui-target-humidity-card-feature"; import "../card-features/hui-vacuum-commands-card-feature"; import "../card-features/hui-water-heater-operation-modes-card-feature"; +import "../card-features/hui-update-actions-card-feature"; + import { LovelaceCardFeatureConfig } from "../card-features/types"; import { createLovelaceElement, @@ -25,6 +28,7 @@ import { const TYPES: Set = new Set([ "alarm-modes", + "climate-fan-modes", "climate-hvac-modes", "climate-preset-modes", "cover-open-close", @@ -43,6 +47,7 @@ const TYPES: Set = new Set([ "target-temperature", "vacuum-commands", "water-heater-operation-modes", + "update-actions", ]); export const createCardFeatureElement = (config: LovelaceCardFeatureConfig) => diff --git a/src/panels/lovelace/create-element/create-row-element.ts b/src/panels/lovelace/create-element/create-row-element.ts index ed39e06c93e6..091f9b779c1a 100644 --- a/src/panels/lovelace/create-element/create-row-element.ts +++ b/src/panels/lovelace/create-element/create-row-element.ts @@ -49,6 +49,7 @@ const LAZY_LOAD_TYPES = { "time-entity": () => import("../entity-rows/hui-time-entity-row"), "timer-entity": () => import("../entity-rows/hui-timer-entity-row"), "update-entity": () => import("../entity-rows/hui-update-entity-row"), + "valve-entity": () => import("../entity-rows/hui-valve-entity-row"), conditional: () => import("../special-rows/hui-conditional-row"), "weather-entity": () => import("../entity-rows/hui-weather-entity-row"), divider: () => import("../special-rows/hui-divider-row"), @@ -94,6 +95,7 @@ const DOMAIN_TO_ELEMENT_TYPE = { timer: "timer", update: "update", vacuum: "toggle", + valve: "valve", // Temporary. Once climate is rewritten, // water heater should get its own row. water_heater: "climate", diff --git a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts index 9405377c1ad3..49290ba57102 100644 --- a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts @@ -22,6 +22,7 @@ import { sortableStyles } from "../../../../resources/ha-sortable-style"; import type { SortableInstance } from "../../../../resources/sortable"; import { HomeAssistant } from "../../../../types"; import { supportsAlarmModesCardFeature } from "../../card-features/hui-alarm-modes-card-feature"; +import { supportsClimateFanModesCardFeature } from "../../card-features/hui-climate-fan-modes-card-feature"; import { supportsClimateHvacModesCardFeature } from "../../card-features/hui-climate-hvac-modes-card-feature"; import { supportsClimatePresetModesCardFeature } from "../../card-features/hui-climate-preset-modes-card-feature"; import { supportsCoverOpenCloseCardFeature } from "../../card-features/hui-cover-open-close-card-feature"; @@ -29,8 +30,8 @@ import { supportsCoverPositionCardFeature } from "../../card-features/hui-cover- import { supportsCoverTiltCardFeature } from "../../card-features/hui-cover-tilt-card-feature"; import { supportsCoverTiltPositionCardFeature } from "../../card-features/hui-cover-tilt-position-card-feature"; import { supportsFanSpeedCardFeature } from "../../card-features/hui-fan-speed-card-feature"; -import { supportsHumidifierToggleCardFeature } from "../../card-features/hui-humidifier-toggle-card-feature"; import { supportsHumidifierModesCardFeature } from "../../card-features/hui-humidifier-modes-card-feature"; +import { supportsHumidifierToggleCardFeature } from "../../card-features/hui-humidifier-toggle-card-feature"; import { supportsLawnMowerCommandCardFeature } from "../../card-features/hui-lawn-mower-commands-card-feature"; import { supportsLightBrightnessCardFeature } from "../../card-features/hui-light-brightness-card-feature"; import { supportsLightColorTempCardFeature } from "../../card-features/hui-light-color-temp-card-feature"; @@ -42,12 +43,14 @@ import { supportsVacuumCommandsCardFeature } from "../../card-features/hui-vacuu import { supportsWaterHeaterOperationModesCardFeature } from "../../card-features/hui-water-heater-operation-modes-card-feature"; import { LovelaceCardFeatureConfig } from "../../card-features/types"; import { getCardFeatureElementClass } from "../../create-element/create-card-feature-element"; +import { supportsUpdateActionsCardFeature } from "../../card-features/hui-update-actions-card-feature"; export type FeatureType = LovelaceCardFeatureConfig["type"]; type SupportsFeature = (stateObj: HassEntity) => boolean; const UI_FEATURE_TYPES = [ "alarm-modes", + "climate-fan-modes", "climate-hvac-modes", "climate-preset-modes", "cover-open-close", @@ -64,6 +67,7 @@ const UI_FEATURE_TYPES = [ "target-humidity", "target-temperature", "vacuum-commands", + "update-actions", "water-heater-operation-modes", "numeric-input", ] as const satisfies readonly FeatureType[]; @@ -79,6 +83,7 @@ const EDITABLES_FEATURE_TYPES = new Set([ "lawn-mower-commands", "climate-preset-modes", "numeric-input", + "update-actions", ]); const SUPPORTS_FEATURE_TYPES: Record< @@ -86,6 +91,7 @@ const SUPPORTS_FEATURE_TYPES: Record< SupportsFeature | undefined > = { "alarm-modes": supportsAlarmModesCardFeature, + "climate-fan-modes": supportsClimateFanModesCardFeature, "climate-hvac-modes": supportsClimateHvacModesCardFeature, "climate-preset-modes": supportsClimatePresetModesCardFeature, "cover-open-close": supportsCoverOpenCloseCardFeature, @@ -104,6 +110,7 @@ const SUPPORTS_FEATURE_TYPES: Record< "vacuum-commands": supportsVacuumCommandsCardFeature, "water-heater-operation-modes": supportsWaterHeaterOperationModesCardFeature, "select-options": supportsSelectOptionsCardFeature, + "update-actions": supportsUpdateActionsCardFeature, }; const customCardFeatures = getCustomCardFeatures(); @@ -453,7 +460,8 @@ export class HuiCardFeaturesEditor extends LitElement { } .feature .handle { padding-right: 8px; - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; padding-inline-end: 8px; padding-inline-start: initial; direction: var(--direction); diff --git a/src/panels/lovelace/editor/config-elements/hui-climate-fan-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-climate-fan-modes-card-feature-editor.ts new file mode 100644 index 000000000000..3316c26b5c47 --- /dev/null +++ b/src/panels/lovelace/editor/config-elements/hui-climate-fan-modes-card-feature-editor.ts @@ -0,0 +1,129 @@ +import { HassEntity } from "home-assistant-js-websocket"; +import { html, LitElement, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../../../../common/dom/fire_event"; +import { FormatEntityAttributeValueFunc } from "../../../../common/translations/entity-state"; +import { LocalizeFunc } from "../../../../common/translations/localize"; +import "../../../../components/ha-form/ha-form"; +import type { + HaFormSchema, + SchemaUnion, +} from "../../../../components/ha-form/types"; +import type { HomeAssistant } from "../../../../types"; +import { + ClimateFanModesCardFeatureConfig, + LovelaceCardFeatureContext, +} from "../../card-features/types"; +import type { LovelaceCardFeatureEditor } from "../../types"; + +@customElement("hui-climate-fan-modes-card-feature-editor") +export class HuiClimateFanModesCardFeatureEditor + extends LitElement + implements LovelaceCardFeatureEditor +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public context?: LovelaceCardFeatureContext; + + @state() private _config?: ClimateFanModesCardFeatureConfig; + + public setConfig(config: ClimateFanModesCardFeatureConfig): void { + this._config = config; + } + + private _schema = memoizeOne( + ( + localize: LocalizeFunc, + formatEntityAttributeValue: FormatEntityAttributeValueFunc, + stateObj?: HassEntity + ) => + [ + { + name: "style", + selector: { + select: { + multiple: false, + mode: "list", + options: ["dropdown", "icons"].map((mode) => ({ + value: mode, + label: localize( + `ui.panel.lovelace.editor.features.types.climate-fan-modes.style_list.${mode}` + ), + })), + }, + }, + }, + { + name: "fan_modes", + selector: { + select: { + multiple: true, + mode: "list", + options: + stateObj?.attributes.fan_modes?.map((mode) => ({ + value: mode, + label: formatEntityAttributeValue(stateObj, "fan_mode", mode), + })) || [], + }, + }, + }, + ] as const satisfies readonly HaFormSchema[] + ); + + protected render() { + if (!this.hass || !this._config) { + return nothing; + } + + const stateObj = this.context?.entity_id + ? this.hass.states[this.context?.entity_id] + : undefined; + + const data: ClimateFanModesCardFeatureConfig = { + style: "dropdown", + fan_modes: [], + ...this._config, + }; + + const schema = this._schema( + this.hass.localize, + this.hass.formatEntityAttributeValue, + stateObj + ); + + return html` + + `; + } + + private _valueChanged(ev: CustomEvent): void { + fireEvent(this, "config-changed", { config: ev.detail.value }); + } + + private _computeLabelCallback = ( + schema: SchemaUnion> + ) => { + switch (schema.name) { + case "style": + case "fan_modes": + return this.hass!.localize( + `ui.panel.lovelace.editor.features.types.climate-fan-modes.${schema.name}` + ); + default: + return ""; + } + }; +} + +declare global { + interface HTMLElementTagNameMap { + "hui-climate-fan-modes-card-feature-editor": HuiClimateFanModesCardFeatureEditor; + } +} diff --git a/src/panels/lovelace/editor/config-elements/hui-humidifier-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-humidifier-card-editor.ts index 3e052d9a64ea..fb8543a0c83f 100644 --- a/src/panels/lovelace/editor/config-elements/hui-humidifier-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-humidifier-card-editor.ts @@ -6,13 +6,17 @@ import { array, assert, assign, + boolean, object, optional, string, } from "superstruct"; import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-form/ha-form"; -import type { SchemaUnion } from "../../../../components/ha-form/types"; +import type { + HaFormSchema, + SchemaUnion, +} from "../../../../components/ha-form/types"; import type { HomeAssistant } from "../../../../types"; import { LovelaceCardFeatureConfig, @@ -37,6 +41,7 @@ const cardConfigStruct = assign( entity: optional(string()), name: optional(string()), theme: optional(string()), + show_current_as_primary: optional(boolean()), features: optional(array(any())), }) ); @@ -55,7 +60,13 @@ const SCHEMA = [ { name: "theme", selector: { theme: {} } }, ], }, -] as const; + { + name: "show_current_as_primary", + selector: { + boolean: {}, + }, + }, +] as const satisfies readonly HaFormSchema[]; @customElement("hui-humidifier-card-editor") export class HuiHumidifierCardEditor @@ -179,20 +190,12 @@ export class HuiHumidifierCardEditor } private _computeLabelCallback = (schema: SchemaUnion) => { - if (schema.name === "entity") { + if (schema.name === "show_current_as_primary") { return this.hass!.localize( - "ui.panel.lovelace.editor.card.generic.entity" + "ui.panel.lovelace.editor.card.humidifier.show_current_as_primary" ); } - if (schema.name === "theme") { - return `${this.hass!.localize( - "ui.panel.lovelace.editor.card.generic.theme" - )} (${this.hass!.localize( - "ui.panel.lovelace.editor.card.config.optional" - )})`; - } - return this.hass!.localize( `ui.panel.lovelace.editor.card.generic.${schema.name}` ); diff --git a/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts index a2f33e6b59cf..a126496d0aa8 100644 --- a/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-thermostat-card-editor.ts @@ -6,19 +6,23 @@ import { array, assert, assign, + boolean, object, optional, string, } from "superstruct"; import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-form/ha-form"; -import type { SchemaUnion } from "../../../../components/ha-form/types"; +import type { + HaFormSchema, + SchemaUnion, +} from "../../../../components/ha-form/types"; import type { HomeAssistant } from "../../../../types"; -import type { ThermostatCardConfig } from "../../cards/types"; import { LovelaceCardFeatureConfig, LovelaceCardFeatureContext, } from "../../card-features/types"; +import type { ThermostatCardConfig } from "../../cards/types"; import type { LovelaceCardEditor } from "../../types"; import "../hui-sub-element-editor"; import { baseLovelaceCardConfig } from "../structs/base-card-struct"; @@ -29,6 +33,7 @@ import type { FeatureType } from "./hui-card-features-editor"; const COMPATIBLE_FEATURES_TYPES: FeatureType[] = [ "climate-hvac-modes", "climate-preset-modes", + "climate-fan-modes", ]; const cardConfigStruct = assign( @@ -37,6 +42,7 @@ const cardConfigStruct = assign( entity: optional(string()), name: optional(string()), theme: optional(string()), + show_current_as_primary: optional(boolean()), features: optional(array(any())), }) ); @@ -51,7 +57,13 @@ const SCHEMA = [ { name: "theme", selector: { theme: {} } }, ], }, -] as const; + { + name: "show_current_as_primary", + selector: { + boolean: {}, + }, + }, +] as const satisfies readonly HaFormSchema[]; @customElement("hui-thermostat-card-editor") export class HuiThermostatCardEditor @@ -175,9 +187,9 @@ export class HuiThermostatCardEditor } private _computeLabelCallback = (schema: SchemaUnion) => { - if (schema.name === "entity") { + if (schema.name === "show_current_as_primary") { return this.hass!.localize( - "ui.panel.lovelace.editor.card.generic.entity" + "ui.panel.lovelace.editor.card.thermostat.show_current_as_primary" ); } diff --git a/src/panels/lovelace/editor/config-elements/hui-update-actions-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-update-actions-card-feature-editor.ts new file mode 100644 index 000000000000..f1478f090efa --- /dev/null +++ b/src/panels/lovelace/editor/config-elements/hui-update-actions-card-feature-editor.ts @@ -0,0 +1,131 @@ +import { html, LitElement, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../../../../common/dom/fire_event"; +import type { LocalizeFunc } from "../../../../common/translations/localize"; +import "../../../../components/ha-form/ha-form"; +import type { SchemaUnion } from "../../../../components/ha-form/types"; +import type { HomeAssistant } from "../../../../types"; +import { + LovelaceCardFeatureContext, + UpdateActionsCardFeatureConfig, +} from "../../card-features/types"; +import type { LovelaceCardFeatureEditor } from "../../types"; +import { supportsFeature } from "../../../../common/entity/supports-feature"; +import { UpdateEntityFeature } from "../../../../data/update"; +import { DEFAULT_UPDATE_BACKUP_OPTION } from "../../card-features/hui-update-actions-card-feature"; + +@customElement("hui-update-actions-card-feature-editor") +export class HuiUpdateActionsCardFeatureEditor + extends LitElement + implements LovelaceCardFeatureEditor +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public context?: LovelaceCardFeatureContext; + + @state() private _config?: UpdateActionsCardFeatureConfig; + + public setConfig(config: UpdateActionsCardFeatureConfig): void { + this._config = config; + } + + private _schema = memoizeOne( + (localize: LocalizeFunc, supportsBackup: boolean) => + [ + { + name: "backup", + disabled: !supportsBackup, + selector: { + select: { + default: "yes", + mode: "dropdown", + options: ["ask", "yes", "no"].map((option) => ({ + value: option, + label: localize( + `ui.panel.lovelace.editor.features.types.update-actions.backup_options.${option}` + ), + })), + }, + }, + }, + ] as const + ); + + private get _stateObj() { + return this.context?.entity_id + ? this.hass!.states[this.context?.entity_id] + : undefined; + } + + protected render() { + if (!this.hass || !this._config) { + return nothing; + } + + const supportsBackup = + this._stateObj != null && + supportsFeature(this._stateObj, UpdateEntityFeature.BACKUP); + + const schema = this._schema(this.hass.localize, supportsBackup); + + const data = { ...this._config }; + + if (!this._config.backup && supportsBackup) { + data.backup = DEFAULT_UPDATE_BACKUP_OPTION; + } + + return html` + + `; + } + + private _valueChanged(ev: CustomEvent): void { + fireEvent(this, "config-changed", { config: ev.detail.value }); + } + + private _computeLabelCallback = ( + schema: SchemaUnion> + ) => { + switch (schema.name) { + case "backup": + return this.hass!.localize( + `ui.panel.lovelace.editor.features.types.update-actions.${schema.name}` + ); + default: + return ""; + } + }; + + private _computeHelperCallback = ( + schema: SchemaUnion> + ) => { + const supportsBackup = + this._stateObj != null && + supportsFeature(this._stateObj, UpdateEntityFeature.BACKUP); + + switch (schema.name) { + case "backup": + if (!supportsBackup) { + return this.hass!.localize( + "ui.panel.lovelace.editor.features.types.update-actions.backup_not_supported" + ); + } + return undefined; + } + return undefined; + }; +} + +declare global { + interface HTMLElementTagNameMap { + "hui-update-actions-card-feature-editor": HuiUpdateActionsCardFeatureEditor; + } +} diff --git a/src/panels/lovelace/editor/hui-entities-card-row-editor.ts b/src/panels/lovelace/editor/hui-entities-card-row-editor.ts index 8e06e231af7b..231305a1a3aa 100644 --- a/src/panels/lovelace/editor/hui-entities-card-row-editor.ts +++ b/src/panels/lovelace/editor/hui-entities-card-row-editor.ts @@ -243,7 +243,8 @@ export class HuiEntitiesCardRowEditor extends LitElement { .entity .handle { padding-right: 8px; - cursor: move; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; padding-inline-end: 8px; padding-inline-start: initial; direction: var(--direction); diff --git a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts index 419bac0d7bc8..0fd083aaed5f 100644 --- a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts @@ -208,10 +208,7 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { > ` : !supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_SET) && - !supportsFeature( - stateObj, - MediaPlayerEntityFeature.VOLUME_BUTTONS - ) + !supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_STEP) ? buttons : ""} ${supportsFeature(stateObj, MediaPlayerEntityFeature.TURN_OFF) && @@ -226,8 +223,8 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { : ""}
    - ${(supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_SET) || - supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_BUTTONS)) && + ${(supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_STEP) || + supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_SET)) && stateActive(stateObj) ? html`
    @@ -266,7 +263,7 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { : !this._veryNarrow && supportsFeature( stateObj, - MediaPlayerEntityFeature.VOLUME_BUTTONS + MediaPlayerEntityFeature.VOLUME_STEP ) ? html` + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + + `; + } + + return html` + + + + `; + } + + static get styles(): CSSResultGroup { + return css` + ha-valve-controls { + margin-right: -0.57em; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-valve-entity-row": HuiValveEntityRow; + } +} diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts new file mode 100644 index 000000000000..cd26ad35fc28 --- /dev/null +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -0,0 +1,441 @@ +import "@material/mwc-button"; +import { formatInTimeZone, toDate } from "date-fns-tz"; +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"; +import { supportsFeature } from "../../common/entity/supports-feature"; +import "../../components/ha-date-input"; +import { createCloseHeading } from "../../components/ha-dialog"; +import "../../components/ha-textarea"; +import "../../components/ha-time-input"; +import { + TodoItemStatus, + TodoListEntityFeature, + createItem, + deleteItems, + updateItem, +} from "../../data/todo"; +import { TimeZone } from "../../data/translation"; +import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box"; +import { haStyleDialog } from "../../resources/styles"; +import { HomeAssistant } from "../../types"; +import { TodoItemEditDialogParams } from "./show-dialog-todo-item-editor"; + +@customElement("dialog-todo-item-editor") +class DialogTodoItemEditor extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @state() private _error?: string; + + @state() private _params?: TodoItemEditDialogParams; + + @state() private _summary = ""; + + @state() private _description? = ""; + + @state() private _due?: Date; + + @state() private _checked = false; + + @state() private _hasTime = false; + + @state() private _submitting = false; + + // Dates are manipulated and displayed in the browser timezone + // which may be different from the Home Assistant timezone. When + // events are persisted, they are relative to the Home Assistant + // timezone, but floating without a timezone. + private _timeZone?: string; + + public showDialog(params: TodoItemEditDialogParams): void { + this._error = undefined; + this._params = params; + this._timeZone = + this.hass.locale.time_zone === TimeZone.local + ? Intl.DateTimeFormat().resolvedOptions().timeZone + : this.hass.config.time_zone; + if (params.item) { + const entry = params.item; + this._checked = entry.status === TodoItemStatus.Completed; + this._summary = entry.summary; + this._description = entry.description || ""; + this._due = entry.due ? new Date(entry.due) : undefined; + this._hasTime = entry.due?.includes("T") || false; + } else { + this._hasTime = false; + this._checked = false; + this._due = undefined; + } + } + + public closeDialog(): void { + if (!this._params) { + return; + } + this._error = undefined; + this._params = undefined; + this._due = undefined; + this._summary = ""; + this._description = ""; + this._hasTime = false; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + protected render() { + if (!this._params) { + return nothing; + } + const isCreate = this._params.item === undefined; + + const { dueDate, dueTime } = this._getLocaleStrings(this._due); + + const canUpdate = this._todoListSupportsFeature( + TodoListEntityFeature.UPDATE_TODO_ITEM + ); + + return html` + +
    + ${this._error + ? html`${this._error}` + : ""} + +
    + + +
    + ${this._todoListSupportsFeature( + TodoListEntityFeature.SET_DESCRIPTION_ON_ITEM + ) + ? html`` + : nothing} + ${this._todoListSupportsFeature( + TodoListEntityFeature.SET_DUE_DATE_ON_ITEM + ) || + this._todoListSupportsFeature( + TodoListEntityFeature.SET_DUE_DATETIME_ON_ITEM + ) + ? html`
    + ${this.hass.localize("ui.components.todo.item.due")}: +
    + + ${this._todoListSupportsFeature( + TodoListEntityFeature.SET_DUE_DATETIME_ON_ITEM + ) + ? html`` + : nothing} +
    +
    ` + : nothing} +
    + ${isCreate + ? html` + + ${this.hass.localize("ui.components.todo.item.add")} + + ` + : html` + + ${this.hass.localize("ui.components.todo.item.save")} + + ${this._todoListSupportsFeature( + TodoListEntityFeature.DELETE_TODO_ITEM + ) + ? html` + + ${this.hass.localize("ui.components.todo.item.delete")} + + ` + : ""} + `} +
    + `; + } + + private _todoListSupportsFeature(feature: number): boolean { + if (!this._params?.entity) { + return false; + } + const entityStateObj = this.hass!.states[this._params?.entity]; + return entityStateObj && supportsFeature(entityStateObj, feature); + } + + private _getLocaleStrings = memoizeOne((due?: Date) => ({ + dueDate: due ? this._formatDate(due) : undefined, + dueTime: due ? this._formatTime(due) : undefined, + })); + + // Formats a date in specified timezone, or defaulting to browser display timezone + private _formatDate(date: Date, timeZone: string = this._timeZone!): string { + return formatInTimeZone(date, timeZone, "yyyy-MM-dd"); + } + + // Formats a time in specified timezone, or defaulting to browser display timezone + private _formatTime( + date: Date, + timeZone: string = this._timeZone! + ): string | undefined { + return this._hasTime + ? formatInTimeZone(date, timeZone, "HH:mm:ss") + : undefined; // 24 hr + } + + // Parse a date in the browser timezone + private _parseDate(dateStr: string): Date { + return toDate(dateStr, { timeZone: this._timeZone! }); + } + + private _checkedCanged(ev) { + this._checked = ev.target.checked; + } + + private _handleSummaryChanged(ev) { + this._summary = ev.target.value; + } + + private _handleDescriptionChanged(ev) { + this._description = ev.target.value; + } + + private _dueDateChanged(ev: CustomEvent) { + if (!ev.detail.value) { + this._due = undefined; + return; + } + const time = this._due ? this._formatTime(this._due) : undefined; + this._due = this._parseDate(`${ev.detail.value}${time ? `T${time}` : ""}`); + } + + private _dueTimeChanged(ev: CustomEvent) { + this._hasTime = true; + this._due = this._parseDate( + `${this._formatDate(this._due || new Date())}T${ev.detail.value}` + ); + } + + private async _createItem() { + if (!this._summary) { + this._error = this.hass.localize( + "ui.components.todo.item.not_all_required_fields" + ); + return; + } + + this._submitting = true; + try { + await createItem(this.hass!, this._params!.entity, { + summary: this._summary, + description: this._description, + due: this._due + ? this._hasTime + ? this._due.toISOString() + : this._formatDate(this._due) + : undefined, + }); + } catch (err: any) { + this._error = err ? err.message : "Unknown error"; + return; + } finally { + this._submitting = false; + } + this.closeDialog(); + } + + private async _saveItem() { + if (!this._summary) { + this._error = this.hass.localize( + "ui.components.todo.item.not_all_required_fields" + ); + return; + } + + this._submitting = true; + const entry = this._params!.item!; + + try { + await updateItem(this.hass!, this._params!.entity, { + ...entry, + summary: this._summary, + description: + this._description || + (this._todoListSupportsFeature( + TodoListEntityFeature.SET_DESCRIPTION_ON_ITEM + ) + ? // backend should accept null to clear the field, but it doesn't now + null + : undefined), + due: this._due + ? this._hasTime + ? this._due.toISOString() + : this._formatDate(this._due) + : null, + status: this._checked + ? TodoItemStatus.Completed + : TodoItemStatus.NeedsAction, + }); + } catch (err: any) { + this._error = err ? err.message : "Unknown error"; + return; + } finally { + this._submitting = false; + } + this.closeDialog(); + } + + private async _deleteItem() { + this._submitting = true; + const entry = this._params!.item!; + const confirm = await showConfirmationDialog(this, { + title: this.hass.localize( + "ui.components.todo.item.confirm_delete.delete" + ), + text: this.hass.localize("ui.components.todo.item.confirm_delete.prompt"), + }); + if (!confirm) { + // Cancel + this._submitting = false; + return; + } + try { + await deleteItems(this.hass!, this._params!.entity, [entry.uid]); + } catch (err: any) { + this._error = err ? err.message : "Unknown error"; + return; + } finally { + this._submitting = false; + } + this.closeDialog(); + } + + static get styles(): CSSResultGroup { + return [ + haStyleDialog, + css` + @media all and (min-width: 450px and min-height: 500px) { + ha-dialog { + --mdc-dialog-min-width: min(600px, 95vw); + --mdc-dialog-max-width: min(600px, 95vw); + } + } + ha-alert { + display: block; + margin-bottom: 16px; + } + ha-textfield, + ha-textarea { + display: block; + width: 100%; + } + ha-checkbox { + margin-top: 4px; + } + ha-textarea { + margin-bottom: 16px; + } + ha-date-input { + flex-grow: 1; + } + ha-time-input { + margin-left: 16px; + } + .flex { + display: flex; + justify-content: space-between; + } + .label { + font-size: 12px; + font-weight: 500; + color: var(--input-label-ink-color); + } + .date-range-details-content { + display: inline-block; + } + ha-svg-icon { + width: 40px; + margin-right: 8px; + margin-inline-end: 16px; + margin-inline-start: initial; + direction: var(--direction); + vertical-align: top; + } + .key { + display: inline-block; + vertical-align: top; + } + .value { + display: inline-block; + vertical-align: top; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-todo-item-editor": DialogTodoItemEditor; + } +} diff --git a/src/panels/todo/ha-panel-todo.ts b/src/panels/todo/ha-panel-todo.ts index ba03971c12e8..0023cf105b5e 100644 --- a/src/panels/todo/ha-panel-todo.ts +++ b/src/panels/todo/ha-panel-todo.ts @@ -23,7 +23,14 @@ import { isComponentLoaded } from "../../common/config/is_component_loaded"; import { storage } from "../../common/decorators/storage"; import { fireEvent } from "../../common/dom/fire_event"; import { computeStateName } from "../../common/entity/compute_state_name"; +import { navigate } from "../../common/navigate"; +import { constructUrlCurrentPath } from "../../common/url/construct-url"; +import { + createSearchParam, + extractSearchParam, +} from "../../common/url/search-params"; import "../../components/ha-button"; +import "../../components/ha-fab"; import "../../components/ha-icon-button"; import "../../components/ha-list-item"; import "../../components/ha-menu-button"; @@ -33,7 +40,7 @@ import "../../components/ha-two-pane-top-app-bar-fixed"; import { deleteConfigEntry } from "../../data/config_entries"; import { getExtendedEntityRegistryEntry } from "../../data/entity_registry"; import { fetchIntegrationManifest } from "../../data/integration"; -import { getTodoLists } from "../../data/todo"; +import { TodoListEntityFeature, getTodoLists } from "../../data/todo"; import { showConfigFlowDialog } from "../../dialogs/config-flow/show-dialog-config-flow"; import { showAlertDialog, @@ -45,12 +52,8 @@ import { HomeAssistant } from "../../types"; import { HuiErrorCard } from "../lovelace/cards/hui-error-card"; import { createCardElement } from "../lovelace/create-element/create-card-element"; import { LovelaceCard } from "../lovelace/types"; -import { navigate } from "../../common/navigate"; -import { - createSearchParam, - extractSearchParam, -} from "../../common/url/search-params"; -import { constructUrlCurrentPath } from "../../common/url/construct-url"; +import { showTodoItemEditDialog } from "./show-dialog-todo-item-editor"; +import { supportsFeature } from "../../common/entity/supports-feature"; @customElement("ha-panel-todo") class PanelTodo extends LitElement { @@ -152,6 +155,9 @@ class PanelTodo extends LitElement { const entityRegistryEntry = this._entityId ? this.hass.entities[this._entityId] : undefined; + const entityState = this._entityId + ? this.hass.states[this._entityId] + : undefined; const showPane = this._showPaneController.value ?? !this.narrow; const listItems = getTodoLists(this.hass).map( (list) => @@ -187,8 +193,8 @@ class PanelTodo extends LitElement {
    ${this._entityId - ? this._entityId in this.hass.states - ? computeStateName(this.hass.states[this._entityId]) + ? entityState + ? computeStateName(entityState) : this._entityId : ""}
    @@ -255,6 +261,16 @@ class PanelTodo extends LitElement {
    ${this._card}
    + ${entityState && + supportsFeature(entityState, TodoListEntityFeature.CREATE_TODO_ITEM) + ? html` + + ` + : nothing} `; } @@ -329,6 +345,10 @@ class PanelTodo extends LitElement { showVoiceCommandDialog(this, this.hass, { pipeline_id: "last_used" }); } + private _addItem() { + showTodoItemEditDialog(this, { entity: this._entityId! }); + } + static get styles(): CSSResultGroup { return [ haStyle, @@ -341,6 +361,7 @@ class PanelTodo extends LitElement { flex-direction: row; justify-content: center; margin: 8px; + padding-bottom: 70px; } .column { flex: 1 0 0; @@ -390,6 +411,11 @@ class PanelTodo extends LitElement { white-space: nowrap; display: block; } + ha-fab { + position: fixed; + right: 16px; + bottom: 16px; + } `, ]; } diff --git a/src/panels/todo/show-dialog-todo-item-editor.ts b/src/panels/todo/show-dialog-todo-item-editor.ts new file mode 100644 index 000000000000..4560df8f6e2d --- /dev/null +++ b/src/panels/todo/show-dialog-todo-item-editor.ts @@ -0,0 +1,20 @@ +import { fireEvent } from "../../common/dom/fire_event"; +import { TodoItem } from "../../data/todo"; + +export interface TodoItemEditDialogParams { + entity: string; + item?: TodoItem; +} + +export const loadTodoItemEditDialog = () => import("./dialog-todo-item-editor"); + +export const showTodoItemEditDialog = ( + element: HTMLElement, + detailParams: TodoItemEditDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "dialog-todo-item-editor", + dialogImport: loadTodoItemEditDialog, + dialogParams: detailParams, + }); +}; diff --git a/src/resources/codemirror.ts b/src/resources/codemirror.ts index b63a3d0be2ff..ad3e48b852ed 100644 --- a/src/resources/codemirror.ts +++ b/src/resources/codemirror.ts @@ -113,11 +113,10 @@ export const haTheme = EditorView.theme({ border: "0", background: "none", fontFamily: "Roboto", - borderBottom: - "1px solid var(--paper-input-container-color, var(--secondary-text-color))", + borderBottom: "1px solid var(--secondary-text-color)", margin: "4px 4px 0", "& ::placeholder": { - color: "var(--paper-input-container-color, var(--secondary-text-color))", + color: "var(--secondary-text-color)", }, "&:focus": { outline: "none", @@ -185,13 +184,11 @@ export const haTheme = EditorView.theme({ "var(--code-editor-gutter-color, var(--secondary-background-color, whitesmoke))", color: "var(--paper-dialog-color, var(--secondary-text-color))", border: "none", - borderRight: - "1px solid var(--paper-input-container-color, var(--secondary-text-color))", + borderRight: "1px solid var(--secondary-text-color)", paddingRight: "1px", }, "&.cm-focused .cm-gutters": { - borderRight: - "2px solid var(--paper-input-container-focus-color, var(--primary-color))", + borderRight: "2px solid var(--primary-color)", paddingRight: "0", }, ".cm-gutterElement.lineNumber": { color: "inherit" }, diff --git a/src/resources/ha-sortable-style.ts b/src/resources/ha-sortable-style.ts index 8c7a5ded7c7b..a1fcfe920900 100644 --- a/src/resources/ha-sortable-style.ts +++ b/src/resources/ha-sortable-style.ts @@ -34,14 +34,22 @@ export const sortableStyles = css` .sortable-fallback { display: none; + opacity: 0; } .sortable-ghost { + border: 2px solid var(--primary-color); + background: rgba(var(--rgb-primary-color), 0.25); + border-radius: 4px; opacity: 0.4; } - .sortable-fallback { - opacity: 0; + .sortable-drag { + border-radius: 4px; + opacity: 1; + background: var(--card-background-color); + box-shadow: 0px 4px 8px 3px #00000026; + cursor: grabbing; } @keyframes keyframes1 { diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index fa4841c7558d..21d9b18214b8 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -174,6 +174,7 @@ const mainStyles = css` --state-switch-active-color: var(--amber-color); --state-update-active-color: var(--orange-color); --state-vacuum-active-color: var(--teal-color); + --state-valve-active-color: var(--blue-color); --state-sensor-battery-high-color: var(--green-color); --state-sensor-battery-low-color: var(--red-color); --state-sensor-battery-medium-color: var(--orange-color); diff --git a/src/resources/markdown-worker.ts b/src/resources/markdown-worker.ts index a2e2234ecaba..85949e3f2307 100644 --- a/src/resources/markdown-worker.ts +++ b/src/resources/markdown-worker.ts @@ -42,6 +42,14 @@ const renderMarkdown = async ( "ha-icon": ["icon"], "ha-svg-icon": ["path"], "ha-alert": ["alert-type", "title"], + "ha-qr-code": [ + "data", + "scale", + "width", + "margin", + "error-correction-level", + "center-image", + ], }; } diff --git a/src/state-control/climate/ha-state-control-climate-temperature.ts b/src/state-control/climate/ha-state-control-climate-temperature.ts index 0975b1bd9944..7634fd2f2d18 100644 --- a/src/state-control/climate/ha-state-control-climate-temperature.ts +++ b/src/state-control/climate/ha-state-control-climate-temperature.ts @@ -1,5 +1,12 @@ -import { mdiMinus, mdiPlus, mdiThermometer } from "@mdi/js"; -import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit"; +import { mdiMinus, mdiPlus, mdiThermometer, mdiThermostat } from "@mdi/js"; +import { + CSSResultGroup, + LitElement, + PropertyValues, + css, + html, + nothing, +} from "lit"; import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { styleMap } from "lit/directives/style-map"; @@ -8,6 +15,8 @@ import { stateActive } from "../../common/entity/state_active"; import { stateColorCss } from "../../common/entity/state_color"; import { supportsFeature } from "../../common/entity/supports-feature"; import { clamp } from "../../common/number/clamp"; +import { formatNumber } from "../../common/number/format_number"; +import { blankBeforeUnit } from "../../common/translations/blank_before_unit"; import { debounce } from "../../common/util/debounce"; import "../../components/ha-big-number"; import "../../components/ha-control-circular-slider"; @@ -45,8 +54,11 @@ export class HaStateControlClimateTemperature extends LitElement { @property({ attribute: false }) public stateObj!: ClimateEntity; - @property({ attribute: "show-current", type: Boolean }) - public showCurrent?: boolean; + @property({ attribute: "show-secondary", type: Boolean }) + public showSecondary?: boolean; + + @property({ attribute: "use-current-as-primary", type: Boolean }) + public showCurrentAsPrimary?: boolean; @property({ type: Boolean, attribute: "prevent-interaction-on-scroll" }) public preventInteractionOnScroll?: boolean; @@ -163,36 +175,13 @@ export class HaStateControlClimateTemperature extends LitElement { `; } - if ( - (!supportsFeature( - this.stateObj, - ClimateEntityFeature.TARGET_TEMPERATURE - ) || - this._targetTemperature.value === null) && - (!supportsFeature( - this.stateObj, - ClimateEntityFeature.TARGET_TEMPERATURE_RANGE - ) || - this._targetTemperature.low === null || - this._targetTemperature.high === null) - ) { - return html` -

    ${this.hass.formatEntityState(this.stateObj)}

    - `; - } - const action = this.stateObj.attributes.hvac_action; - const actionLabel = this.hass.formatEntityAttributeValue( - this.stateObj, - "hvac_action" - ); - return html`

    - ${action && action !== "off" && action !== "idle" - ? actionLabel - : this.hass.localize("ui.card.climate.target")} + ${action + ? this.hass.formatEntityAttributeValue(this.stateObj, "hvac_action") + : this.hass.formatEntityState(this.stateObj)}

    `; } @@ -234,52 +223,175 @@ export class HaStateControlClimateTemperature extends LitElement { `; } - private _renderTargetTemperature(temperature: number) { + private _renderTarget( + temperature: number, + style: "normal" | "big", + hideUnit?: boolean + ) { const digits = this._step.toString().split(".")?.[1]?.length ?? 0; const formatOptions: Intl.NumberFormatOptions = { maximumFractionDigits: digits, minimumFractionDigits: digits, }; - return html` - - `; + + const unit = hideUnit ? "" : this.hass.config.unit_system.temperature; + + if (style === "big") { + return html` + + `; + } + + const formatted = formatNumber( + temperature, + this.hass.locale, + formatOptions + ); + return html`${formatted}${blankBeforeUnit(unit)}${unit}`; } - private _renderCurrentTemperature(temperature?: number) { - if (!this.showCurrent || temperature == null) { - return html`

     

    `; + private _renderCurrent(temperature: number, style: "normal" | "big") { + const formatOptions: Intl.NumberFormatOptions = { + maximumFractionDigits: 1, + }; + if (style === "big") { + return html` + + `; } return html` -

    - - - ${this.hass.formatEntityAttributeValue( - this.stateObj, - "current_temperature", - temperature - )} - -

    + ${this.hass.formatEntityAttributeValue( + this.stateObj, + "current_temperature", + temperature + )} `; } - protected render() { - const supportsTargetTemperature = supportsFeature( - this.stateObj, - ClimateEntityFeature.TARGET_TEMPERATURE + private _renderPrimary() { + const currentTemperature = this.stateObj.attributes.current_temperature; + + if (currentTemperature != null && this.showCurrentAsPrimary) { + return this._renderCurrent(currentTemperature, "big"); + } + + if (this._supportsTargetTemperature && !this.showCurrentAsPrimary) { + return this._renderTarget(this._targetTemperature.value!, "big"); + } + + if (this._supportsTargetTemperatureRange && !this.showCurrentAsPrimary) { + return html` +
    + + +
    + `; + } + + return nothing; + } + + private _renderSecondary() { + if (!this.showSecondary) { + return html`

    `; + } + + const currentTemperature = this.stateObj.attributes.current_temperature; + + if (currentTemperature && !this.showCurrentAsPrimary) { + return html` +

    + + ${this._renderCurrent(currentTemperature, "normal")} +

    + `; + } + + if (this._supportsTargetTemperature && this.showCurrentAsPrimary) { + return html` +

    + + ${this._renderTarget(this._targetTemperature.value!, "normal")} +

    + `; + } + + if (this._supportsTargetTemperatureRange && this.showCurrentAsPrimary) { + return html` +

    + + + + +

    + `; + } + + return html`

    `; + } + + get _supportsTargetTemperature() { + return ( + supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE) && + this._targetTemperature.value != null ); + } - const supportsTargetTemperatureRange = supportsFeature( - this.stateObj, - ClimateEntityFeature.TARGET_TEMPERATURE_RANGE + get _supportsTargetTemperatureRange() { + return ( + supportsFeature( + this.stateObj, + ClimateEntityFeature.TARGET_TEMPERATURE_RANGE + ) && + this._targetTemperature.low != null && + this._targetTemperature.high != null ); + } + protected render() { const mode = this.stateObj.state; const action = this.stateObj.attributes.hvac_action; const active = stateActive(this.stateObj); @@ -301,8 +413,7 @@ export class HaStateControlClimateTemperature extends LitElement { : ""; if ( - supportsTargetTemperature && - this._targetTemperature.value != null && + this._supportsTargetTemperature && this.stateObj.state !== UNAVAILABLE ) { const heatCoolModes = this.stateObj.attributes.hvac_modes.filter((m) => @@ -337,11 +448,7 @@ export class HaStateControlClimateTemperature extends LitElement { >
    - ${this._renderLabel()} - ${this._renderTargetTemperature(this._targetTemperature.value)} - ${this._renderCurrentTemperature( - this.stateObj.attributes.current_temperature - )} + ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
    ${this._renderTemperatureButtons("value")}
    @@ -349,9 +456,7 @@ export class HaStateControlClimateTemperature extends LitElement { } if ( - supportsTargetTemperatureRange && - this._targetTemperature.low != null && - this._targetTemperature.high != null && + this._supportsTargetTemperatureRange && this.stateObj.state !== UNAVAILABLE ) { return html` @@ -380,30 +485,7 @@ export class HaStateControlClimateTemperature extends LitElement { >
    - ${this._renderLabel()} -
    - - -
    - ${this._renderCurrentTemperature( - this.stateObj.attributes.current_temperature - )} + ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
    ${this._renderTemperatureButtons(this._selectTargetTemperature, true)}
    @@ -412,9 +494,7 @@ export class HaStateControlClimateTemperature extends LitElement { return html`
    - ${this._renderLabel()} - ${this._renderCurrentTemperature( - this.stateObj.attributes.current_temperature - )} + ${this._renderLabel()} ${this._renderSecondary()}
    `; @@ -450,24 +527,26 @@ export class HaStateControlClimateTemperature extends LitElement { flex-direction: row; gap: 24px; } - .dual button { + .target-button { outline: none; background: none; color: inherit; font-family: inherit; + font-size: inherit; + font-weight: inherit; -webkit-tap-highlight-color: transparent; border: none; - opacity: 0.5; + opacity: 0.7; padding: 0; transition: opacity 180ms ease-in-out, transform 180ms ease-in-out; cursor: pointer; } - .dual button:focus-visible { + .target-button:focus-visible { transform: scale(1.1); } - .dual button.selected { + .target-button.selected { opacity: 1; } .container.md .dual { @@ -477,6 +556,9 @@ export class HaStateControlClimateTemperature extends LitElement { .container.xs .dual { gap: 8px; } + .container.sm .target-icon { + display: none; + } ha-control-circular-slider { --control-circular-slider-low-color: var( --low-color, diff --git a/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts b/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts index 648753ab6611..6078180cd849 100644 --- a/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts +++ b/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts @@ -1,5 +1,5 @@ -import { mdiMinus, mdiPlus, mdiWaterPercent } from "@mdi/js"; -import { CSSResultGroup, LitElement, PropertyValues, html } from "lit"; +import { mdiMinus, mdiPlus, mdiThermostat, mdiWaterPercent } from "@mdi/js"; +import { CSSResultGroup, LitElement, PropertyValues, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { styleMap } from "lit/directives/style-map"; import { stateActive } from "../../common/entity/state_active"; @@ -11,6 +11,7 @@ import "../../components/ha-control-circular-slider"; import "../../components/ha-outlined-icon-button"; import "../../components/ha-svg-icon"; import { UNAVAILABLE } from "../../data/entity"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../data/entity_attributes"; import { HUMIDIFIER_ACTION_MODE, HumidifierEntity, @@ -28,8 +29,11 @@ export class HaStateControlHumidifierHumidity extends LitElement { @property({ attribute: false }) public stateObj!: HumidifierEntity; - @property({ attribute: "show-current", type: Boolean }) - public showCurrent?: boolean = false; + @property({ attribute: "show-secondary", type: Boolean }) + public showSecondary?: boolean; + + @property({ attribute: "use-current-as-primary", type: Boolean }) + public showCurrentAsPrimary?: boolean; @property({ type: Boolean, attribute: "prevent-interaction-on-scroll" }) public preventInteractionOnScroll?: boolean; @@ -101,37 +105,11 @@ export class HaStateControlHumidifierHumidity extends LitElement { const action = this.stateObj.attributes.action; - const actionLabel = this.hass.formatEntityAttributeValue( - this.stateObj, - "action" - ); - - return html` -

    - ${action && action !== "off" && action !== "idle" - ? actionLabel - : this._targetHumidity - ? this.hass.localize("ui.card.humidifier.target") - : this.hass.formatEntityState(this.stateObj)} -

    - `; - } - - private _renderCurrentHumidity(humidity?: number) { - if (!this.showCurrent || humidity == null) { - return html`

     

    `; - } - return html`

    - - - ${this.hass.formatEntityAttributeValue( - this.stateObj, - "current_humidity", - humidity - )} - + ${action + ? this.hass.formatEntityAttributeValue(this.stateObj, "action") + : this.hass.formatEntityState(this.stateObj)}

    `; } @@ -155,19 +133,95 @@ export class HaStateControlHumidifierHumidity extends LitElement { `; } - private _renderTarget(humidity: number) { - const formatOptions = { + private _renderPrimary() { + const currentHumidity = this.stateObj.attributes.current_humidity; + + if (currentHumidity != null && this.showCurrentAsPrimary) { + return this._renderCurrent(currentHumidity, "big"); + } + + if (this._targetHumidity != null && !this.showCurrentAsPrimary) { + return this._renderTarget(this._targetHumidity!, "big"); + } + + return nothing; + } + + private _renderSecondary() { + if (!this.showSecondary) { + return html`

    `; + } + + const currentHumidity = this.stateObj.attributes.current_humidity; + + if (currentHumidity != null && !this.showCurrentAsPrimary) { + return html` +

    + + ${this._renderCurrent(currentHumidity, "normal")} +

    + `; + } + + if (this._targetHumidity != null && this.showCurrentAsPrimary) { + return html` +

    + + ${this._renderCurrent(this._targetHumidity, "normal")} +

    + `; + } + + return html`

    `; + } + + private _renderTarget(humidity: number, style: "normal" | "big") { + const formatOptions: Intl.NumberFormatOptions = { maximumFractionDigits: 0, }; + if (style === "big") { + return html` + + `; + } + + return html` + ${this.hass.formatEntityAttributeValue( + this.stateObj, + "humidity", + humidity + )} + `; + } + + private _renderCurrent(humidity: number, style: "normal" | "big") { + const formatOptions: Intl.NumberFormatOptions = { + maximumFractionDigits: 1, + }; + if (style === "big") { + return html` + + `; + } return html` - + ${this.hass.formatEntityAttributeValue( + this.stateObj, + "current_humidity", + humidity + )} `; } @@ -219,10 +273,7 @@ export class HaStateControlHumidifierHumidity extends LitElement { >
    - ${this._renderLabel()} ${this._renderTarget(targetHumidity)} - ${this._renderCurrentHumidity( - this.stateObj.attributes.current_humidity - )} + ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
    ${this._renderButtons()}
    @@ -246,10 +297,7 @@ export class HaStateControlHumidifierHumidity extends LitElement { >
    - ${this._renderLabel()} - ${this._renderCurrentHumidity( - this.stateObj.attributes.current_humidity - )} + ${this._renderLabel()} ${this._renderSecondary()}
    `; diff --git a/src/state-control/state-control-circular-slider-style.ts b/src/state-control/state-control-circular-slider-style.ts index 8928960380f1..cc1c9366d7e9 100644 --- a/src/state-control/state-control-circular-slider-style.ts +++ b/src/state-control/state-control-circular-slider-style.ts @@ -41,6 +41,9 @@ export const stateControlCircularSliderStyle = css` -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; + line-height: 1.5; + min-height: 1.5em; + white-space: nowrap; } .label span { white-space: nowrap; diff --git a/src/state-control/valve/ha-state-control-valve-buttons.ts b/src/state-control/valve/ha-state-control-valve-buttons.ts new file mode 100644 index 000000000000..5421741087c4 --- /dev/null +++ b/src/state-control/valve/ha-state-control-valve-buttons.ts @@ -0,0 +1,145 @@ +import { mdiStop, mdiValveClosed, mdiValveOpen } from "@mdi/js"; +import { + CSSResultGroup, + LitElement, + TemplateResult, + css, + html, + nothing, +} from "lit"; +import { customElement, property } from "lit/decorators"; +import { repeat } from "lit/directives/repeat"; +import memoizeOne from "memoize-one"; +import { supportsFeature } from "../../common/entity/supports-feature"; +import "../../components/ha-control-button"; +import "../../components/ha-control-button-group"; +import "../../components/ha-control-slider"; +import "../../components/ha-svg-icon"; +import { + ValveEntity, + ValveEntityFeature, + canClose, + canOpen, + canStop, +} from "../../data/valve"; +import { HomeAssistant } from "../../types"; + +type ValveButton = "open" | "close" | "stop" | "none"; + +export const getValveButtons = memoizeOne( + (stateObj: ValveEntity): ValveButton[] => { + const supportsOpen = supportsFeature(stateObj, ValveEntityFeature.OPEN); + const supportsClose = supportsFeature(stateObj, ValveEntityFeature.CLOSE); + const supportsStop = supportsFeature(stateObj, ValveEntityFeature.STOP); + + const buttons: ValveButton[] = []; + if (supportsOpen) buttons.push("open"); + if (supportsStop) buttons.push("stop"); + if (supportsClose) buttons.push("close"); + return buttons; + } +); + +@customElement("ha-state-control-valve-buttons") +export class HaStateControlValveButtons extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public stateObj!: ValveEntity; + + private _onOpenTap(ev): void { + ev.stopPropagation(); + this.hass!.callService("valve", "open_valve", { + entity_id: this.stateObj!.entity_id, + }); + } + + private _onCloseTap(ev): void { + ev.stopPropagation(); + this.hass!.callService("valve", "close_valve", { + entity_id: this.stateObj!.entity_id, + }); + } + + private _onStopTap(ev): void { + ev.stopPropagation(); + this.hass!.callService("valve", "stop_valve", { + entity_id: this.stateObj!.entity_id, + }); + } + + protected renderButton(button: ValveButton | undefined) { + if (button === "open") { + return html` + + + + `; + } + if (button === "close") { + return html` + + + + `; + } + if (button === "stop") { + return html` + + + + `; + } + return nothing; + } + + protected render(): TemplateResult { + const buttons = getValveButtons(this.stateObj); + + return html` + + ${repeat( + buttons, + (button) => button, + (button) => this.renderButton(button) + )} + + `; + } + + static get styles(): CSSResultGroup { + return css` + ha-control-button-group { + height: 45vh; + max-height: 320px; + min-height: 200px; + --control-button-group-spacing: 6px; + --control-button-group-thickness: 100px; + } + ha-control-button { + --control-button-border-radius: 18px; + --mdc-icon-size: 24px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-state-control-valve-buttons": HaStateControlValveButtons; + } +} diff --git a/src/state-control/valve/ha-state-control-valve-position.ts b/src/state-control/valve/ha-state-control-valve-position.ts new file mode 100644 index 000000000000..992c96056168 --- /dev/null +++ b/src/state-control/valve/ha-state-control-valve-position.ts @@ -0,0 +1,88 @@ +import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { styleMap } from "lit/directives/style-map"; +import { computeAttributeNameDisplay } from "../../common/entity/compute_attribute_display"; +import { stateColorCss } from "../../common/entity/state_color"; +import "../../components/ha-control-slider"; +import { CoverEntity } from "../../data/cover"; +import { UNAVAILABLE } from "../../data/entity"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../data/entity_attributes"; +import { HomeAssistant } from "../../types"; + +@customElement("ha-state-control-valve-position") +export class HaStateControlValvePosition extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public stateObj!: CoverEntity; + + @state() value?: number; + + protected updated(changedProp: Map): void { + if (changedProp.has("stateObj")) { + const currentPosition = this.stateObj?.attributes.current_position; + this.value = + currentPosition != null ? Math.round(currentPosition) : undefined; + } + } + + private _valueChanged(ev: CustomEvent) { + const value = (ev.detail as any).value; + if (isNaN(value)) return; + + this.hass.callService("valve", "set_valve_position", { + entity_id: this.stateObj!.entity_id, + position: value, + }); + } + + protected render(): TemplateResult { + const color = stateColorCss(this.stateObj); + + return html` + + + `; + } + + static get styles(): CSSResultGroup { + return css` + ha-control-slider { + height: 45vh; + max-height: 320px; + min-height: 200px; + --control-slider-thickness: 100px; + --control-slider-border-radius: 24px; + --control-slider-color: var(--primary-color); + --control-slider-background: var(--disabled-color); + --control-slider-background-opacity: 0.2; + --control-slider-tooltip-font-size: 20px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-state-control-valve-position": HaStateControlValvePosition; + } +} diff --git a/src/state-control/valve/ha-state-control-valve-toggle.ts b/src/state-control/valve/ha-state-control-valve-toggle.ts new file mode 100644 index 000000000000..2eb0dbd93477 --- /dev/null +++ b/src/state-control/valve/ha-state-control-valve-toggle.ts @@ -0,0 +1,167 @@ +import { HassEntity } from "home-assistant-js-websocket"; +import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { customElement, property } from "lit/decorators"; +import { classMap } from "lit/directives/class-map"; +import { styleMap } from "lit/directives/style-map"; +import { domainIcon } from "../../common/entity/domain_icon"; +import { stateColorCss } from "../../common/entity/state_color"; +import "../../components/ha-control-button"; +import "../../components/ha-control-switch"; +import { UNAVAILABLE, UNKNOWN } from "../../data/entity"; +import { forwardHaptic } from "../../data/haptics"; +import { HomeAssistant } from "../../types"; + +@customElement("ha-state-control-valve-toggle") +export class HaStateControlValveToggle extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public stateObj!: HassEntity; + + private _valueChanged(ev) { + const checked = ev.target.checked as boolean; + + if (checked) { + this._turnOn(); + } else { + this._turnOff(); + } + } + + private _turnOn() { + this._callService(true); + } + + private _turnOff() { + this._callService(false); + } + + private async _callService(turnOn): Promise { + if (!this.hass || !this.stateObj) { + return; + } + forwardHaptic("light"); + + await this.hass.callService( + "valve", + turnOn ? "open_valve" : "close_valve", + { + entity_id: this.stateObj.entity_id, + } + ); + } + + protected render(): TemplateResult { + const onColor = stateColorCss(this.stateObj, "open"); + const offColor = stateColorCss(this.stateObj, "closed"); + + const isOn = + this.stateObj.state === "open" || + this.stateObj.state === "closing" || + this.stateObj.state === "opening"; + const isOff = this.stateObj.state === "closed"; + + if ( + this.stateObj.attributes.assumed_state || + this.stateObj.state === UNKNOWN + ) { + return html` +
    + + + + + + +
    + `; + } + + return html` + + + `; + } + + static get styles(): CSSResultGroup { + return css` + ha-control-switch { + height: 45vh; + max-height: 320px; + min-height: 200px; + --control-switch-thickness: 100px; + --control-switch-border-radius: 24px; + --control-switch-padding: 6px; + --mdc-icon-size: 24px; + } + .buttons { + display: flex; + flex-direction: column; + width: 100px; + height: 45vh; + max-height: 320px; + min-height: 200px; + padding: 6px; + box-sizing: border-box; + } + ha-control-button { + flex: 1; + width: 100%; + --control-button-border-radius: 18px; + --mdc-icon-size: 24px; + } + ha-control-button.active { + --control-button-icon-color: white; + --control-button-background-color: var(--color); + --control-button-background-opacity: 1; + } + ha-control-button:not(:last-child) { + margin-bottom: 6px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-state-control-valve-toggle": HaStateControlValveToggle; + } +} diff --git a/src/translations/en.json b/src/translations/en.json index c2eb73e36e5b..df67e68c8ed4 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -255,6 +255,11 @@ "turn_off": "Turn off" } }, + "valve": { + "open_valve": "Open valve", + "close_valve": "Close valve", + "stop_valve": "Stop valve" + }, "water_heater": { "currently": "[%key:ui::card::climate::currently%]", "on_off": "On / off", @@ -344,7 +349,8 @@ "error_required": "Required", "copied": "Copied", "copied_clipboard": "Copied to clipboard", - "name": "Name" + "name": "Name", + "optional": "optional" }, "components": { "selectors": { @@ -703,7 +709,7 @@ "media_not_supported": "The Browser Media Player does not support this type of media", "media_browsing_error": "Media browsing error", "learn_adding_local_media": "Learn more about adding media in the {documentation}.", - "local_media_files": "Place your video, audio and image files in the media directory to be able to browse and play them in the browser or on supported media players.", + "local_media_files": "Place your video, audio, and image files in the media directory to be able to browse and play them in the browser or on supported media players.", "documentation": "documentation", "no_local_media_found": "No local media found", "no_media_folder": "It looks like you have not yet created a media directory.", @@ -750,6 +756,22 @@ "grid": "Grid", "list": "List" }, + "todo": { + "item": { + "summary": "Task name", + "description": "Description", + "add": "Add item", + "delete": "Delete item", + "edit": "Edit item", + "save": "Save item", + "due": "Due date", + "not_all_required_fields": "Not all required fields are filled in", + "confirm_delete": { + "delete": "Delete item", + "prompt": "Do you want to delete this item?" + } + } + }, "calendar": { "label": "Calendar", "my_calendars": "My calendars", @@ -987,7 +1009,8 @@ "crop_image": "Picture to crop" }, "date-picker": { - "today": "Today" + "today": "Today", + "clear": "Clear" }, "more_info_control": { "dismiss": "Dismiss dialog", @@ -1094,6 +1117,12 @@ "start_mowing": "Start mowing", "pause": "Pause", "dock": "Return to dock" + }, + "valve": { + "switch_mode": { + "button": "[%key:ui::dialogs::more_info_control::cover::switch_mode::button%]", + "position": "[%key:ui::dialogs::more_info_control::cover::switch_mode::position%]" + } } }, "entity_registry": { @@ -1519,6 +1548,11 @@ "gateway": "Gateway: {gateway}", "method": "Method: {method}", "nameservers": "Name Servers: {nameservers}" + }, + "update_backup": { + "title": "Create backup?", + "text": "This will create a backup before installing.", + "create": "Create" } }, "weekdays": { @@ -1546,10 +1580,10 @@ "supervisor": { "title": "Could not load the Supervisor panel!", "wait": "If you just started, make sure you have given the Supervisor enough time to start.", - "ask": "Ask for help", - "reboot": "Try a reboot of the host", - "observer": "Check the observer", - "system_health": "Check system health" + "ask": "Ask for help.", + "reboot": "Try a reboot of the host.", + "observer": "Check the observer.", + "system_health": "Check the system health." } }, "login-form": { @@ -1598,11 +1632,11 @@ "dashboard": { "devices": { "main": "Devices & services", - "secondary": "Integrations, devices, entities and helpers" + "secondary": "Integrations, devices, entities, and helpers" }, "automations": { "main": "Automations & scenes", - "secondary": "Automations, scenes, scripts and blueprints" + "secondary": "Automations, scenes, scripts, and blueprints" }, "backup": { "main": "Backup", @@ -1646,7 +1680,7 @@ }, "about": { "main": "About", - "secondary": "Version information, credits and more" + "secondary": "Version information, credit, and more" }, "cloud": { "secondary": "Loading..." @@ -1660,7 +1694,7 @@ }, "updates": { "caption": "Updates", - "description": "Manage updates of Home Assistant, add-ons and devices", + "description": "Manage updates of Home Assistant, add-ons, and devices", "no_updates": "No updates available", "no_update_entities": { "title": "Unable to check for updates", @@ -1676,7 +1710,8 @@ "show_skipped": "Show skipped updates", "join_beta": "[%key:supervisor::system::supervisor::join_beta_action%]", "leave_beta": "[%key:supervisor::system::supervisor::leave_beta_action%]", - "skipped": "Skipped" + "skipped": "Skipped", + "update_in_progress": "Update in progress" }, "repairs": { "caption": "Repairs", @@ -1717,7 +1752,7 @@ }, "picker": { "header": "Areas", - "introduction": "Areas are used to organize where devices are. This information will be used throughout Home Assistant to help you in organizing your interface, permissions and integrations with other systems.", + "introduction": "Areas are used to organize where devices are. This information will be used throughout Home Assistant to help you in organizing your interface, permissions, and integrations with other systems.", "introduction2": "To place devices in an area, use the link below to navigate to the integrations page and then click on a configured integration to get to the device cards.", "integrations_page": "Integrations page", "no_areas": "Looks like you have no areas yet!", @@ -1992,7 +2027,7 @@ "section": { "core": { "header": "General configuration", - "introduction": "Manage your location, network and analytics.", + "introduction": "Manage your location, network, and analytics.", "core_config": { "edit_requires_storage": "Editor disabled because config stored in configuration.yaml.", "location_name": "Name", @@ -2349,7 +2384,10 @@ "trigger": "Trigger", "actions": "Actions", "state": "State" - } + }, + "empty_header": "Start automating", + "empty_text_1": "Automations make Home Assistant automatically respond to things happening in and around your home.", + "empty_text_2": "Automations connect triggers to actions in a ''when trigger then action'' fashion with optional conditions. For example: ''When the sun sets and if {user} is home, then turn on the lights''." }, "dialog_new": { "header": "Create automation", @@ -2426,11 +2464,15 @@ "edit_yaml": "Edit in YAML", "edit_ui": "Edit in visual editor", "copy_to_clipboard": "Copy to clipboard", + "search_in": "Search · {group}", "triggers": { - "header": "Triggers", + "name": "Triggers", + "header": "When", + "description": "This list of triggers is what starts your automation. A trigger is a specific event happening in or around your home, for example: ''When the sun sets''.", "learn_more": "Learn more about triggers", "triggered": "Triggered", "add": "Add trigger", + "search": "Search trigger", "id": "Trigger ID", "edit_id": "Edit ID", "duplicate": "[%key:ui::common::duplicate%]", @@ -2447,6 +2489,17 @@ "unsupported_platform": "No visual editor support for platform: {platform}", "type_select": "Trigger type", "unknown_trigger": "[%key:ui::panel::config::devices::automation::triggers::unknown_trigger%]", + "groups": { + "entity": { + "label": "Entity", + "description": "When something happens to an entity." + }, + "time_location": { + "label": "Time and location", + "description": "When someone enters or leaves a zone, or at a specific time." + }, + "other": { "label": "Other triggers" } + }, "type": { "calendar": { "label": "Calendar", @@ -2455,7 +2508,10 @@ "end": "Event end", "offset": "Offset (optional)", "before": "Before", - "after": "After" + "after": "After", + "description": { + "picker": "When a calendar event starts or ends." + } }, "device": { "label": "Device", @@ -2465,6 +2521,9 @@ "below": "Below", "for": "Duration (optional)", "zone": "[%key:ui::panel::config::automation::editor::triggers::type::zone::label%]" + }, + "description": { + "picker": "When something happens to a device. Great way to start." } }, "event": { @@ -2475,6 +2534,7 @@ "context_user_picked": "User firing event", "context_user_pick": "Select user", "description": { + "picker": "When an event is being received (event is an advanced concept in Home Assistant).", "full": "When {eventTypes} event is fired" } }, @@ -2486,6 +2546,7 @@ "enter": "Enter", "leave": "Leave", "description": { + "picker": "When an entity created by a geolocation platform appears in or disappears from a zone.", "full": "When {source} {event, select, \n enter {enters}\n leave {leaves} other {} \n} {zone} {numberOfZones, plural,\n one {zone}\n other {zones}\n}" } }, @@ -2495,7 +2556,10 @@ "from": "From (optional)", "for": "For", "to": "To (optional)", - "any_state_ignore_attributes": "Any state (ignoring attribute changes)" + "any_state_ignore_attributes": "Any state (ignoring attribute changes)", + "description": { + "picker": "When the state of an entity (or attribute) changes." + } }, "homeassistant": { "label": "Home Assistant", @@ -2503,6 +2567,7 @@ "start": "Start", "shutdown": "Shutdown", "description": { + "picker": "When Home Assistant starts up or shuts down.", "started": "When Home Assistant is started", "shutdown": "When Home Assistant is shutdown" } @@ -2512,6 +2577,7 @@ "topic": "Topic", "payload": "Payload (optional)", "description": { + "picker": "When a specific message is received on a given MQTT topic.", "full": "When an MQTT message has been received" } }, @@ -2525,6 +2591,7 @@ "type_value": "Fixed number", "type_input": "Numeric value of another entity", "description": { + "picker": "When the numeric value of an entity''s state (or attribute''s value) crosses a given threshold.", "above": "When {attribute, select, \n undefined {} \n other {{attribute} from }\n }{entity} {numberOfEntities, plural,\n one {is}\n other {are}\n} above {above}{duration, select, \n undefined {} \n other { for {duration}}\n }", "below": "When {attribute, select, \n undefined {} \n other {{attribute} from }\n }{entity} {numberOfEntities, plural,\n one {is}\n other {are}\n} below {below}{duration, select, \n undefined {} \n other { for {duration}}\n }", "above-below": "When {attribute, select, \n undefined {} \n other {{attribute} from }\n }{entity} {numberOfEntities, plural,\n one {is}\n other {are}\n} above {above} and below {below}{duration, select, \n undefined {} \n other { for {duration}}\n }" @@ -2541,6 +2608,7 @@ "updated": "updated" }, "description": { + "picker": "When a persistent notification is added or removed.", "full": "When a persistent notification is updated" } }, @@ -2551,6 +2619,7 @@ "sunset": "Sunset", "offset": "Offset (optional)", "description": { + "picker": "When the sun sets or rises.", "sets": "When the sun sets{hasDuration, select, \n true { offset by {duration}} \n other {}\n }", "rises": "When the sun rises{hasDuration, select, \n true { offset by {duration}} \n other {}\n }" } @@ -2562,6 +2631,7 @@ "delete": "Delete sentence", "confirm_delete": "Are you sure you want to delete this sentence?", "description": { + "picker": "When Assist matches a sentence from a voice assistant.", "empty": "When a sentence is said", "full": "When the sentence {sentence} is said" } @@ -2569,6 +2639,7 @@ "tag": { "label": "Tag", "description": { + "picker": "When a tag is scanned (tags are usually created from the companion app).", "full": "When a tag is scanned" } }, @@ -2577,6 +2648,7 @@ "value_template": "Value template", "for": "For", "description": { + "picker": "When a template evaluates to true.", "full": "When a template changes from false to true{hasDuration, select, \n true { for {duration}} \n other {}\n }" } }, @@ -2587,6 +2659,7 @@ "at": "At time", "mode": "Mode", "description": { + "picker": "At a specific time, or on a specific date.", "full": "When the time is equal to {time}" } }, @@ -2594,16 +2667,20 @@ "label": "Time pattern", "hours": "Hours", "minutes": "Minutes", - "seconds": "Seconds" + "seconds": "Seconds", + "description": { + "picker": "Periodically, at a defined interval." + } }, "webhook": { "copy_url": "Copy URL to clipboard", "label": "Webhook", "local_only": "Only accessible from the local network", "webhook_id": "Webhook ID", - "webhook_id_helper": "Treat this ID like a password: keep it secret, and make it hard to guess.", + "webhook_id_helper": "Treat this ID like a password: keep it secret and make it hard to guess.", "webhook_settings": "Webhook settings", "description": { + "picker": "When Home Assistant receives a web request to the webhook endpoint.", "full": "When a Webhook payload has been received" } }, @@ -2615,15 +2692,20 @@ "enter": "Enter", "leave": "Leave", "description": { + "picker": "When someone (or something) enters or leaves a zone.", "full": "When {entity} {event, select, \n enter {enters}\n leave {leaves} other {} \n} {zone} {numberOfZones, plural,\n one {zone} \n other {zones}\n}" } } } }, "conditions": { - "header": "Conditions", + "name": "Conditions", + "header": "And if", + "description": "This list of conditions needs to be satisfied for the automation to run. A condition can be satisfied or not at any given time, for example: ''If {user} is home''. You can use building blocks to create more complex conditions.", "learn_more": "Learn more about conditions", "add": "Add condition", + "search": "Search condition", + "add_building_block": "Add building block", "test": "Test", "testing_error": "Condition did not pass", "testing_pass": "Condition passes", @@ -2643,10 +2725,26 @@ "unsupported_condition": "No visual editor support for condition: {condition}", "type_select": "Condition type", "unknown_condition": "[%key:ui::panel::config::devices::automation::conditions::unknown_condition%]", + "groups": { + "entity": { + "label": "Entity", + "description": "If an entity is in a specific state." + }, + "time_location": { + "label": "Time and location", + "description": "If someone is in a zone or if the current time is before or after a specified time." + }, + "other": { "label": "Other conditions" }, + "building_blocks": { + "label": "Building blocks", + "description": "Build more complex conditions." + } + }, "type": { "and": { "label": "And", "description": { + "picker": "Test if multiple conditions are true.", "no_conditions": "Test if multiple conditions match", "full": "Test if {count} {count, plural,\n one {condition match}\n other {conditions matches}\n}" } @@ -2660,11 +2758,15 @@ "for": "Duration", "hvac_mode": "HVAC mode", "preset_mode": "Preset mode" + }, + "description": { + "picker": "Set of conditions provided by your device. Great way to start." } }, "not": { "label": "Not", "description": { + "picker": "Test if a condition is not true.", "no_conditions": "Test if no condition matches", "one_condition": "Test if 1 condition does not match", "full": "Test if none of {count} conditions match" @@ -2680,6 +2782,7 @@ "mode_below": "[%key:ui::panel::config::automation::editor::triggers::type::numeric_state::mode_below%]", "value_template": "[%key:ui::panel::config::automation::editor::triggers::type::numeric_state::value_template%]", "description": { + "picker": "If the numeric value of an entity''s state (or attribute''s value) is above or below a given threshold.", "above": "When {attribute, select, \n undefined {} \n other {{attribute} from }\n }{entity} is above {above}", "below": "When {attribute, select, \n undefined {} \n other {{attribute} from }\n }{entity} is below {below}", "above-below": "When {attribute, select, \n undefined {} \n other {{attribute} from }\n }{entity} is above {above} and below {below}" @@ -2688,13 +2791,19 @@ "or": { "label": "Or", "description": { + "picker": "Test if any condition is true.", "no_conditions": "Test if any condition matches", "full": "Test if any of {count} {count, plural,\n one {condition}\n other {conditions}\n} matches" } }, "state": { "label": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]", - "state": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]" + "state": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]", + "description": { + "picker": "If an entity (or attribute) is in a specific state.", + "no_entity": "Confirm state", + "full": "Confirm{hasAttribute, select, \n true { {attribute} of}\n other {}\n} {numberOfEntities, plural,\n zero {an entity is}\n one {{entities} is}\n other {{entities} are}\n} {numberOfStates, plural,\n zero {a state}\n other {{states}}\n}{hasDuration, select, \n true { for {duration}} \n other {}\n }" + } }, "sun": { "label": "[%key:ui::panel::config::automation::editor::triggers::type::sun::label%]", @@ -2703,12 +2812,16 @@ "before_offset": "Before offset (optional)", "after_offset": "After offset (optional)", "sunrise": "Sunrise", - "sunset": "Sunset" + "sunset": "Sunset", + "description": { + "picker": "If the sun is above or below the horizon." + } }, "template": { "label": "[%key:ui::panel::config::automation::editor::triggers::type::template::label%]", "value_template": "[%key:ui::panel::config::automation::editor::triggers::type::template::value_template%]", "description": { + "picker": "If a template evaluates to true.", "full": "Test if template renders a value equal to true" } }, @@ -2731,6 +2844,7 @@ "sun": "Sunday" }, "description": { + "picker": "If the current time is before or after a specified time.", "full": "Confirm the {hasTime, select, \n after {time is after {time_after}}\n before {time is before {time_before}}\n after_before {time is after {time_after} and before {time_before}} \n other {}\n }{hasTimeAndDay, select, \n true { and the }\n other {}\n}{hasDay, select, \n true { day is {day}}\n other {}\n}" } }, @@ -2739,6 +2853,7 @@ "no_triggers": "No triggers have an ID set. You can set an ID using the trigger menu button.", "id": "Trigger", "description": { + "picker": "If the automation has been triggered by a specific trigger.", "full": "When triggered by {id}" } }, @@ -2747,15 +2862,20 @@ "entity": "[%key:ui::panel::config::automation::editor::triggers::type::zone::entity%]", "zone": "[%key:ui::panel::config::automation::editor::triggers::type::zone::label%]", "description": { + "picker": "If someone (or something) is in a zone.", "full": "Confirm {entity} {numberOfEntities, plural,\n one {is}\n other {are}\n} in {zone} {numberOfZones, plural,\n one {zone} \n other {zones}\n} " } } } }, "actions": { - "header": "Actions", + "name": "Actions", + "header": "Then do", + "description": "This list of actions will be performed in sequence when the automation runs. An action usually controls one of your areas, devices, or entities, for example: 'Turn on the lights'. You can use building blocks to create more complex sequences of actions.", "learn_more": "Learn more about actions", "add": "Add action", + "search": "Search action", + "add_building_block": "Add building block", "invalid_action": "Invalid action", "run": "Run", "run_action_error": "Error running action", @@ -2777,6 +2897,14 @@ "unsupported_action": "No visual editor support for this action", "type_select": "Action type", "continue_on_error": "Continue on error", + "groups": { + "helpers": { "label": "Helpers" }, + "other": { "label": "Other actions" }, + "building_blocks": { + "label": "Building blocks", + "description": "Build more complex sequences of actions." + } + }, "type": { "service": { "label": "Call service", @@ -2786,6 +2914,7 @@ "description": { "service_based_on_template": "Call a service based on a template on {targets}", "service_based_on_name": "Call a service ''{name}'' on {targets}", + "service_name": "{domain} ''{name}'' on {targets}", "service": "Call a service", "target_template": "templated {name}", "target_unknown_entity": "unknown entity", @@ -2796,6 +2925,7 @@ "play_media": { "label": "Play media", "description": { + "picker": "Play media on a media player.", "full": "Play {hasMedia, select, \n true {{media}} \n other {media}\n } on {hasMediaPlayer, select, \n true {{mediaPlayer}} \n other {a media player}\n }" } }, @@ -2803,6 +2933,7 @@ "label": "Wait for time to pass (delay)", "delay": "Duration", "description": { + "picker": "Wait some time to perform a sequence of actions.", "full": "Delay {duration}", "duration_string": "for {string}", "duration_template": "based on a template", @@ -2815,6 +2946,7 @@ "timeout": "Timeout (optional)", "continue_timeout": "Continue on timeout", "description": { + "picker": "Wait for a template to be evaluated to true to perform a sequence of actions.", "full": "Wait for a template to evaluate to true" } }, @@ -2823,18 +2955,23 @@ "timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::timeout%]", "continue_timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::continue_timeout%]", "description": { + "picker": "Wait for a trigger to perform a sequence of actions.", "wait_for_a_trigger": "Wait for a trigger", "wait_for_triggers": "Wait for {count} {count, plural,\n one {trigger}\n other {triggers}\n}" } }, "condition": { - "label": "Condition" + "label": "Condition", + "description": { + "picker": "Test a condition (and stop the sequence if the condition is not met)." + } }, "event": { "label": "Manual event", "event": "[%key:ui::panel::config::automation::editor::triggers::type::event::event_type%]", "event_data": "[%key:ui::panel::config::automation::editor::triggers::type::event::event_data%]", "description": { + "picker": "Fire an event manually (event is an advanced concept in Home Assistant).", "full": "Manually fire event {name}", "template": "based on a template" } @@ -2852,6 +2989,10 @@ "value": "Value", "brightness_pct": "[%key:ui::card::light::brightness%]", "flash": "Flash" + }, + "description": { + "picker": "Do something on a device. Great way to start.", + "no_device": "Device action" } }, "activate_scene": { @@ -2884,6 +3025,7 @@ }, "sequence": "Actions", "description": { + "picker": "Repeat a sequence of actions.", "full": "Repeat an action {chosenAction}", "count": "{count} {count, plural,\n one {time}\n other {times}\n}", "while_count": "while {count} {count, plural,\n one {condition matches}\n other {conditions match}\n} ", @@ -2906,6 +3048,7 @@ "no_conditions": "[%key:ui::panel::config::devices::automation::conditions::no_conditions%]", "sequence": "Actions", "description": { + "picker": "Choose what to do based on conditions (Similar to If-Then, but more powerful).", "full": "Choose between {number} {number, plural,\n one {action}\n other{actions}\n}", "no_action": "Choose an action" } @@ -2917,6 +3060,7 @@ "else": "Else", "add_else": "Add else", "description": { + "picker": "Do something conditionally.", "if": "Conditionally execute an action", "if_else": "Conditionally execute an action and default to another action" } @@ -2927,18 +3071,21 @@ "response_variable": "The name of the variable to use as response", "error": "Stop because of an unexpected error", "description": { + "picker": "Stop the sequence of actions.", "full": "Stop {hasReason, select, \n true { because: {reason}} \n other {}\n }" } }, "parallel": { "label": "Run in parallel", "description": { + "picker": "Perform a sequence of actions in parallel.", "full": "Run {number} {number, plural,\n one {action}\n other {actions}\n} in parallel" } }, "variables": { "label": "Define variables", "description": { + "picker": "Define variables to be used later in the sequence.", "full": "Define variables {names}" } }, @@ -2958,7 +3105,31 @@ "download_trace": "Download trace", "edit_automation": "Edit automation", "older_trace": "Older trace", - "newer_trace": "Newer trace" + "newer_trace": "Newer trace", + "no_traces_found": "No traces found", + "tabs": { + "details": "Step Details", + "timeline": "Trace Timeline", + "logbook": "Related logbook entries", + "automation_config": "Automation Config", + "step_config": "Step Config", + "changed_variables": "Changed Variables", + "blueprint_config": "Blueprint Config" + }, + "path": { + "choose": "Select a step on the left for more information.", + "default_action_executed": "The default action was executed because no options matched.", + "no_further_execution": "This step was not executed and so no further trace information is available.", + "disabled_step": "This step was disabled and skipped during execution so no further trace information is available.", + "iteration": "Iteration {number}", + "executed": "Executed: {time}", + "error": "Error: {error}", + "result": "Result:", + "step_not_executed": "This step was not executed.", + "no_logbook_entries": "No Logbook entries found for this step.", + "no_variables_changed": "No variables changed", + "unable_to_find_config": "Unable to find config" + } } }, "blueprint": { @@ -2982,7 +3153,7 @@ "script": "scripts" }, "error": "{path} could not be loaded", - "blueprint_in_use_title": "This blueprint is in use, and can not be deleted", + "blueprint_in_use_title": "This blueprint is in use and can not be deleted", "blueprint_in_use_text": "Please remove all below {type} that use this blueprint before deleting it. {list}", "blueprint_in_use_view": "view {type}", "confirm_delete_title": "Delete blueprint?", @@ -3044,7 +3215,9 @@ "state": "State" }, "delete": "[%key:ui::common::delete%]", - "duplicate": "[%key:ui::common::duplicate%]" + "duplicate": "[%key:ui::common::duplicate%]", + "empty_header": "Create your first script", + "empty_text": "A script is a sequence of actions that can be run from a dashboard, an automation, or be triggered by voice. For example, a ''Wake-up routine''' script that gradually turns on the light in the bedroom and opens the blinds after a delay." }, "dialog_new": { "header": "Create script", @@ -3144,7 +3317,9 @@ "state": "State", "name": "Name", "last_activated": "Last activated" - } + }, + "empty_header": "Create your first scene", + "empty_text": "Scenes capture entities' states, so you can re-experience the same scene later on. For example, a ''Watching TV'' scene that dims the living room lights, sets a warm white color and turns on the TV." }, "editor": { "default_name": "New scene", @@ -3491,8 +3666,7 @@ "unavailable": "Unavailable", "disabled": "Disabled", "readonly": "Read-only", - "hidden": "Hidden", - "ok": "Ok" + "hidden": "Hidden" }, "headers": { "state_icon": "State icon", @@ -3628,6 +3802,9 @@ "add_zwave_js_device": "Add Z-Wave device", "add_zha_device": "Add Zigbee device", "add_matter_device": "Add Matter device", + "what_device_type": "What type of device is it?", + "what_to_add": "What do you want to add?", + "confirm_add_discovered": "Want to add these discovered devices?", "disable": { "show_disabled": "Show disabled integrations", "disabled_integrations": "{number} disabled", @@ -3650,6 +3827,8 @@ "entries_service": "Services", "entries_helper": "Helpers", "entries_hardware": "Hardware", + "entries_system": "[%key:ui::panel::config::integrations::integration_page::entries%]", + "entries_entity": "[%key:ui::panel::config::integrations::integration_page::entries%]", "no_entries": "No entries", "attention_entries": "Needs attention", "add_entry": "Add entry", @@ -3657,7 +3836,9 @@ "add_hub": "Add hub", "add_service": "Add service", "add_helper": "Add helper", - "add_hardware": "Add hardware" + "add_hardware": "Add hardware", + "add_entity": "[%key:ui::panel::config::integrations::integration_page::add_entry%]", + "add_system": "[%key:ui::panel::config::integrations::integration_page::add_entry%]" }, "config_entry": { "application_credentials": { @@ -3993,6 +4174,7 @@ "removing_members": "Removing devices", "create_group_details": "Enter the required details to create a new Zigbee group", "group_name_placeholder": "Group name", + "group_id_placeholder": "Group ID (optional)", "create_group": "Create group", "create": "Create group", "creating_group": "Creating group", @@ -4057,8 +4239,6 @@ "cancel_inclusion_exclusion": "Stop searching" }, "dashboard": { - "header": "Manage your Z-Wave network", - "introduction": "Manage your Z-Wave network and Z-Wave devices", "driver_version": "Driver version", "server_version": "Server version", "home_id": "Home ID", @@ -4550,7 +4730,7 @@ }, "system_health": { "caption": "System health", - "description": "Status, metrics and integration startup time", + "description": "Status, metrics, and integration startup time", "cpu_usage": "Processor usage", "ram_usage": "Memory usage", "core_stats": "Core metrics", @@ -4587,14 +4767,18 @@ "never_triggered": "Never triggered" }, "todo-list": { - "checked_items": "Checked items", - "clear_items": "Clear checked items", + "unchecked_items": "Active", + "no_unchecked_items": "You have no to-do items!", + "checked_items": "Completed", + "clear_items": "Remove completed items", "add_item": "Add item", + "today": "Today", "reorder_items": "Reorder items", + "exit_reorder_items": "Exit reorder mode", "drag_and_drop": "Drag and drop", "delete_item": "Delete item", - "delete_confirm_title": "Clear checked items?", - "delete_confirm_text": "{number} {number, plural,\n one {item}\n other {items}\n} will be permanently deleted from the to-do list." + "delete_confirm_title": "Remove completed items?", + "delete_confirm_text": "{number} {number, plural,\n one {item}\n other {items}\n} will be permanently removed from the to-do list." }, "picture-elements": { "hold": "Hold:", @@ -4690,7 +4874,7 @@ "show_summary": "Show summary view" }, "carbon_consumed_gauge": { - "card_indicates_energy_used": "This card indicates how much of the energy consumed by your home was generated using non-fossil fuels like solar, wind and nuclear. The higher, the better!", + "card_indicates_energy_used": "This card indicates how much of the energy consumed by your home was generated using non-fossil fuels like solar, wind, and nuclear. The higher, the better!", "low_carbon_energy_consumed": "Low-carbon energy consumed", "low_carbon_energy_not_calculated": "Consumed low-carbon energy couldn't be calculated" } @@ -4940,7 +5124,7 @@ }, "calendar": { "name": "Calendar", - "description": "The Calendar card displays a calendar including day, week and list views", + "description": "The Calendar card displays a calendar including day, week, and list views", "initial_view": "Initial view", "calendar_entities": "Calendar entities", "views": { @@ -5093,7 +5277,8 @@ }, "humidifier": { "name": "Humidifier", - "description": "The Humidifier card gives control of your humidifier entity. Allowing you to change the humidity and mode of the entity." + "description": "The Humidifier card gives control of your humidifier entity. Allowing you to change the humidity and mode of the entity.", + "show_current_as_primary": "Show current humidity as primary information" }, "iframe": { "name": "Webpage", @@ -5191,7 +5376,8 @@ }, "thermostat": { "name": "Thermostat", - "description": "The Thermostat card gives control of your climate entity. Allowing you to change the temperature and mode of the entity." + "description": "The Thermostat card gives control of your climate entity. Allowing you to change the temperature and mode of the entity.", + "show_current_as_primary": "Show current temperature as primary information" }, "tile": { "name": "Tile", @@ -5280,6 +5466,15 @@ "return_home": "[%key:ui::dialogs::more_info_control::vacuum::return_home%]" } }, + "climate-fan-modes": { + "label": "Climate fan modes", + "style": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style%]", + "style_list": { + "dropdown": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style_list::dropdown%]", + "icons": "[%key:ui::panel::lovelace::editor::features::types::climate-preset-modes::style_list::icons%]" + }, + "fan_modes": "Fan modes" + }, "climate-hvac-modes": { "label": "Climate HVAC modes", "hvac_modes": "HVAC modes", @@ -5338,6 +5533,16 @@ "start_pause": "Start Pause", "dock": "[%key:ui::dialogs::more_info_control::lawn_mower::dock%]" } + }, + "update-actions": { + "label": "Update actions", + "backup": "Backup", + "backup_options": { + "yes": "[%key:ui::common::yes%]", + "no": "[%key:ui::common::no%]", + "ask": "Ask" + }, + "backup_not_supported": "Backup is not supported." } } }, @@ -5646,6 +5851,7 @@ "assist": "[%key:ui::panel::lovelace::menu::assist%]", "create_list": "Create list", "delete_list": "Delete list", + "add_item": "Add item", "information": "Information", "delete_confirm_title": "Remove {name}?", "delete_confirm_text": "Are you sure you want to remove this list and all of its items?", diff --git a/yarn.lock b/yarn.lock index b7bfc015a964..2f9b96e6b6ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -55,45 +55,45 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": version: 7.23.5 resolution: "@babel/compat-data@npm:7.23.5" checksum: 088f14f646ecbddd5ef89f120a60a1b3389a50a9705d44603dca77662707d0175a5e0e0da3943c3298f1907a4ab871468656fbbf74bb7842cd8b0686b2c19736 languageName: node linkType: hard -"@babel/core@npm:7.23.5, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": - version: 7.23.5 - resolution: "@babel/core@npm:7.23.5" +"@babel/core@npm:7.23.7, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": + version: 7.23.7 + resolution: "@babel/core@npm:7.23.7" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.23.5" - "@babel/generator": "npm:^7.23.5" - "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/generator": "npm:^7.23.6" + "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.5" - "@babel/parser": "npm:^7.23.5" + "@babel/helpers": "npm:^7.23.7" + "@babel/parser": "npm:^7.23.6" "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.5" - "@babel/types": "npm:^7.23.5" + "@babel/traverse": "npm:^7.23.7" + "@babel/types": "npm:^7.23.6" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: f24265172610dbffe0e315b6a8e8f87cf87d2643c8915196adcddd81c66a8eaeb1b36fea851e2308961636a180089a5f10becaa340d5b707d5f64e2e5ffb2bc8 + checksum: 956841695ea801c8b4196d01072e6c1062335960715a6fcfd4009831003b526b00627c78b373ed49b1658c3622c71142f7ff04235fe839cac4a1a25ed51b90aa languageName: node linkType: hard -"@babel/generator@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/generator@npm:7.23.5" +"@babel/generator@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/generator@npm:7.23.6" dependencies: - "@babel/types": "npm:^7.23.5" + "@babel/types": "npm:^7.23.6" "@jridgewell/gen-mapping": "npm:^0.3.2" "@jridgewell/trace-mapping": "npm:^0.3.17" jsesc: "npm:^2.5.1" - checksum: 094af79c2e8fdb0cfd06b42ff6a39a8a95639bc987cace44f52ed5c46127f5469eb20ab5f4c8991fc00fa9c1445a1977cde8e44289d6be29ddbb315fb0fc1b45 + checksum: 864090d5122c0aa3074471fd7b79d8a880c1468480cbd28925020a3dcc7eb6e98bedcdb38983df299c12b44b166e30915b8085a7bc126e68fa7e2aadc7bd1ac5 languageName: node linkType: hard @@ -115,22 +115,22 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6": - version: 7.22.15 - resolution: "@babel/helper-compilation-targets@npm:7.22.15" +"@babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/helper-compilation-targets@npm:7.23.6" dependencies: - "@babel/compat-data": "npm:^7.22.9" - "@babel/helper-validator-option": "npm:^7.22.15" - browserslist: "npm:^4.21.9" + "@babel/compat-data": "npm:^7.23.5" + "@babel/helper-validator-option": "npm:^7.23.5" + browserslist: "npm:^4.22.2" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 9706decaa1591cf44511b6f3447eb9653b50ca3538215fe2e5387a8598c258c062f4622da5b95e61f0415706534deee619bbf53a2889f9bd967949b8f6024e0e + checksum: 05595cd73087ddcd81b82d2f3297aac0c0422858dfdded43d304786cf680ec33e846e2317e6992d2c964ee61d93945cbf1fa8ec80b55aee5bfb159227fb02cb9 languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/helper-create-class-features-plugin@npm:7.23.5" +"@babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.6, @babel/helper-create-class-features-plugin@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.23.7" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-environment-visitor": "npm:^7.22.20" @@ -143,7 +143,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: cd951e81b6a4ad79879f38edbe78d51cf29dfd5a7d33d7162aeaa3ac536dcc9a6679de8feb976bbd76d255a1654bf1742410517edd5c426fec66e0bf41eb8c45 + checksum: c8b3ef58fca399a25f00d703b0fb2ac1d86642d9e3bd7af04df77857641ed08aaca042ffb271ef93771f9272481fd1cf102a9bddfcee407fb126c927deeef6a7 languageName: node linkType: hard @@ -160,9 +160,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-define-polyfill-provider@npm:0.4.3, @babel/helper-define-polyfill-provider@npm:^0.4.3": - version: 0.4.3 - resolution: "@babel/helper-define-polyfill-provider@npm:0.4.3" +"@babel/helper-define-polyfill-provider@npm:0.4.4, @babel/helper-define-polyfill-provider@npm:^0.4.4": + version: 0.4.4 + resolution: "@babel/helper-define-polyfill-provider@npm:0.4.4" dependencies: "@babel/helper-compilation-targets": "npm:^7.22.6" "@babel/helper-plugin-utils": "npm:^7.22.5" @@ -171,7 +171,7 @@ __metadata: resolve: "npm:^1.14.2" peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 9ab9d6a2cfaffc44f8b7ad661b642b03f31597282557686b7f4c64f67acd3c5844d4eac028e63d238819bcec0549ddef7dc0539d10966ace96f4c61e97b33138 + checksum: 16c312e40ecf2ead81f3ab7275387079071012d2363022c04cf16d56fe0d781185f3a517b928f4556c716ae45e0567b817b636d5cd2fee8fb2ce2b18a04c5bcd languageName: node linkType: hard @@ -335,14 +335,14 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/helpers@npm:7.23.5" +"@babel/helpers@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/helpers@npm:7.23.7" dependencies: "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.5" - "@babel/types": "npm:^7.23.5" - checksum: 84a813db55e03b5f47cef1210eb22751dae5dc3605bf62ff9acd4c248d857f94cb43dc7299e0edcec9312b31088f0d77f881282df2957e65a322b5412801cc24 + "@babel/traverse": "npm:^7.23.7" + "@babel/types": "npm:^7.23.6" + checksum: ec07061dc871d406ed82c8757c4d7a510aaf15145799fb0a2c3bd3c72ca101fe82a02dd5f83ca604fbbba5de5408dd731bb1452150562bed4f3b0a2846f81f61 languageName: node linkType: hard @@ -357,12 +357,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.18.4, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/parser@npm:7.23.5" +"@babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5, @babel/parser@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/parser@npm:7.23.6" bin: parser: ./bin/babel-parser.js - checksum: 828c250ace0c58f9dc311fd13ad3da34e86ed27a5c6b4183ce9d85be250e78eeb71a13f6d51a368c46f8cbe51106c726bfbb158bf46a89db3a168a0002d3050a + checksum: 6be3a63d3c9d07b035b5a79c022327cb7e16cbd530140ecb731f19a650c794c315a72c699a22413ebeafaff14aa8f53435111898d59e01a393d741b85629fa7d languageName: node linkType: hard @@ -390,30 +390,28 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.3" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.7" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: 6e13f14949eb943d33cf4d3775a7195fa93c92851dfb648931038e9eb92a9b1709fdaa5a0ff6cf063cfcd68b3e52d280f3ebc0f3085b3e006e64dd6196ecb72a + checksum: 3b0c9554cd0048e6e7341d7b92f29d400dbc6a5a4fc2f86dbed881d32e02ece9b55bc520387bae2eac22a5ab38a0b205c29b52b181294d99b4dd75e27309b548 languageName: node linkType: hard -"@babel/plugin-proposal-decorators@npm:7.23.5": - version: 7.23.5 - resolution: "@babel/plugin-proposal-decorators@npm:7.23.5" +"@babel/plugin-proposal-decorators@npm:7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-proposal-decorators@npm:7.23.7" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.23.5" + "@babel/helper-create-class-features-plugin": "npm:^7.23.7" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.20" - "@babel/helper-split-export-declaration": "npm:^7.22.6" "@babel/plugin-syntax-decorators": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 03d74af44cd332607e9ec0f78917bbcca5a0773175a87d614a8b5dd532a9accfa2bb203313bf962c7d4767b4e8161936ebe3b71de31986227bb6de5be4572860 + checksum: 1fc506b113fa204323537b3299686641c29b7626f05aa098c68a818da65ce657d2398c49aea69af91c45bbdfca6086424e28d283729dba401eb93c8a16826c95 languageName: node linkType: hard @@ -669,9 +667,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.4" +"@babel/plugin-transform-async-generator-functions@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.7" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-plugin-utils": "npm:^7.22.5" @@ -679,7 +677,7 @@ __metadata: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e2fc132c9033711d55209f4781e1fc73f0f4da5e0ca80a2da73dec805166b73c92a6e83571a8994cd2c893a28302e24107e90856202b24781bab734f800102bb + checksum: b1f66b23423933c27336b1161ac92efef46683321caea97e2255a666f992979376f47a5559f64188d3831fa66a4b24c2a7a40838cc0e9737e90eebe20e8e6372 languageName: node linkType: hard @@ -844,14 +842,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-for-of@npm:7.23.3" +"@babel/plugin-transform-for-of@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/plugin-transform-for-of@npm:7.23.6" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 745054f125fba6dbaea3d863352c94266c97db87e3521bc6c436a8c05f384821907c0109ace437a90342e423a3365f4d8e592de06e4a241bbd7070e1f293604f + checksum: b84ef1f26a2db316237ae6d10fa7c22c70ac808ed0b8e095a8ecf9101551636cbb026bee9fb95a0a7944f3b8278ff9636a9088cb4a4ac5b84830a13829242735 languageName: node linkType: hard @@ -1135,19 +1134,19 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-runtime@npm:7.23.4": - version: 7.23.4 - resolution: "@babel/plugin-transform-runtime@npm:7.23.4" +"@babel/plugin-transform-runtime@npm:7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-transform-runtime@npm:7.23.7" dependencies: "@babel/helper-module-imports": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" - babel-plugin-polyfill-corejs2: "npm:^0.4.6" - babel-plugin-polyfill-corejs3: "npm:^0.8.5" - babel-plugin-polyfill-regenerator: "npm:^0.5.3" + babel-plugin-polyfill-corejs2: "npm:^0.4.7" + babel-plugin-polyfill-corejs3: "npm:^0.8.7" + babel-plugin-polyfill-regenerator: "npm:^0.5.4" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d962002d4cdeae91866fb7e9fb8ae5e5d568bd9ea866cfd03e8e564120f6f7db99d8f142f9b044819b975c0d0ca76418d8673bf46ea48feeba7779ae4f3bc46f + checksum: 1e0b21c943e565e6a2a859991059f5b5a8b917689aab9b3beb172babece1843b42f9ae9ff9913f01134fb201fd67ac2831559578949c7287e7c782e6d6740de8 languageName: node linkType: hard @@ -1208,16 +1207,16 @@ __metadata: linkType: hard "@babel/plugin-transform-typescript@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-typescript@npm:7.23.3" + version: 7.23.6 + resolution: "@babel/plugin-transform-typescript@npm:7.23.6" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-create-class-features-plugin": "npm:^7.22.15" + "@babel/helper-create-class-features-plugin": "npm:^7.23.6" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-typescript": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 74dff264701131e615e577d4080d8a1de99cf4b11f4a9cdf8228091456241529fa1f3ebbcbc8399b906972258c2d21088e361c569c76a06353561abdc8922d00 + checksum: a816811129f3fcb0af1aeb52b84285be390ed8a0eedab17d31fa8e6847c4ca39b4b176d44831f20a8561b3f586974053570ad7bdfa51f89566276e6b191786d2 languageName: node linkType: hard @@ -1268,17 +1267,17 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:7.23.5, @babel/preset-env@npm:^7.11.0": - version: 7.23.5 - resolution: "@babel/preset-env@npm:7.23.5" +"@babel/preset-env@npm:7.23.7, @babel/preset-env@npm:^7.11.0": + version: 7.23.7 + resolution: "@babel/preset-env@npm:7.23.7" dependencies: "@babel/compat-data": "npm:^7.23.5" - "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/helper-validator-option": "npm:^7.23.5" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.23.3" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.3" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.7" "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-class-properties": "npm:^7.12.13" @@ -1299,7 +1298,7 @@ __metadata: "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" "@babel/plugin-transform-arrow-functions": "npm:^7.23.3" - "@babel/plugin-transform-async-generator-functions": "npm:^7.23.4" + "@babel/plugin-transform-async-generator-functions": "npm:^7.23.7" "@babel/plugin-transform-async-to-generator": "npm:^7.23.3" "@babel/plugin-transform-block-scoped-functions": "npm:^7.23.3" "@babel/plugin-transform-block-scoping": "npm:^7.23.4" @@ -1313,7 +1312,7 @@ __metadata: "@babel/plugin-transform-dynamic-import": "npm:^7.23.4" "@babel/plugin-transform-exponentiation-operator": "npm:^7.23.3" "@babel/plugin-transform-export-namespace-from": "npm:^7.23.4" - "@babel/plugin-transform-for-of": "npm:^7.23.3" + "@babel/plugin-transform-for-of": "npm:^7.23.6" "@babel/plugin-transform-function-name": "npm:^7.23.3" "@babel/plugin-transform-json-strings": "npm:^7.23.4" "@babel/plugin-transform-literals": "npm:^7.23.3" @@ -1347,14 +1346,14 @@ __metadata: "@babel/plugin-transform-unicode-regex": "npm:^7.23.3" "@babel/plugin-transform-unicode-sets-regex": "npm:^7.23.3" "@babel/preset-modules": "npm:0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2: "npm:^0.4.6" - babel-plugin-polyfill-corejs3: "npm:^0.8.5" - babel-plugin-polyfill-regenerator: "npm:^0.5.3" + babel-plugin-polyfill-corejs2: "npm:^0.4.7" + babel-plugin-polyfill-corejs3: "npm:^0.8.7" + babel-plugin-polyfill-regenerator: "npm:^0.5.4" core-js-compat: "npm:^3.31.0" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9c2c2ca7a8ac7ea5a36866f5c1df43936f60b4b5988693c574d531a2abfbcd2804d8a67db3560a8e505cf11e2c3e3031ce4104a84685cff6fbd46b884592146c + checksum: 2059dee350c39aba0a1f128d00ccfd7abf97f92a9b661f4db07a96c11d91c928a9f1df39477583f068090627bff571b4415f1a4f94008d29f6ad8b124e69804e languageName: node linkType: hard @@ -1393,12 +1392,12 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:7.23.5, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4": - version: 7.23.5 - resolution: "@babel/runtime@npm:7.23.5" +"@babel/runtime@npm:7.23.7, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4": + version: 7.23.7 + resolution: "@babel/runtime@npm:7.23.7" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 0f1669f639af30a0a2948ffcefa2c61935f337b0777bd94f8d7bc66bba8e7d4499e725caeb0449540d9c6d67399b733c4e719babb43ce9a0f33095aa01b42b37 + checksum: b29cf3ca6277aea8c5c823d9b86e7f7153757f07eaaa81d726f125de00ac0e7451c90845770f919826a94ade8f71a6bda9c0421410dfcc285ee17a40f8f8ca00 languageName: node linkType: hard @@ -1413,32 +1412,32 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/traverse@npm:7.23.5" +"@babel/traverse@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/traverse@npm:7.23.7" dependencies: "@babel/code-frame": "npm:^7.23.5" - "@babel/generator": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.6" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-hoist-variables": "npm:^7.22.5" "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.5" - "@babel/types": "npm:^7.23.5" - debug: "npm:^4.1.0" + "@babel/parser": "npm:^7.23.6" + "@babel/types": "npm:^7.23.6" + debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 281cae2765caad88c7af6214eab3647db0e9cadc7ffcd3fd924f09fbb9bd09d97d6fb210794b7545c317ce417a30016636530043a455ba6922349e39c1ba622a + checksum: 3215e59429963c8dac85c26933372cdd322952aa9930e4bc5ef2d0e4bd7a1510d1ecf8f8fd860ace5d4d9fe496d23805a1ea019a86410aee4111de5f63ee84f9 languageName: node linkType: hard -"@babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.5, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.23.5 - resolution: "@babel/types@npm:7.23.5" +"@babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.23.6 + resolution: "@babel/types@npm:7.23.6" dependencies: "@babel/helper-string-parser": "npm:^7.23.4" "@babel/helper-validator-identifier": "npm:^7.22.20" to-fast-properties: "npm:^2.0.0" - checksum: a623a4e7f396f1903659099da25bfa059694a49f42820f6b5288347f1646f0b37fb7cc550ba45644e9067149368ef34ccb1bd4a4251ec59b83b3f7765088f363 + checksum: 07e70bb94d30b0231396b5e9a7726e6d9227a0a62e0a6830c0bd3232f33b024092e3d5a7d1b096a65bbf2bb43a9ab4c721bf618e115bfbb87b454fa060f88cbf languageName: node linkType: hard @@ -1449,12 +1448,12 @@ __metadata: languageName: node linkType: hard -"@bundle-stats/plugin-webpack-filter@npm:4.8.3": - version: 4.8.3 - resolution: "@bundle-stats/plugin-webpack-filter@npm:4.8.3" +"@bundle-stats/plugin-webpack-filter@npm:4.8.4": + version: 4.8.4 + resolution: "@bundle-stats/plugin-webpack-filter@npm:4.8.4" peerDependencies: core-js: ^3.0.0 - checksum: a832be786197b0cd534e4ccb35cd7230f322b2b77697f5f4ac0b098e51f7867bff0364020f6015d31f2963619e1408933454841baac035452a9fec37d921f841 + checksum: 7a33a19094fb32579ca215cfee7c536a7e524558e6a17bee0376377691b4957bd1346531dfe3b01e8daf364acef75e1926f3d1aed76d986be79ba374157782fb languageName: node linkType: hard @@ -1528,14 +1527,14 @@ __metadata: languageName: node linkType: hard -"@codemirror/view@npm:6.22.2, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0": - version: 6.22.2 - resolution: "@codemirror/view@npm:6.22.2" +"@codemirror/view@npm:6.22.3, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0": + version: 6.22.3 + resolution: "@codemirror/view@npm:6.22.3" dependencies: "@codemirror/state": "npm:^6.1.4" style-mod: "npm:^4.1.0" w3c-keyname: "npm:^2.2.4" - checksum: ddd75424e9bef556663f4bfa4f76c181bc80c8cb6fd12f910714f7d3cc6942a6732c569b9c69561d99b66852a8537870cf7306df9326558c642a95a0364fcf00 + checksum: c0ad3e9ab49ca9aba214cfe317e506f25d094bb3243cafd0309093279eb99084810f289a5cc019db6c35463813707bdc31557b28afb30d390f4736dd0dadc541 languageName: node linkType: hard @@ -1576,9 +1575,9 @@ __metadata: linkType: hard "@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": - version: 4.9.1 - resolution: "@eslint-community/regexpp@npm:4.9.1" - checksum: 8f1ba51fa5dedd93f01623382d006c838a436aaea85561c7e540b15600988350843bf746a60e2aaefa79ee4904c9dc0a2f3f00e025b162112c76520ffb34805d + version: 4.10.0 + resolution: "@eslint-community/regexpp@npm:4.10.0" + checksum: 8c36169c815fc5d726078e8c71a5b592957ee60d08c6470f9ce0187c8046af1a00afbda0a065cc40ff18d5d83f82aed9793c6818f7304a74a7488dc9f3ecbd42 languageName: node linkType: hard @@ -1599,10 +1598,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.55.0": - version: 8.55.0 - resolution: "@eslint/js@npm:8.55.0" - checksum: 34b001a95b16501fd64f525b1de3ab0e4c252e5820b74069004934cb13977fc04ba4522a3e8f8074bd6af49da10d3444cd49fa711819f425ad73d6bf46eea82d +"@eslint/js@npm:8.56.0": + version: 8.56.0 + resolution: "@eslint/js@npm:8.56.0" + checksum: 97a4b5ccf7e24f4d205a1fb0f21cdcd610348ecf685f6798a48dd41ba443f2c1eedd3050ff5a0b8f30b8cf6501ab512aa9b76e531db15e59c9ebaa41f3162e37 languageName: node linkType: hard @@ -2041,7 +2040,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": +"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.9": version: 0.3.20 resolution: "@jridgewell/trace-mapping@npm:0.3.20" dependencies: @@ -2075,9 +2074,9 @@ __metadata: linkType: hard "@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.1.0": - version: 1.1.0 - resolution: "@lezer/common@npm:1.1.0" - checksum: cabe34758bb41c6c7e38aaabdc8a6f51469b1307ed9b5760dd1fc7777d77a012e3e3f37c970a91319c10cc5e4d355db5c0e5515cc9392b9d0b833a66a8cc4120 + version: 1.1.2 + resolution: "@lezer/common@npm:1.1.2" + checksum: 2fb13b87c6cd1a33924908e3eb3bf08d9be9a624b32ca28d8dd369bacc7347f1765628353a8cb0d713d81a3fdc4d7939d5b0323764ecd2b926f0ca5255fe89ec languageName: node linkType: hard @@ -2091,11 +2090,11 @@ __metadata: linkType: hard "@lezer/lr@npm:^1.0.0": - version: 1.3.13 - resolution: "@lezer/lr@npm:1.3.13" + version: 1.3.14 + resolution: "@lezer/lr@npm:1.3.14" dependencies: "@lezer/common": "npm:^1.0.0" - checksum: b61fc33991b26cfde1e3053be50d8b3f09943eaf8a235fd009e7bde790633ff8bfa07b34240ce5962f414ce3adbf9b44c8bf16cb1aca986ae089a0d39fff85fa + checksum: 9d32701f91fdf7d570073f5e83cda028c80bea7633f928c809eb6977d4f0b5e32424f95fb78cafea98789c4c0dadc9694636903290f0c1c418d2a47ed7f18f46 languageName: node linkType: hard @@ -3134,27 +3133,27 @@ __metadata: languageName: node linkType: hard -"@material/web@npm:=1.0.1": - version: 1.0.1 - resolution: "@material/web@npm:1.0.1" +"@material/web@npm:=1.1.1": + version: 1.1.1 + resolution: "@material/web@npm:1.1.1" dependencies: lit: "npm:^2.7.4 || ^3.0.0" tslib: "npm:^2.4.0" - checksum: febc2ee82d5d85a3387ca89ef6179893e50d491655355a7377f6b79bd2d367a685c14fe7f805acb2a77dd2d0f313ab661c6fbcedd70d243fcfaef890152751cc + checksum: e1066e50b06af54e64029a281bd49044c6b54817fa920453d622680f8dcbbbc920f83dfd6977c15b669fe3bfdf1e01cb851a4cd38d27cc96a497590a4b3cb2cd languageName: node linkType: hard -"@mdi/js@npm:7.3.67": - version: 7.3.67 - resolution: "@mdi/js@npm:7.3.67" - checksum: 0f54a632d4ab3213931cc348d524f0f5e6b492ea74f8f1babe00298a8e7ae07b2fec88cfaf0cf7be0f1e427026a8da23fb8bed55b22892ad3b40b482e01cfb17 +"@mdi/js@npm:7.4.47": + version: 7.4.47 + resolution: "@mdi/js@npm:7.4.47" + checksum: c1a8fc82f23030bccc0cf324b13b73a0034d06140e79f8bc7b0e4e59275624c470e5ca6524d6141ad8c4fe3ad0f314c7af99afb3e38df163eb50d3b13b9eab17 languageName: node linkType: hard -"@mdi/svg@npm:7.3.67": - version: 7.3.67 - resolution: "@mdi/svg@npm:7.3.67" - checksum: bd9593e6cc16d140b681dedacd2a164da7884186d496c89809a9389c980c295d16edf4ba8744338d28bb6e627b1801f47c4c0cbf7b8faf7084ee87cd5d7b4250 +"@mdi/svg@npm:7.4.47": + version: 7.4.47 + resolution: "@mdi/svg@npm:7.4.47" + checksum: e5a6b80bb82cc7b7c98e9a018883aee1eaa0e98edfb62192e7ec5798fa573f30b9226629361d747de6e0a81fe6657fb37e9bc2fd89c68e9b094a07e863be4fba languageName: node linkType: hard @@ -3185,6 +3184,19 @@ __metadata: languageName: node linkType: hard +"@npmcli/agent@npm:^2.0.0": + version: 2.2.0 + resolution: "@npmcli/agent@npm:2.2.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.1" + checksum: 822ea077553cd9cfc5cbd6d92380b0950fcb054a7027cd1b63a33bd0cbb16b0c6626ea75d95ec0e804643c8904472d3361d2da8c2444b1fb02a9b525d9c07c41 + languageName: node + linkType: hard + "@npmcli/fs@npm:^3.1.0": version: 3.1.0 resolution: "@npmcli/fs@npm:3.1.0" @@ -3214,8 +3226,8 @@ __metadata: linkType: hard "@octokit/core@npm:^5.0.0": - version: 5.0.1 - resolution: "@octokit/core@npm:5.0.1" + version: 5.0.2 + resolution: "@octokit/core@npm:5.0.2" dependencies: "@octokit/auth-token": "npm:^4.0.0" "@octokit/graphql": "npm:^7.0.0" @@ -3224,18 +3236,17 @@ __metadata: "@octokit/types": "npm:^12.0.0" before-after-hook: "npm:^2.2.0" universal-user-agent: "npm:^6.0.0" - checksum: e0f6398e594ab1add6655178e4460f0ff38496299ae752a176504727fa3c655e559b2d362470a36077985d5990ae011d9d5118828f605ba183eaf80af2932804 + checksum: bb991f88793fab043c4c09f9441432596fe0e6448caf42cd2209f52c1f26807418be488ad2cea7a8293e58e79e5c0019f38dda46e8cf96af5e89e43cca37ec3e languageName: node linkType: hard "@octokit/endpoint@npm:^9.0.0": - version: 9.0.1 - resolution: "@octokit/endpoint@npm:9.0.1" + version: 9.0.4 + resolution: "@octokit/endpoint@npm:9.0.4" dependencies: "@octokit/types": "npm:^12.0.0" - is-plain-object: "npm:^5.0.0" universal-user-agent: "npm:^6.0.0" - checksum: 8d1e6540cab8686afd977d0a256528b748aba0910530c903c032676c701073f5b90786b8ba74b573f2dc5de41befdb59d3ddb83b1d22e5ab54fb32b3d0abb6c5 + checksum: 7df35c96f2b5628fe5b3f44a72614be9b439779c06b4dd1bb72283b3cb2ea53e59e1f9a108798efe5404b6856f4380a4c5be12d93255d854f0683cd6e22f3a27 languageName: node linkType: hard @@ -3258,40 +3269,33 @@ __metadata: linkType: hard "@octokit/oauth-methods@npm:^4.0.0": - version: 4.0.0 - resolution: "@octokit/oauth-methods@npm:4.0.0" + version: 4.0.1 + resolution: "@octokit/oauth-methods@npm:4.0.1" dependencies: "@octokit/oauth-authorization-url": "npm:^6.0.2" "@octokit/request": "npm:^8.0.2" "@octokit/request-error": "npm:^5.0.0" - "@octokit/types": "npm:^11.0.0" + "@octokit/types": "npm:^12.0.0" btoa-lite: "npm:^1.0.0" - checksum: 477ba87aeccc6d314abec4e5d57414885971b3bafd25d676f8dee42907590b11bf4890cbfece54706ddbde841a52ae406464119354b526245fa0daaf04e44b47 + checksum: a749cbe5e6d8799428e8c3db35f22fd9576c0a37e68c1e34bfbe2fdb56fd6ce76552352eed15308b8f243d61b54cc68c720fb3e338872d9bf3bf94b1ee8b1827 languageName: node linkType: hard -"@octokit/openapi-types@npm:^18.0.0": - version: 18.1.1 - resolution: "@octokit/openapi-types@npm:18.1.1" - checksum: bd2920a238f74c6ccc1e2ee916bd3e17adeeef3bbb1726f821b8722dceaeff5ea2786b3170cc25dd51775cb9179d3cdf448a3526e70b8a1fc21cdd8aa52e5d4c - languageName: node - linkType: hard - -"@octokit/openapi-types@npm:^19.0.2": - version: 19.0.2 - resolution: "@octokit/openapi-types@npm:19.0.2" - checksum: 6814c76917716ee87fbb1d62317037c41d3080f8e73d0c26ebb43ccd3a0ca90d9ee77f5404344060bea30a6b7b5def0016caada3ebaee5ec3a2c9494c28ba28c +"@octokit/openapi-types@npm:^19.1.0": + version: 19.1.0 + resolution: "@octokit/openapi-types@npm:19.1.0" + checksum: 3abedc09baa91bb4de00a2b82bf519401c2b6388913b7caa98541002c9e9612eba8256926323b1e40782ac700309a3373bb8c13520af325cef1accc40cb4566b languageName: node linkType: hard "@octokit/plugin-paginate-rest@npm:^9.0.0": - version: 9.0.0 - resolution: "@octokit/plugin-paginate-rest@npm:9.0.0" + version: 9.1.5 + resolution: "@octokit/plugin-paginate-rest@npm:9.1.5" dependencies: - "@octokit/types": "npm:^12.0.0" + "@octokit/types": "npm:^12.4.0" peerDependencies: "@octokit/core": ">=5" - checksum: 1fcf2358d260f91ac995ceec725584fadda3a17cd895459942c78aa69c43969d1bb79e80b1cce80870dc28d018f1eaa39aeb1d4f1076e90b8b65378675fa9e02 + checksum: 5f1793ebebc9e2feaf8574beb2308b6fe9d0fec69d3fc3c93ed7ce8083d34e7ae7452121bd88b27e9ba91da29d648f8ffbf19d6f02787f8273a8bb0e3fbc2b9f languageName: node linkType: hard @@ -3305,13 +3309,13 @@ __metadata: linkType: hard "@octokit/plugin-rest-endpoint-methods@npm:^10.0.0": - version: 10.0.1 - resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.0.1" + version: 10.2.0 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.2.0" dependencies: - "@octokit/types": "npm:^12.0.0" + "@octokit/types": "npm:^12.3.0" peerDependencies: "@octokit/core": ">=5" - checksum: 8953424d8527b28f63e268b139296f1a14a06b61497d5a7f316390ecb87db889d0f08b44f713864f4e17afd398115f55f32d21cfa746530f5689e050526d86cf + checksum: 0f8ca73b3e582b366b400278f19df6309f263efa3809a9d6ba613063e7a26f16d6f8d69c413bf9b23c2431ad4c795e4e06a43717b6acc1367186fb55347cfb69 languageName: node linkType: hard @@ -3340,15 +3344,14 @@ __metadata: linkType: hard "@octokit/request@npm:^8.0.0, @octokit/request@npm:^8.0.1, @octokit/request@npm:^8.0.2": - version: 8.1.4 - resolution: "@octokit/request@npm:8.1.4" + version: 8.1.6 + resolution: "@octokit/request@npm:8.1.6" dependencies: "@octokit/endpoint": "npm:^9.0.0" "@octokit/request-error": "npm:^5.0.0" "@octokit/types": "npm:^12.0.0" - is-plain-object: "npm:^5.0.0" universal-user-agent: "npm:^6.0.0" - checksum: a51470f47009b078a29e80be62e522083a82a0eae0e0a1f2fd85e220b84274d6c44f3c43d594fc29d5901b0597873dc95222d38c8697574314bd0dfcad9915f6 + checksum: aebea1c33d607d23c70f663cd5f8279a8bd932ab77b4ca5cca3b33968a347b4adb47476c886086f3a9aa1acefab3b79adac78ee7aa2dacd67eb1f2a05e272618 languageName: node linkType: hard @@ -3364,21 +3367,12 @@ __metadata: languageName: node linkType: hard -"@octokit/types@npm:^11.0.0": - version: 11.1.0 - resolution: "@octokit/types@npm:11.1.0" +"@octokit/types@npm:^12.0.0, @octokit/types@npm:^12.3.0, @octokit/types@npm:^12.4.0": + version: 12.4.0 + resolution: "@octokit/types@npm:12.4.0" dependencies: - "@octokit/openapi-types": "npm:^18.0.0" - checksum: ebd510c14c4b26df127b76b4ed6b4b9a97cd6ec7a047532060f8346bfb29a68414c7189ee2b98f5386bcd7fa1a8c29af8e8460e5a7373cf6bf38a11775c8e26d - languageName: node - linkType: hard - -"@octokit/types@npm:^12.0.0": - version: 12.3.0 - resolution: "@octokit/types@npm:12.3.0" - dependencies: - "@octokit/openapi-types": "npm:^19.0.2" - checksum: ab78fd25490f995f79e341b00c375bade64eedb44d4c76fa3da85961003ba1efcac3cf168ea221bf4f9f5761afe91738412737acf30f1f41f3f2dbad14b872e4 + "@octokit/openapi-types": "npm:^19.1.0" + checksum: b0a893e31fed59a919c2072ae67b671aa5f21e00ee3dee689af325f09f12ddd9175ce07c590b835d183bcb1cd2a2da908e02391b2fc33071881561366b2a35e7 languageName: node linkType: hard @@ -3783,17 +3777,17 @@ __metadata: languageName: node linkType: hard -"@rollup/plugin-json@npm:6.0.1": - version: 6.0.1 - resolution: "@rollup/plugin-json@npm:6.0.1" +"@rollup/plugin-json@npm:6.1.0": + version: 6.1.0 + resolution: "@rollup/plugin-json@npm:6.1.0" dependencies: - "@rollup/pluginutils": "npm:^5.0.1" + "@rollup/pluginutils": "npm:^5.1.0" peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - checksum: 86995e3ceec0205bd0b5ae3075f4592e0ab3e6e6327a5dcfc825b44113eaae5819d26d5403d29b177ac59299e0b08c641c8d030e0c72805b92805ededc9cac44 + checksum: cc018d20c80242a2b8b44fae61a968049cf31bb8406218187cc7cda35747616594e79452dd65722e7da6dd825b392e90d4599d43cd4461a02fefa2865945164e languageName: node linkType: hard @@ -3888,9 +3882,9 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.0.1": - version: 5.0.5 - resolution: "@rollup/pluginutils@npm:5.0.5" +"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.1.0": + version: 5.1.0 + resolution: "@rollup/pluginutils@npm:5.1.0" dependencies: "@types/estree": "npm:^1.0.0" estree-walker: "npm:^2.0.2" @@ -3900,7 +3894,7 @@ __metadata: peerDependenciesMeta: rollup: optional: true - checksum: 7c07bdb6bc898a3188a860c16df3d26fcd4c632f8ea93a1e1c2387445f86f877c717f714e09652d7442c791b9fed10a2332525036bcb6fb99aad64888ce1d690 + checksum: abb15eaec5b36f159ec351b48578401bedcefdfa371d24a914cfdbb1e27d0ebfbf895299ec18ccc343d247e71f2502cba21202bc1362d7ef27d5ded699e5c2b2 languageName: node linkType: hard @@ -3987,19 +3981,12 @@ __metadata: languageName: node linkType: hard -"@tootallnate/once@npm:2": - version: 2.0.0 - resolution: "@tootallnate/once@npm:2.0.0" - checksum: ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 - languageName: node - linkType: hard - "@types/accepts@npm:*": - version: 1.3.6 - resolution: "@types/accepts@npm:1.3.6" + version: 1.3.7 + resolution: "@types/accepts@npm:1.3.7" dependencies: "@types/node": "npm:*" - checksum: e5e8d72e9abd460c3c3cd50d4a83b5f66d1437f6c5dd522c1ea3c2596ef85dd2a604f5e972816bb98733d1c0e91789625e4edc9bee23f9ea48bf6507289ff38e + checksum: 7678cf74976e16093aff6e6f9755826faf069ac1e30179276158ce46ea246348ff22ca6bdd46cef08428881337d9ceefbf00bab08a7731646eb9fc9449d6a1e7 languageName: node linkType: hard @@ -4011,31 +3998,31 @@ __metadata: linkType: hard "@types/body-parser@npm:*": - version: 1.19.4 - resolution: "@types/body-parser@npm:1.19.4" + version: 1.19.5 + resolution: "@types/body-parser@npm:1.19.5" dependencies: "@types/connect": "npm:*" "@types/node": "npm:*" - checksum: 10accc30773319bd49af7d12d2cd5faf9a0293ea4764345297f26ba6ef31d5caa7609da7619584d6c61279e09b89d3ab13d28c5cb644807c5d9c722ae1454778 + checksum: 1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82 languageName: node linkType: hard "@types/bonjour@npm:^3.5.9": - version: 3.5.12 - resolution: "@types/bonjour@npm:3.5.12" + version: 3.5.13 + resolution: "@types/bonjour@npm:3.5.13" dependencies: "@types/node": "npm:*" - checksum: d8ef676a2386f09ced670e8a04f9ea77d29d05c406ac15db97820d6feb49b2bb65d9e951565b4f7f744e0585650cae59feea284c5a330214025f708ed43bb7f5 + checksum: e827570e097bd7d625a673c9c208af2d1a22fa3885c0a1646533cf24394c839c3e5f60ac1bc60c0ddcc69c0615078c9fb2c01b42596c7c582d895d974f2409ee languageName: node linkType: hard "@types/chrome@npm:*": - version: 0.0.248 - resolution: "@types/chrome@npm:0.0.248" + version: 0.0.254 + resolution: "@types/chrome@npm:0.0.254" dependencies: "@types/filesystem": "npm:*" "@types/har-format": "npm:*" - checksum: 228d901fcb8a84949c2bd023106697d074987cffc74e5260bcf56bf1c96ed859a04a176da12b9910ad8c1538aad2315909a6fe16c91fb2ec3ca4f501ef50226f + checksum: 61f29e116cb915ccfee266f43f9235743dee7bd9ce9c736acd35dc209d5be6ca4afc4cf064b45407f5e03ac46d8180e94f2b2c32fb3cd28b21fcd1071a25e2d7 languageName: node linkType: hard @@ -4056,74 +4043,74 @@ __metadata: linkType: hard "@types/command-line-args@npm:^5.0.0": - version: 5.2.2 - resolution: "@types/command-line-args@npm:5.2.2" - checksum: 572a8b5b60a5b9a885c1627fb22223667e154cfaa399b7967ebc694beb0b38f204d0ebd42de678057e2e30580b4e922cfcca713670a29f5c85eae4faa4cd5b87 + version: 5.2.3 + resolution: "@types/command-line-args@npm:5.2.3" + checksum: 3d90db5b4bbaabd049654a0d12fa378989ab0d76a0f98d4c606761b5a08ce76458df0f9bb175219e187b4cd57e285e6f836d23e86b2c3d997820854cc3ed9121 languageName: node linkType: hard "@types/connect-history-api-fallback@npm:^1.3.5": - version: 1.5.2 - resolution: "@types/connect-history-api-fallback@npm:1.5.2" + version: 1.5.4 + resolution: "@types/connect-history-api-fallback@npm:1.5.4" dependencies: "@types/express-serve-static-core": "npm:*" "@types/node": "npm:*" - checksum: 588934d2b4877df8a8460315fd6d911749334c59cf2eba6a0aa167c4fb9b8c6789c9d9a0f5118464953634a3efad89eeb19de7d65d619d917f3a1f8d98276672 + checksum: e1dee43b8570ffac02d2d47a2b4ba80d3ca0dd1840632dafb221da199e59dbe3778d3d7303c9e23c6b401f37c076935a5bc2aeae1c4e5feaefe1c371fe2073fd languageName: node linkType: hard "@types/connect@npm:*": - version: 3.4.37 - resolution: "@types/connect@npm:3.4.37" + version: 3.4.38 + resolution: "@types/connect@npm:3.4.38" dependencies: "@types/node": "npm:*" - checksum: 79ef1f79a28235ea7cbefa153914318d7b46d60041a932681b613abd706591108f4f17ddd2072ee8ec23ba9a3fb068a6c3bbdca66b95de1a7e6039bd940ae988 + checksum: 7eb1bc5342a9604facd57598a6c62621e244822442976c443efb84ff745246b10d06e8b309b6e80130026a396f19bf6793b7cecd7380169f369dac3bfc46fb99 languageName: node linkType: hard "@types/content-disposition@npm:*": - version: 0.5.7 - resolution: "@types/content-disposition@npm:0.5.7" - checksum: 3691d07a44626501cd0e8585861f2ff542f458e04a69757702b4fe29056c6a4191103d1e2bcbc0dc74b6bcf8656fe345fe728af70e9df56c80c4372dbfb5376e + version: 0.5.8 + resolution: "@types/content-disposition@npm:0.5.8" + checksum: eeea868fb510ae7a32aa2d7de680fba79d59001f3e758a334621e10bc0a6496d3a42bb79243a5e53b9c63cb524522853ccc144fe1ab160c4247d37cdb81146c4 languageName: node linkType: hard "@types/cookies@npm:*": - version: 0.7.9 - resolution: "@types/cookies@npm:0.7.9" + version: 0.7.10 + resolution: "@types/cookies@npm:0.7.10" dependencies: "@types/connect": "npm:*" "@types/express": "npm:*" "@types/keygrip": "npm:*" "@types/node": "npm:*" - checksum: 26ce43afaf78b50955b6c63247ee1f3d1533bfeff4109916711a93f31d569f1fae81647861e9597a3a053831e3985759b4d9299e488569737a95cfe0be340fc3 + checksum: 85d4b434bac9a971d8a4122d5a7c947dcaaca98fee26e90e0b792b1046da1de414dc37ea164b1693653b9b59f72c501927de90412a3a1dff2c7bdb6abadc3608 languageName: node linkType: hard "@types/eslint-scope@npm:^3.7.3": - version: 3.7.6 - resolution: "@types/eslint-scope@npm:3.7.6" + version: 3.7.7 + resolution: "@types/eslint-scope@npm:3.7.7" dependencies: "@types/eslint": "npm:*" "@types/estree": "npm:*" - checksum: a2339e312949ae7f96bca52cde89a3d2218d4505746a78a0ba1aa56573e43b3d52ce9662b86ab785663a62fa8f2bd2fb61b990398785b40f2efc91be3fd246f8 + checksum: e2889a124aaab0b89af1bab5959847c5bec09809209255de0e63b9f54c629a94781daa04adb66bffcdd742f5e25a17614fb933965093c0eea64aacda4309380e languageName: node linkType: hard "@types/eslint@npm:*": - version: 8.44.6 - resolution: "@types/eslint@npm:8.44.6" + version: 8.56.0 + resolution: "@types/eslint@npm:8.56.0" dependencies: "@types/estree": "npm:*" "@types/json-schema": "npm:*" - checksum: 07ee27c1803fce2d732800d4972462e4c08f2ac84c70a6addb0ae2566de392eb92e39ccc8f6ab487348f751b4b253c4724d3490ea8856abcd8917acae676a2d6 + checksum: 0405403788b9b8b3dbce59b668cdf5f7dc3b3fe5f82a4bf335cd7c936b95df83d892bd70af69f0d4f463125b45d15084dc5c0eeda9982d80ddbd988aa6758b63 languageName: node linkType: hard "@types/estree@npm:*, @types/estree@npm:^1.0.0": - version: 1.0.3 - resolution: "@types/estree@npm:1.0.3" - checksum: c51984ec3003a93b619f25995ceba74428f390747d246833928d0121bb2df3b8bca67deb27fc634da47c5b341837d2ae17d0c5b8d16be5110477a73531ac3528 + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: 7de6d928dd4010b0e20c6919e1a6c27b61f8d4567befa89252055fad503d587ecb9a1e3eab1b1901f923964d7019796db810b7fd6430acb26c32866d126fd408 languageName: node linkType: hard @@ -4135,49 +4122,49 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": - version: 4.17.39 - resolution: "@types/express-serve-static-core@npm:4.17.39" + version: 4.17.41 + resolution: "@types/express-serve-static-core@npm:4.17.41" dependencies: "@types/node": "npm:*" "@types/qs": "npm:*" "@types/range-parser": "npm:*" "@types/send": "npm:*" - checksum: 5988b79a44db57c02bda423829bd431a63841ba69d75f50f35a7e7b7b8ee5cc8813b235f17270f6f492281b7b90939aa10408476e4c13bffe8472bf032d8f4aa + checksum: 7647e19d9c3d57ddd18947d2b161b90ef0aedd15875140e5b824209be41c1084ae942d4fb43cd5f2051a6a5f8c044519ef6c9ac1b2ad86b9aa546b4f1f023303 languageName: node linkType: hard "@types/express@npm:*, @types/express@npm:^4.17.13": - version: 4.17.20 - resolution: "@types/express@npm:4.17.20" + version: 4.17.21 + resolution: "@types/express@npm:4.17.21" dependencies: "@types/body-parser": "npm:*" "@types/express-serve-static-core": "npm:^4.17.33" "@types/qs": "npm:*" "@types/serve-static": "npm:*" - checksum: 7dba63831c61102397cb8dfc2a8b71bb85d93760958c43292cbd7962ba44e8978c998e47226b152d103c0a7492e2bfb2174c1f20805ddad796c7854973c8ebf9 + checksum: 7a6d26cf6f43d3151caf4fec66ea11c9d23166e4f3102edfe45a94170654a54ea08cf3103d26b3928d7ebcc24162c90488e33986b7e3a5f8941225edd5eb18c7 languageName: node linkType: hard "@types/filesystem@npm:*": - version: 0.0.34 - resolution: "@types/filesystem@npm:0.0.34" + version: 0.0.35 + resolution: "@types/filesystem@npm:0.0.35" dependencies: "@types/filewriter": "npm:*" - checksum: cdbf23e1a77ee25e867cca1b72bbf434fb1761d9223b0b501bbfa8b5d0ac3c73677562a0e5929f115f562b55bc45eb5aa159c3d6a487750b154c4ab7663e64f3 + checksum: d8eb6c2b28601c5eacf8b48464bc48f060c2a7194e2c8e493e943f3a8543e35da9c706987665356ed67b11587cc94819fd8262037bf56945c6a38569a0e260f1 languageName: node linkType: hard "@types/filewriter@npm:*": - version: 0.0.31 - resolution: "@types/filewriter@npm:0.0.31" - checksum: c4011aa5d25774419b74e77857366ecfe372515a4a07d701268d26d778e1bb9c3a6814a175494f1ba41e357d485881e2a0d3e81888d4af8dbdfe31d0eccbf7c9 + version: 0.0.32 + resolution: "@types/filewriter@npm:0.0.32" + checksum: fe2f19239c23c63c009c6d422227d692bc2a0cd1113f8ce31b0fb7048f32ec018003172199949843fdbb1c5988551c29e1e9e2238b9c160969b5e5edbfb76424 languageName: node linkType: hard "@types/geojson@npm:*": - version: 7946.0.12 - resolution: "@types/geojson@npm:7946.0.12" - checksum: 435ac23d3b66d68d142312be059c4a707bb38927edfe68f38c8051667e72f1f50f02848be5e51b56811c1c85c2ad64b8b38fd3e4c7ab43a591922ebaf3fde641 + version: 7946.0.13 + resolution: "@types/geojson@npm:7946.0.13" + checksum: b3b68457c89bc3f0445dc9eb54d07e6f89658672867c54989bc7f71f87d54e562195b291d43e1b84476493351271d7ccb9f5c6ab2012b29fbafbb0e8e43c4bca languageName: node linkType: hard @@ -4192,16 +4179,16 @@ __metadata: linkType: hard "@types/hammerjs@npm:^2.0.36": - version: 2.0.43 - resolution: "@types/hammerjs@npm:2.0.43" - checksum: 15baadb42259ee0bdd92caa3f3f53ae3b7964a47cdedeb2d6cb6b073b288016c5db3bf314dbc401ef7f2defd50aeb987d905ce0e09debd1a959f831bc14c5536 + version: 2.0.45 + resolution: "@types/hammerjs@npm:2.0.45" + checksum: 8d7f8791789853a9461f6445e625f18922a823a61042161dde5513f4a2c15ecd6361fa6f9b457ce13bfb6b518489b892fedb9e2cebb4420523cb45f1cbb4ee88 languageName: node linkType: hard "@types/har-format@npm:*": - version: 1.2.14 - resolution: "@types/har-format@npm:1.2.14" - checksum: 2ea4a55a8d0032eeed4708a9ad5dfbdf84e73f7756e484a0b8f312fc1f725a6872f3ec7cfd091b80c5b1c02f88ba09e9b57137de8b52b388e491b3f5f077e286 + version: 1.2.15 + resolution: "@types/har-format@npm:1.2.15" + checksum: fcb397741076ed1095ef8dcccd408c9ef4e20fcfeef0d3fe700f837cc015fe72ee2a3c081cc9c03d73c115005b38ba7b1c563d27e050fa612d60bc2049f309ca languageName: node linkType: hard @@ -4213,25 +4200,25 @@ __metadata: linkType: hard "@types/http-assert@npm:*": - version: 1.5.4 - resolution: "@types/http-assert@npm:1.5.4" - checksum: 70d37f65642b2999970bda2c291fcd3cd404f868efc8f85c5cab762cf9a9f1263e7bbbce651f7aa690096545dc4a77344067f578495b4acabfb71a96e10810a1 + version: 1.5.5 + resolution: "@types/http-assert@npm:1.5.5" + checksum: cd6bb7fd42cc6e2a702cb55370b8b25231954ad74c04bcd185b943a74ded3d4c28099c30f77b26951df2426441baff41718816c60b5af80efe2b8888d900bf93 languageName: node linkType: hard "@types/http-errors@npm:*": - version: 2.0.3 - resolution: "@types/http-errors@npm:2.0.3" - checksum: ea9530fb6e8a0400c4f9aac4dd628c5074f0adc8d01e2cdb917c0b97c230dedf4fcc67eadb491377b0eff5778e566648e63613a9719e383185318b9ec8c009b9 + version: 2.0.4 + resolution: "@types/http-errors@npm:2.0.4" + checksum: 1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3 languageName: node linkType: hard "@types/http-proxy@npm:^1.17.8": - version: 1.17.13 - resolution: "@types/http-proxy@npm:1.17.13" + version: 1.17.14 + resolution: "@types/http-proxy@npm:1.17.14" dependencies: "@types/node": "npm:*" - checksum: 389c07a31e6d2ad2b478680eff834245b967c0cae43598cfd3f4faf72285531a3368b54a4f39a5aa796bef0c3f340241a46d9f4b6ddc9e978c81950ae83f7ca2 + checksum: aa1a3e66cd43cbf06ea5901bf761d2031200a0ab42ba7e462a15c752e70f8669f21fb3be7c2f18fefcb83b95132dfa15740282e7421b856745598fbaea8e3a42 languageName: node linkType: hard @@ -4243,9 +4230,9 @@ __metadata: linkType: hard "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": - version: 7.0.14 - resolution: "@types/json-schema@npm:7.0.14" - checksum: 84b5efed51984c077f9cb7c5a3dcb8d8288ce1ae8825952b173c3506a0cfc90bc961d7f2a8847c440310d02bbd570cf918ac463d8310b0c9dce2252baa1ba4e0 + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7 languageName: node linkType: hard @@ -4257,24 +4244,24 @@ __metadata: linkType: hard "@types/keygrip@npm:*": - version: 1.0.4 - resolution: "@types/keygrip@npm:1.0.4" - checksum: f30ce9bfa93ab6fd67991ae9afd14e42d85b8ecbacad4aa4dccba3e0c44bb8369e53eb46d27bbed1367813707e591f8bcb693222279a7348bbcfbf9549ac483e + version: 1.0.6 + resolution: "@types/keygrip@npm:1.0.6" + checksum: d157f60bf920492347791d2b26d530d5069ce05796549fbacd4c24d66ffbebbcb0ab67b21e7a1b80a593b9fd4b67dc4843dec04c12bbc2e0fddfb8577a826c41 languageName: node linkType: hard "@types/koa-compose@npm:*": - version: 3.2.7 - resolution: "@types/koa-compose@npm:3.2.7" + version: 3.2.8 + resolution: "@types/koa-compose@npm:3.2.8" dependencies: "@types/koa": "npm:*" - checksum: ef79ca207f9815432299a65d5d9552ec384613064a9acfee8def54fc46d00125213c15743b58120d8a7800d694c5c14f05a6df57e2ac658405815ae1fdb2655e + checksum: 95c32bdee738ac7c10439bbf6342ca3b9f0aafd7e8118739eac7fb0fa703a23cfe4c88f63e13a69a16fbde702e0bcdc62b272aa734325fc8efa7e5625479752e languageName: node linkType: hard "@types/koa@npm:*, @types/koa@npm:^2.11.6": - version: 2.13.10 - resolution: "@types/koa@npm:2.13.10" + version: 2.13.12 + resolution: "@types/koa@npm:2.13.12" dependencies: "@types/accepts": "npm:*" "@types/content-disposition": "npm:*" @@ -4284,7 +4271,7 @@ __metadata: "@types/keygrip": "npm:*" "@types/koa-compose": "npm:*" "@types/node": "npm:*" - checksum: 1d537d7908743a237f08c4c21923069c1c6e228a58ef25b1dcc2b6bcede6c96888f56d7044b1c61fd951c7f5c9ad020bdad91974c022fe40b94bc9db9f9f441d + checksum: d148fb02aa25cb239d5179211cd66f19275e7fc2563532dd2bc347163332f771dea224b7555209530abf6777afa5b5c7a2d650e752fb1126ce362fbdde4ec214 languageName: node linkType: hard @@ -4307,18 +4294,18 @@ __metadata: linkType: hard "@types/lodash-es@npm:^4.17.4": - version: 4.17.10 - resolution: "@types/lodash-es@npm:4.17.10" + version: 4.17.12 + resolution: "@types/lodash-es@npm:4.17.12" dependencies: "@types/lodash": "npm:*" - checksum: a6c68872425418491d693186238e22c9da0e88bdf7ffe2b26e5436a19027ffedabeaec162e336b3722d5c43411866e859beae76a1a8f737bb5b115d5a574f758 + checksum: 56b9a433348b11c31051c6fa9028540a033a08fb80b400c589d740446c19444d73b217cf1471d4036448ef686a83e8cf2a35d1fadcb3f2105f26701f94aebb07 languageName: node linkType: hard "@types/lodash@npm:*": - version: 4.14.200 - resolution: "@types/lodash@npm:4.14.200" - checksum: aed5943a4f43b898c18e7148b6ad825dba4611230c8dc12126f20ab4ffc9250794d9134fca0c17218ad7594879835438e9c95e57b801ca6c8da0d3fbc6ef811d + version: 4.14.202 + resolution: "@types/lodash@npm:4.14.202" + checksum: 1bb9760a5b1dda120132c4b987330d67979c95dbc22612678682cd61b00302e190f4207228f3728580059cdab5582362262e3819aea59960c1017bd2b9fb26f6 languageName: node linkType: hard @@ -4330,16 +4317,16 @@ __metadata: linkType: hard "@types/mime@npm:*": - version: 3.0.3 - resolution: "@types/mime@npm:3.0.3" - checksum: d905a6b4736cc60fb56b39776b77ba0e10983d39f0aefc0034dc895b6ef90780e2f2e0a8c576539adb2963741a5aa67a6924d8940b0f7250f69e3e68a57f93b5 + version: 3.0.4 + resolution: "@types/mime@npm:3.0.4" + checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843 languageName: node linkType: hard "@types/mime@npm:^1": - version: 1.3.4 - resolution: "@types/mime@npm:1.3.4" - checksum: d8670d2993773903e00fc0d7aa3254be2f8b384300ce3278999d057afbb80a5f71543d656d9d9725d691088c0b94e4acfca84359becf122cdf5942e53c9a75ce + version: 1.3.5 + resolution: "@types/mime@npm:1.3.5" + checksum: e29a5f9c4776f5229d84e525b7cd7dd960b51c30a0fb9a028c0821790b82fca9f672dab56561e2acd9e8eed51d431bde52eafdfef30f643586c4162f1aecfc78 languageName: node linkType: hard @@ -4357,12 +4344,21 @@ __metadata: languageName: node linkType: hard +"@types/node-forge@npm:^1.3.0": + version: 1.3.10 + resolution: "@types/node-forge@npm:1.3.10" + dependencies: + "@types/node": "npm:*" + checksum: 111520ac4db33bba4e46fcb75e9c29234ca78e2ece32fc929e7382798cdb7985e01da7e8f70c32769f42996e8d06f347d34d90308951cf2d004f418135ac7735 + languageName: node + linkType: hard + "@types/node@npm:*": - version: 20.8.7 - resolution: "@types/node@npm:20.8.7" + version: 20.10.5 + resolution: "@types/node@npm:20.10.5" dependencies: - undici-types: "npm:~5.25.1" - checksum: a347ac7e6a9748ffff018ca01142ba625e774cb0b53785abb58b16a5a8468cc9b7656686dbe4c39c2f3fc477439994ee8aeae9b80ced86f320598bafaf83f802 + undici-types: "npm:~5.26.4" + checksum: 4a378428d2c9f692b19801a5a3d20dc4c0ad5d4a3d103350f8b401af439941a9aa5efeadc8eb9db13c66c620318bc7f336abfc8934f82fd32c4a689d85068c6f languageName: node linkType: hard @@ -4381,9 +4377,9 @@ __metadata: linkType: hard "@types/offscreencanvas@npm:^2019.6.4": - version: 2019.7.2 - resolution: "@types/offscreencanvas@npm:2019.7.2" - checksum: 23b7b463181af20737925ca1c670eba512be1c45009a8205f098ab6ba52b54e5c945180345ba848a1f56bade856e125e83944fc10df88c94a041fa48b4eb6ddf + version: 2019.7.3 + resolution: "@types/offscreencanvas@npm:2019.7.3" + checksum: 53a394a65ae08eddff6e0a2a8db72abecc94f41fc8fee166e8900075d3c1ca32540ddf5b4836c37357d53a0253a03fea4d781b2db543e3f08bc1cdc2dc0fefb5 languageName: node linkType: hard @@ -4404,9 +4400,9 @@ __metadata: linkType: hard "@types/prismjs@npm:^1.16.5": - version: 1.26.2 - resolution: "@types/prismjs@npm:1.26.2" - checksum: d86561508d423eaf1dc2dda1e7f465888731a6af40577eac1a8a52aaac330dee121c702f23868e0a96fca9c907f960286e2f3431e3f16cd13612276745e9235c + version: 1.26.3 + resolution: "@types/prismjs@npm:1.26.3" + checksum: 4bd55230ffc0b2b16f4008be3a7f1d7c6b32dd3bed8006e64d24fb22c44fc7e300dac77b856f732803ccdc9a3472b2c0ee7776cad048843c47d608c41a89b6a6 languageName: node linkType: hard @@ -4420,16 +4416,16 @@ __metadata: linkType: hard "@types/qs@npm:*": - version: 6.9.9 - resolution: "@types/qs@npm:6.9.9" - checksum: 03ddbd032bcaa8f07429efe9de6d0fc027ccdd1e24eac1656bd931c2210c204bbc25be0937a9d46702fb6262fb6ffcc2980e040b399b62a3f91ec6e387c2edae + version: 6.9.11 + resolution: "@types/qs@npm:6.9.11" + checksum: 620ca1628bf3da65662c54ed6ebb120b18a3da477d0bfcc872b696685a9bb1893c3c92b53a1190a8f54d52eaddb6af8b2157755699ac83164604329935e8a7f2 languageName: node linkType: hard "@types/range-parser@npm:*": - version: 1.2.6 - resolution: "@types/range-parser@npm:1.2.6" - checksum: 22decf0fa30a5fb5b26b9d30052c8eca1dddf55449c87031c8d58a4e2e75c606d7bab6a1409988c96f774eb0ebf814147d47c76487d1d0d83441f1ab26bd5d6a + version: 1.2.7 + resolution: "@types/range-parser@npm:1.2.7" + checksum: 95640233b689dfbd85b8c6ee268812a732cf36d5affead89e806fe30da9a430767af8ef2cd661024fd97e19d61f3dec75af2df5e80ec3bea000019ab7028629a languageName: node linkType: hard @@ -4457,19 +4453,19 @@ __metadata: linkType: hard "@types/semver@npm:^7.5.0": - version: 7.5.4 - resolution: "@types/semver@npm:7.5.4" - checksum: e99c3edc8d64f56abcd891b9e44a45c4ae3cab551c8af5aa67b5df2b49e5fd03f74aac9da71fd5357a50a08d5deb95014516956b15b407052e07f25c7a4a606e + version: 7.5.6 + resolution: "@types/semver@npm:7.5.6" + checksum: e77282b17f74354e17e771c0035cccb54b94cc53d0433fa7e9ba9d23fd5d7edcd14b6c8b7327d58bbd89e83b1c5eda71dfe408e06b929007e2b89586e9b63459 languageName: node linkType: hard "@types/send@npm:*": - version: 0.17.3 - resolution: "@types/send@npm:0.17.3" + version: 0.17.4 + resolution: "@types/send@npm:0.17.4" dependencies: "@types/mime": "npm:^1" "@types/node": "npm:*" - checksum: 59ad262fd74c4fad615c6b32019d07c796d3d8f3c3cd2d639e6cb41c4ce7872ee724eff3538ad365970b4861179029205f6ca65d003527eaae9064e4821fad49 + checksum: 28320a2aa1eb704f7d96a65272a07c0bf3ae7ed5509c2c96ea5e33238980f71deeed51d3631927a77d5250e4091b3e66bce53b42d770873282c6a20bb8b0280d languageName: node linkType: hard @@ -4483,31 +4479,31 @@ __metadata: linkType: hard "@types/serve-index@npm:^1.9.1": - version: 1.9.3 - resolution: "@types/serve-index@npm:1.9.3" + version: 1.9.4 + resolution: "@types/serve-index@npm:1.9.4" dependencies: "@types/express": "npm:*" - checksum: 792b8629e5bec1513398727fbeb17c87ebbcb0462a7193ad92bca3e746e4f581c7c6b077365cb40e73b25179d6b335ad5b6224bd0374534eea55df89b101d5ef + checksum: 72727c88d54da5b13275ebfb75dcdc4aa12417bbe9da1939e017c4c5f0c906fae843aa4e0fbfe360e7ee9df2f3d388c21abfc488f77ce58693fb57809f8ded92 languageName: node linkType: hard "@types/serve-static@npm:*, @types/serve-static@npm:^1.13.10": - version: 1.15.4 - resolution: "@types/serve-static@npm:1.15.4" + version: 1.15.5 + resolution: "@types/serve-static@npm:1.15.5" dependencies: "@types/http-errors": "npm:*" "@types/mime": "npm:*" "@types/node": "npm:*" - checksum: edac44abead06a4aa9d48c37f1814665ffa9162ed29e3c22bbc75bd15f7c6d639500a34886f0785b725893fcc78a388e05b2fad21ea61b07d393af1107d77c5b + checksum: 49aa21c367fffe4588fc8c57ea48af0ea7cbadde7418bc53cde85d8bd57fd2a09a293970d9ea86e79f17a87f8adeb3e20da76aab38e1c4d1567931fa15c8af38 languageName: node linkType: hard "@types/sockjs@npm:^0.3.33": - version: 0.3.35 - resolution: "@types/sockjs@npm:0.3.35" + version: 0.3.36 + resolution: "@types/sockjs@npm:0.3.36" dependencies: "@types/node": "npm:*" - checksum: 829b6bbe155f4320a57429bcc3b87aedfec7ee0bd055d46ab021bed676fba0210600ad22d516fe3ae5b3989c2a2c892f2b95d47eb5e41e71ca48954b7abab79d + checksum: b4b5381122465d80ea8b158537c00bc82317222d3fb31fd7229ff25b31fa89134abfbab969118da55622236bf3d8fee75759f3959908b5688991f492008f29bc languageName: node linkType: hard @@ -4529,9 +4525,9 @@ __metadata: linkType: hard "@types/trusted-types@npm:^2.0.2": - version: 2.0.5 - resolution: "@types/trusted-types@npm:2.0.5" - checksum: e138a70a702e31b49ac73cc33852d892367224be6e096c445194d76327cb46f54f971ae311e34371f649a2d5ac9204afee345bb22f32cfc515eb21c3f12f66b7 + version: 2.0.7 + resolution: "@types/trusted-types@npm:2.0.7" + checksum: 8e4202766a65877efcf5d5a41b7dd458480b36195e580a3b1085ad21e948bc417d55d6f8af1fd2a7ad008015d4117d5fdfe432731157da3c68678487174e4ba3 languageName: node linkType: hard @@ -4559,23 +4555,23 @@ __metadata: linkType: hard "@types/ws@npm:^8.5.5": - version: 8.5.8 - resolution: "@types/ws@npm:8.5.8" + version: 8.5.10 + resolution: "@types/ws@npm:8.5.10" dependencies: "@types/node": "npm:*" - checksum: 5f33608d1afa38236f0c0c6e153555d94d8ff74f54a21d1c062f4a93f0cb8c1aaecd6f11f0dd9a41774f79b1c56235aaccaad290e57f69350ccc9bd47c63b040 + checksum: 9b414dc5e0b6c6f1ea4b1635b3568c58707357f68076df9e7cd33194747b7d1716d5189c0dbdd68c8d2521b148e88184cf881bac7429eb0e5c989b001539ed31 languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/eslint-plugin@npm:6.13.2" +"@typescript-eslint/eslint-plugin@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.16.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.13.2" - "@typescript-eslint/type-utils": "npm:6.13.2" - "@typescript-eslint/utils": "npm:6.13.2" - "@typescript-eslint/visitor-keys": "npm:6.13.2" + "@typescript-eslint/scope-manager": "npm:6.16.0" + "@typescript-eslint/type-utils": "npm:6.16.0" + "@typescript-eslint/utils": "npm:6.16.0" + "@typescript-eslint/visitor-keys": "npm:6.16.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -4588,44 +4584,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: e6665fc5de0ae2b7ada9150d3d119157521a04208b8da385a4c39538b9471871efe6eef272dbcee4c76f599e09453b6f7317f3b3b80d89291f6b2ace4125c51b + checksum: 4bedce948ac3c20492a59813ee5d4f1f2306310857864dfaac2736f6c38e18785002c36844fd64c9fbdf3059fc390b29412be105fd7a118177f1eeeb1eb533f7 languageName: node linkType: hard -"@typescript-eslint/parser@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/parser@npm:6.13.2" +"@typescript-eslint/parser@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/parser@npm:6.16.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.13.2" - "@typescript-eslint/types": "npm:6.13.2" - "@typescript-eslint/typescript-estree": "npm:6.13.2" - "@typescript-eslint/visitor-keys": "npm:6.13.2" + "@typescript-eslint/scope-manager": "npm:6.16.0" + "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/typescript-estree": "npm:6.16.0" + "@typescript-eslint/visitor-keys": "npm:6.16.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: a2b32d2ad1aa12ce31790e80e059fd5b0699265541f3799b58f2e5c8b40f2e21ac7010519802bc406f4b74c14a1f52081570fa6119b949f68392d0968628b3b8 + checksum: 3d941ce345dc2ce29957e2110957662873d514b094b8939923c3281d858c11cd1f9058db862644afe14f68d087770f39a0a1f9e523a2013ed5d2fdf3421b34d0 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/scope-manager@npm:6.13.2" +"@typescript-eslint/scope-manager@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/scope-manager@npm:6.16.0" dependencies: - "@typescript-eslint/types": "npm:6.13.2" - "@typescript-eslint/visitor-keys": "npm:6.13.2" - checksum: a6505cc73e90dfed3b9b03816213610f05be58548f468ce24c05ce49a3c6d029ef02233db51cff3b780aa8d040a0c7b3268ea28244c704932c9ee6ef82088509 + "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/visitor-keys": "npm:6.16.0" + checksum: 3360aae4b85f5c31d20ad48d771cc09a6f8f6b1811b00d94f06e55b5a09c610ac75631b1c4edecb3bec682d41351b87e7d14d42bee84aa032064d0e13463035b languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/type-utils@npm:6.13.2" +"@typescript-eslint/type-utils@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/type-utils@npm:6.16.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.13.2" - "@typescript-eslint/utils": "npm:6.13.2" + "@typescript-eslint/typescript-estree": "npm:6.16.0" + "@typescript-eslint/utils": "npm:6.16.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -4633,59 +4629,60 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: c8de5ab94295980a378e4f22dd51dedb3838761969ad1a355386a801c9bc332837651747cdc2edf7f399c88d0bbd787d2233d09e14e4e2849fb01a57bd0cab00 + checksum: 5964b87a87252bed278a248eb568902babd7c34defd3af8c3df371926d96aec716f33f1dc14bde170e93f73ed1b0af6e591e647853d0f33f378e2c7b3b73fc5b languageName: node linkType: hard -"@typescript-eslint/types@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/types@npm:6.13.2" - checksum: 3ed2622468b2c61bff0828a3675357b498360bada85740dd72e4ec3c80ee112bce8808d7688aa0104b9d0a655a30e2deb0fee69468474c7e046fc9285f549fe6 +"@typescript-eslint/types@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/types@npm:6.16.0" + checksum: 236ca318c2440c95068e5d4d147e2bfed62447775e18695e21c8ca04a341a74d01c37ed2b417629b7bf2fb91ad4fd5e2a6570215d16fc24dd1507ce6973b4e22 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/typescript-estree@npm:6.13.2" +"@typescript-eslint/typescript-estree@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.16.0" dependencies: - "@typescript-eslint/types": "npm:6.13.2" - "@typescript-eslint/visitor-keys": "npm:6.13.2" + "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/visitor-keys": "npm:6.16.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" + minimatch: "npm:9.0.3" semver: "npm:^7.5.4" ts-api-utils: "npm:^1.0.1" peerDependenciesMeta: typescript: optional: true - checksum: 8fa1344228858fa8171a9660e11eb0d5ed88de2ada343bce4a02a957724ccbeb9b67da1083eada29247f444aeba6908a4145d1758b528d320928abbb4e48dca7 + checksum: 8e1ef03ecabaf3791b11240a51217836dbb74850e458258db77ac5eab5508cd9c63fb671924993d1e7654718c0c857c3550d51ecba0845fe489d143bb858e1b1 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/utils@npm:6.13.2" +"@typescript-eslint/utils@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/utils@npm:6.16.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.13.2" - "@typescript-eslint/types": "npm:6.13.2" - "@typescript-eslint/typescript-estree": "npm:6.13.2" + "@typescript-eslint/scope-manager": "npm:6.16.0" + "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/typescript-estree": "npm:6.16.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 934282b612e5f78423bc375122258c5aec65fcdf9c25fd0521e3984686d1e5b950500f093c5f1c21a267be164bc7025d8f629dcfaa60573ad98c6e3861092076 + checksum: 84dd02f7c8e47fae699cc222da5cbea08b28c6e1cc7827860430bc86c2a17ee3f86e198a4356902b95930f85785aa662266ea9c476f69bf80c6a5f648e55f9f4 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/visitor-keys@npm:6.13.2" +"@typescript-eslint/visitor-keys@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.16.0" dependencies: - "@typescript-eslint/types": "npm:6.13.2" + "@typescript-eslint/types": "npm:6.16.0" eslint-visitor-keys: "npm:^3.4.1" - checksum: eb6f3a3fa4dae6003533eac41bd2a8181a0353f352640e92b619e353b4bd5a5cd4c076018cbdf4b1ba45b826be0c1d15293d87e956fc9a8aa2fb8d8aa04a7c98 + checksum: 19e559f14ea0092585a374b8c5f1aca9b6b271fc23909d9857de9cf71a1e1d3abc0afd237e9c02d7a5fbdfe8e3be7853cf9fedf40a6f16bac3495cb7f4e67982 languageName: node linkType: hard @@ -4696,126 +4693,127 @@ __metadata: languageName: node linkType: hard -"@vaadin/a11y-base@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/a11y-base@npm:24.2.5" +"@vaadin/a11y-base@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/a11y-base@npm:24.3.2" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.2.5" - lit: "npm:^2.0.0" - checksum: 309cc0f0c19b6bb321ec0efb8f44cb791939a051b13db6edd55cd029e170dda60cf350893960bdee371e0fdf6cb6c33dfa23a70c938a34ea2370e11c73a04f8d + "@vaadin/component-base": "npm:~24.3.2" + lit: "npm:^3.0.0" + checksum: 8ddff8610cdf74816bcd9f24e6d7985c869cc5691de0a5928bf794d36e7e655a9d8e51c88c4918f5784dc35331a09bccf1de3233ed263a0854fa4bafc171a21e languageName: node linkType: hard -"@vaadin/combo-box@npm:24.2.5": - version: 24.2.5 - resolution: "@vaadin/combo-box@npm:24.2.5" +"@vaadin/combo-box@npm:24.3.2": + version: 24.3.2 + resolution: "@vaadin/combo-box@npm:24.3.2" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/a11y-base": "npm:~24.2.5" - "@vaadin/component-base": "npm:~24.2.5" - "@vaadin/field-base": "npm:~24.2.5" - "@vaadin/input-container": "npm:~24.2.5" - "@vaadin/item": "npm:~24.2.5" - "@vaadin/lit-renderer": "npm:~24.2.5" - "@vaadin/overlay": "npm:~24.2.5" - "@vaadin/vaadin-lumo-styles": "npm:~24.2.5" - "@vaadin/vaadin-material-styles": "npm:~24.2.5" - "@vaadin/vaadin-themable-mixin": "npm:~24.2.5" - checksum: 3391b4bb99f9216fbcba2669c2fe437f4b199afdbd77d89222ca6294af5e7adc9fba5b4a96f30e65914f6a5744eae57286c45145c585c61aa44698d0e8b88dd6 + "@vaadin/a11y-base": "npm:~24.3.2" + "@vaadin/component-base": "npm:~24.3.2" + "@vaadin/field-base": "npm:~24.3.2" + "@vaadin/input-container": "npm:~24.3.2" + "@vaadin/item": "npm:~24.3.2" + "@vaadin/lit-renderer": "npm:~24.3.2" + "@vaadin/overlay": "npm:~24.3.2" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.2" + "@vaadin/vaadin-material-styles": "npm:~24.3.2" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.2" + checksum: 1b1a5b80977a782e74717030dc5007bb29668534b6a25dca592f2cc8d666479682c622501847bdf87e764fb688f5e23b0070e6089114e10aebdc7c1915c62f7b languageName: node linkType: hard -"@vaadin/component-base@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/component-base@npm:24.2.5" +"@vaadin/component-base@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/component-base@npm:24.3.2" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" "@vaadin/vaadin-development-mode-detector": "npm:^2.0.0" "@vaadin/vaadin-usage-statistics": "npm:^2.1.0" - lit: "npm:^2.0.0" - checksum: 55452811689596e0bf4da17f06dbc531458dca6ce6456d892ae5c28d8c430ac5f2a894ee220e78346ea90d78980b1e1c4a4acb1ec831ca21fa07946c371e3094 + lit: "npm:^3.0.0" + checksum: b5fc7a7f8cb9ad26a1a4f4b554ac78f29c34ecaab74fd48516656d70347c7a3c9ae00a958b9a9a31f9861cf29bc640166567d0a8102b9dcf75e6ea08e184a102 languageName: node linkType: hard -"@vaadin/field-base@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/field-base@npm:24.2.5" +"@vaadin/field-base@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/field-base@npm:24.3.2" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/a11y-base": "npm:~24.2.5" - "@vaadin/component-base": "npm:~24.2.5" - lit: "npm:^2.0.0" - checksum: 4a8396fa68a78dce9ca2c4442162ce30595447b1c4647da21fc115396755d1c253fd91a95337319474687be681dea574cf9f60fb662558542f3ffc588272fb0b + "@vaadin/a11y-base": "npm:~24.3.2" + "@vaadin/component-base": "npm:~24.3.2" + lit: "npm:^3.0.0" + checksum: 1be21ff4e6eabaa203ae1ab8f2f55033d1830359782bac7e001721c22d5e7c404436644c3d7e2bc9e5af1f743949f37f874c99495f3d3e2df47a51aed2b5f046 languageName: node linkType: hard -"@vaadin/icon@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/icon@npm:24.2.5" +"@vaadin/icon@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/icon@npm:24.3.2" dependencies: "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.2.5" - "@vaadin/vaadin-lumo-styles": "npm:~24.2.5" - "@vaadin/vaadin-themable-mixin": "npm:~24.2.5" - lit: "npm:^2.0.0" - checksum: c7ae5c9367d60318d3085389bb68b0cd7891409031e8df65231abec0295a0e1ac9f32c110c12393ad7688bfb5baec8d32feb2e8436b8646723cb71ced341d04b + "@vaadin/component-base": "npm:~24.3.2" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.2" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.2" + lit: "npm:^3.0.0" + checksum: 2a5f9eeed5aac093f38878f749c774ad20ecf2ca4105c606f6b1938a0f3e4181b79a8ac8c51f7b3d1990552cd6bcdc04984c1846b41f7ef4143fc96b2b276445 languageName: node linkType: hard -"@vaadin/input-container@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/input-container@npm:24.2.5" +"@vaadin/input-container@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/input-container@npm:24.3.2" dependencies: "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.2.5" - "@vaadin/vaadin-lumo-styles": "npm:~24.2.5" - "@vaadin/vaadin-material-styles": "npm:~24.2.5" - "@vaadin/vaadin-themable-mixin": "npm:~24.2.5" - checksum: 8a9b7114b237aeed2e4690cf57acf527d817e42c05d4a22bc183d74d8495907265bc02f8bad7e9273d5e4728c109f3ad4fb1d6bd049bef3b5520d9ecf5791f65 + "@vaadin/component-base": "npm:~24.3.2" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.2" + "@vaadin/vaadin-material-styles": "npm:~24.3.2" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.2" + lit: "npm:^3.0.0" + checksum: b43926c876259e189d1910696f539fbb90b17478fca101bd3216a471afaf16d765c8d5952bddafe8282fcfe9babe7dfc819f84ca2adb108eba4616a32858ffde languageName: node linkType: hard -"@vaadin/item@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/item@npm:24.2.5" +"@vaadin/item@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/item@npm:24.3.2" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/a11y-base": "npm:~24.2.5" - "@vaadin/component-base": "npm:~24.2.5" - "@vaadin/vaadin-lumo-styles": "npm:~24.2.5" - "@vaadin/vaadin-material-styles": "npm:~24.2.5" - "@vaadin/vaadin-themable-mixin": "npm:~24.2.5" - checksum: 1b58b5b8b7c2a50d9a6284cb22d42a8862f70a032daaff117e2a1daa6b7cce17bbab4b697f48d47b946d6f310076c5dc7ffb550c19d5b264f3250f1ebbd067f3 + "@vaadin/a11y-base": "npm:~24.3.2" + "@vaadin/component-base": "npm:~24.3.2" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.2" + "@vaadin/vaadin-material-styles": "npm:~24.3.2" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.2" + checksum: b56cbe033a6fbf591edd26780658d5cc89338d79ced469812be0f6f0f462a571bc1550f835681d6a6981119dd958810312abe31c6641317e8be5dbcc3cfd1f01 languageName: node linkType: hard -"@vaadin/lit-renderer@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/lit-renderer@npm:24.2.5" +"@vaadin/lit-renderer@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/lit-renderer@npm:24.3.2" dependencies: - lit: "npm:^2.0.0" - checksum: d8645421550946c01daf5949364fdc54d9fba09ce59f2a2d4504f68c92dac1c2e49685773beb44332d5303e232acd5e91adcf9bd74e5bbbe40449368915a62fa + lit: "npm:^3.0.0" + checksum: 3736065a55f69c13f76d202c7a9a4f690f2c9e84a127e9558ff522b113698c5a6ea8bf8f4aefbf3d532bd5eb2798f427ab0e35459f270d3c458861fb1861c194 languageName: node linkType: hard -"@vaadin/overlay@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/overlay@npm:24.2.5" +"@vaadin/overlay@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/overlay@npm:24.3.2" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/a11y-base": "npm:~24.2.5" - "@vaadin/component-base": "npm:~24.2.5" - "@vaadin/vaadin-lumo-styles": "npm:~24.2.5" - "@vaadin/vaadin-material-styles": "npm:~24.2.5" - "@vaadin/vaadin-themable-mixin": "npm:~24.2.5" - checksum: c9d289c151caa6e5e4480d2073613ce16393dae46cf8d5b0313ffce66b51fe4c541d756c708b417cb37dcc5c86e67bdc782a359ba1aba943e652565b095428a3 + "@vaadin/a11y-base": "npm:~24.3.2" + "@vaadin/component-base": "npm:~24.3.2" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.2" + "@vaadin/vaadin-material-styles": "npm:~24.3.2" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.2" + checksum: e04aff31f8cf2475dfed3d7f29ab1c7e08d914c6c74fbd7abd92bdd89a2c9ace810436cb2b31840fa6e6a152f1b39596f4c6625611c9174d1fdff7a8c20acafa languageName: node linkType: hard @@ -4826,36 +4824,36 @@ __metadata: languageName: node linkType: hard -"@vaadin/vaadin-lumo-styles@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/vaadin-lumo-styles@npm:24.2.5" +"@vaadin/vaadin-lumo-styles@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/vaadin-lumo-styles@npm:24.3.2" dependencies: "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.2.5" - "@vaadin/icon": "npm:~24.2.5" - "@vaadin/vaadin-themable-mixin": "npm:~24.2.5" - checksum: 6dd33aee2420ecb22a0916ea5f4600261151166100d21bc5d76ba3135a93fb6f51cb34296b683f7afabd0605f7f937ddfecc16ea2de4d29b160aa25434ef267d + "@vaadin/component-base": "npm:~24.3.2" + "@vaadin/icon": "npm:~24.3.2" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.2" + checksum: e37abd1d54d5045815f91efe8ef845fd2e5417bf7a8f1aaff8d98adf34c0cf0ec25990d0cb62f869d04777b9e7f2b64437e8d83cec05121e482d60b4bba61ff1 languageName: node linkType: hard -"@vaadin/vaadin-material-styles@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/vaadin-material-styles@npm:24.2.5" +"@vaadin/vaadin-material-styles@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/vaadin-material-styles@npm:24.3.2" dependencies: "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.2.5" - "@vaadin/vaadin-themable-mixin": "npm:~24.2.5" - checksum: 7b17376f9952ea1d7c390d0db16162faa62b9c8726db70b69daf66bb2d5494df2c320170d54bcc936f128b33256d81a43bf227b3889063dbb12a91563a215baa + "@vaadin/component-base": "npm:~24.3.2" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.2" + checksum: 8de34251d755d0120d9b79be6c0fa481c928c3ad6044caae3b4f9217c404cadb032fa8c8ab4fcd0150f89e0f7a5ade4660964056e4470923353c2f234ca0673b languageName: node linkType: hard -"@vaadin/vaadin-themable-mixin@npm:24.2.5, @vaadin/vaadin-themable-mixin@npm:~24.2.5": - version: 24.2.5 - resolution: "@vaadin/vaadin-themable-mixin@npm:24.2.5" +"@vaadin/vaadin-themable-mixin@npm:24.3.2, @vaadin/vaadin-themable-mixin@npm:~24.3.2": + version: 24.3.2 + resolution: "@vaadin/vaadin-themable-mixin@npm:24.3.2" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" - lit: "npm:^2.0.0" - checksum: 07ae5c2127b708cb0aabdfc2d3a4cf300118954194e9cc711551130e505e0a98276d9bb886fbe3c7fd0d8f98b46d214353cce3d990fd42c80b311ce0ef965dc3 + lit: "npm:^3.0.0" + checksum: cb85790319b4f76eabf6dd9ff3455781773a3bfcd534fd2ab040c5a792e485bbbb60aa36f8f6c837c1d42ece069ea54e2cd67397053d0f64eacea009ddc5394b languageName: node linkType: hard @@ -4985,14 +4983,18 @@ __metadata: languageName: node linkType: hard -"@vue/compiler-sfc@npm:2.7.15": - version: 2.7.15 - resolution: "@vue/compiler-sfc@npm:2.7.15" +"@vue/compiler-sfc@npm:2.7.16": + version: 2.7.16 + resolution: "@vue/compiler-sfc@npm:2.7.16" dependencies: - "@babel/parser": "npm:^7.18.4" + "@babel/parser": "npm:^7.23.5" postcss: "npm:^8.4.14" + prettier: "npm:^1.18.2 || ^2.0.0" source-map: "npm:^0.6.1" - checksum: 6c01a2a0a41f418f6b5d33a3551d4a6f5f70630bb316317ec8067307508d07b703bfbb660bf2a11140cde8b06b25d676ffff683d8cee3faffc94b87c97f47529 + dependenciesMeta: + prettier: + optional: true + checksum: fd1128fe1b0ebb1e680aa34909d73716ee5e6f4d3460c1c292b47626976d7af25982cdcbfba7cdbd74e1bee865c39813b82dc71c483731c58184d99ef4043d4d languageName: node linkType: hard @@ -5315,10 +5317,10 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^1.0.0": - version: 1.1.1 - resolution: "abbrev@npm:1.1.1" - checksum: 2d882941183c66aa665118bafdab82b7a177e9add5eb2776c33e960a4f3c89cff88a1b38aba13a456de01d0dd9d66a8bea7c903268b21ea91dd1097e1e2e8243 +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: ca0a54e35bea4ece0ecb68a47b312e1a9a6f772408d5bcb9051230aaa94b0460671c5b5c9cb3240eb5b7bc94c52476550eb221f65a0bbd0145bdc9f3113a6707 languageName: node linkType: hard @@ -5351,29 +5353,20 @@ __metadata: linkType: hard "acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.10.0 - resolution: "acorn@npm:8.10.0" + version: 8.11.2 + resolution: "acorn@npm:8.11.2" bin: acorn: bin/acorn - checksum: 522310c20fdc3c271caed3caf0f06c51d61cb42267279566edd1d58e83dbc12eebdafaab666a0f0be1b7ad04af9c6bc2a6f478690a9e6391c3c8b165ada917dd + checksum: ff559b891382ad4cd34cc3c493511d0a7075a51f5f9f02a03440e92be3705679367238338566c5fbd3521ecadd565d29301bc8e16cb48379206bffbff3d72500 languageName: node linkType: hard -"agent-base@npm:6, agent-base@npm:^6.0.2": - version: 6.0.2 - resolution: "agent-base@npm:6.0.2" - dependencies: - debug: "npm:4" - checksum: 21fb903e0917e5cb16591b4d0ef6a028a54b83ac30cd1fca58dece3d4e0990512a8723f9f83130d88a41e2af8b1f7be1386fda3ea2d181bb1a62155e75e95e23 - languageName: node - linkType: hard - -"agentkeepalive@npm:^4.2.1": - version: 4.5.0 - resolution: "agentkeepalive@npm:4.5.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": + version: 7.1.0 + resolution: "agent-base@npm:7.1.0" dependencies: - humanize-ms: "npm:^1.2.1" - checksum: dd210ba2a2e2482028f027b1156789744aadbfd773a6c9dd8e4e8001930d5af82382abe19a69240307b1d8003222ce6b0542935038313434b900e351914fc15f + debug: "npm:^4.3.4" + checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f languageName: node linkType: hard @@ -5480,6 +5473,15 @@ __metadata: languageName: node linkType: hard +"ansi-escapes@npm:^4.3.2": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: "npm:^0.21.3" + checksum: 8661034456193ffeda0c15c8c564a9636b0c04094b7f78bd01517929c17c504090a60f7a75f949f5af91289c264d3e1001d91492c1bd58efc8e100500ce04de2 + languageName: node + linkType: hard + "ansi-escapes@npm:^6.2.0": version: 6.2.0 resolution: "ansi-escapes@npm:6.2.0" @@ -5624,13 +5626,6 @@ __metadata: languageName: node linkType: hard -"aproba@npm:^1.0.3 || ^2.0.0": - version: 2.0.0 - resolution: "aproba@npm:2.0.0" - checksum: c2b9a631298e8d6f3797547e866db642f68493808f5b37cd61da778d5f6ada890d16f668285f7d60bd4fc3b03889bd590ffe62cf81b700e9bb353431238a0a7b - languageName: node - linkType: hard - "archy@npm:^1.0.0": version: 1.0.0 resolution: "archy@npm:1.0.0" @@ -5638,16 +5633,6 @@ __metadata: languageName: node linkType: hard -"are-we-there-yet@npm:^3.0.0": - version: 3.0.1 - resolution: "are-we-there-yet@npm:3.0.1" - dependencies: - delegates: "npm:^1.0.0" - readable-stream: "npm:^3.6.0" - checksum: 390731720e1bf9ed5d0efc635ea7df8cbc4c90308b0645a932f06e8495a0bf1ecc7987d3b97e805f62a17d6c4b634074b25200aa4d149be2a7b17250b9744bc4 - languageName: node - linkType: hard - "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -5907,10 +5892,10 @@ __metadata: languageName: node linkType: hard -"assertion-error@npm:^1.1.0": - version: 1.1.0 - resolution: "assertion-error@npm:1.1.0" - checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66 languageName: node linkType: hard @@ -5959,9 +5944,9 @@ __metadata: linkType: hard "async@npm:^3.2.3": - version: 3.2.4 - resolution: "async@npm:3.2.4" - checksum: bebb5dc2258c45b83fa1d3be179ae0eb468e1646a62d443c8d60a45e84041b28fccebe1e2d1f234bfc3dcad44e73dcdbf4ba63d98327c9f6556e3dbd47c2ae8b + version: 3.2.5 + resolution: "async@npm:3.2.5" + checksum: 323c3615c3f0ab1ac25a6f953296bc0ac3213d5e0f1c0debdb12964e55963af288d570293c11e44f7967af58c06d2a88d0ea588c86ec0fbf62fa98037f604a0f languageName: node linkType: hard @@ -5989,9 +5974,9 @@ __metadata: linkType: hard "axe-core@npm:^4.3.3": - version: 4.8.2 - resolution: "axe-core@npm:4.8.2" - checksum: 3e8dbf264a57767713daa77fe04bbabd71a956b08b99c2eb0ec61b75852f21190653f557d2da623dea9e0a7555460deaac71d9f6a9125c0b52576f8581bfbe52 + version: 4.8.3 + resolution: "axe-core@npm:4.8.3" + checksum: 86d72bcdff867b8a4f223b910f90d1c963ddab1db3bdc5290e111453bae4e319ed14d667cd7a6ac97185ffa141261c88ac9a586aa007d007ffc19ed9ae81ee1d languageName: node linkType: hard @@ -6015,39 +6000,39 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs2@npm:^0.4.6": - version: 0.4.6 - resolution: "babel-plugin-polyfill-corejs2@npm:0.4.6" +"babel-plugin-polyfill-corejs2@npm:^0.4.7": + version: 0.4.7 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.7" dependencies: "@babel/compat-data": "npm:^7.22.6" - "@babel/helper-define-polyfill-provider": "npm:^0.4.3" + "@babel/helper-define-polyfill-provider": "npm:^0.4.4" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 736b1bb8e570be029f941a374c769972af870c96b5c324a5387c6b6994aabdad045ce560c530038c8626f02ec70f711ad7445f2572c32ba81fa0e13402cc23f8 + checksum: 3b61cdb275592f61b29d582ee8c738a13d9897c5dd201cddb0610b381f3ae139ebc988ac96f72978fc143c3d50c15d46618df865822e282c8e76c236e7378b63 languageName: node linkType: hard -"babel-plugin-polyfill-corejs3@npm:^0.8.5": - version: 0.8.5 - resolution: "babel-plugin-polyfill-corejs3@npm:0.8.5" +"babel-plugin-polyfill-corejs3@npm:^0.8.7": + version: 0.8.7 + resolution: "babel-plugin-polyfill-corejs3@npm:0.8.7" dependencies: - "@babel/helper-define-polyfill-provider": "npm:^0.4.3" - core-js-compat: "npm:^3.32.2" + "@babel/helper-define-polyfill-provider": "npm:^0.4.4" + core-js-compat: "npm:^3.33.1" peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 5c2ac3615bd064f294a0b36bf6a1939995ec510173602e317fb18b1c015d31f46e2dd885faa3376e4da22785a515e5ba37e069f0008e5eea830d2fe3b0e66a27 + checksum: defbc6de3d309c9639dd31223b5011707fcc0384037ac5959a1aefe16eb314562e1c1e5cfbce0af14a220d639ef92dfe5baf66664e9e6054656aca2841677622 languageName: node linkType: hard -"babel-plugin-polyfill-regenerator@npm:^0.5.3": - version: 0.5.3 - resolution: "babel-plugin-polyfill-regenerator@npm:0.5.3" +"babel-plugin-polyfill-regenerator@npm:^0.5.4": + version: 0.5.4 + resolution: "babel-plugin-polyfill-regenerator@npm:0.5.4" dependencies: - "@babel/helper-define-polyfill-provider": "npm:^0.4.3" + "@babel/helper-define-polyfill-provider": "npm:^0.4.4" peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 2bb546582cda1870d19e646a7183baeb2cccd56e0ef3e4eaeabd28e120daf17cb87399194a9ccdcf32506bcaa68d23e73440fc8ab990a7a0f8c5a77c12d5d4bc + checksum: 461b735c6c0eca3c7b4434d14bfa98c2ab80f00e2bdc1c69eb46d1d300092a9786d76bbd3ee55e26d2d1a2380c14592d8d638e271dfd2a2b78a9eacffa3645d1 languageName: node linkType: hard @@ -6122,13 +6107,6 @@ __metadata: languageName: node linkType: hard -"big-integer@npm:^1.6.44": - version: 1.6.51 - resolution: "big-integer@npm:1.6.51" - checksum: c7a12640901906d6f6b6bdb42a4eaba9578397b6d9a0dd090cf001ec813ff2bfcd441e364068ea0416db6175d2615f8ed19cff7d1a795115bf7c92d44993f991 - languageName: node - linkType: hard - "binary-extensions@npm:^1.0.0": version: 1.13.1 resolution: "binary-extensions@npm:1.13.1" @@ -6215,15 +6193,6 @@ __metadata: languageName: node linkType: hard -"bplist-parser@npm:^0.2.0": - version: 0.2.0 - resolution: "bplist-parser@npm:0.2.0" - dependencies: - big-integer: "npm:^1.6.44" - checksum: 15d31c1b0c7e0fb384e96349453879a33609d92d91b55a9ccee04b4be4b0645f1c823253d73326a1a23104521fbc45c2dd97fb05adf61863841b68cbb2ca7a3d - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -6277,17 +6246,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.14.5, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1": - version: 4.22.1 - resolution: "browserslist@npm:4.22.1" +"browserslist@npm:^4.14.5, browserslist@npm:^4.22.2": + version: 4.22.2 + resolution: "browserslist@npm:4.22.2" dependencies: - caniuse-lite: "npm:^1.0.30001541" - electron-to-chromium: "npm:^1.4.535" - node-releases: "npm:^2.0.13" + caniuse-lite: "npm:^1.0.30001565" + electron-to-chromium: "npm:^1.4.601" + node-releases: "npm:^2.0.14" update-browserslist-db: "npm:^1.0.13" bin: browserslist: cli.js - checksum: 4a515168e0589c7b1ccbf13a93116ce0418cc5e65d228ec036022cf0e08773fdfb732e2abbf1e1188b96d19ecd4dd707504e75b6d393cba2782fc7d6a7fdefe8 + checksum: e3590793db7f66ad3a50817e7b7f195ce61e029bd7187200244db664bfbe0ac832f784e4f6b9c958aef8ea4abe001ae7880b7522682df521f4bc0a5b67660b5e languageName: node linkType: hard @@ -6336,12 +6305,12 @@ __metadata: languageName: node linkType: hard -"bundle-name@npm:^3.0.0": - version: 3.0.0 - resolution: "bundle-name@npm:3.0.0" +"bundle-name@npm:^4.1.0": + version: 4.1.0 + resolution: "bundle-name@npm:4.1.0" dependencies: - run-applescript: "npm:^5.0.0" - checksum: edf2b1fbe6096ed32e7566947ace2ea937ee427391744d7510a2880c4b9a5b3543d3f6c551236a29e5c87d3195f8e2912516290e638c15bcbede7b37cc375615 + run-applescript: "npm:^7.0.0" + checksum: 1d966c8d2dbf4d9d394e53b724ac756c2414c45c01340b37743621f59cc565a435024b394ddcb62b9b335d1c9a31f4640eb648c3fec7f97ee74dc0694c9beb6c languageName: node linkType: hard @@ -6359,23 +6328,23 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^17.0.0": - version: 17.1.4 - resolution: "cacache@npm:17.1.4" +"cacache@npm:^18.0.0": + version: 18.0.1 + resolution: "cacache@npm:18.0.1" dependencies: "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" glob: "npm:^10.2.2" - lru-cache: "npm:^7.7.1" + lru-cache: "npm:^10.0.1" minipass: "npm:^7.0.3" - minipass-collect: "npm:^1.0.2" + minipass-collect: "npm:^2.0.1" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" p-map: "npm:^4.0.0" ssri: "npm:^10.0.0" tar: "npm:^6.1.11" unique-filename: "npm:^3.0.0" - checksum: 6e26c788bc6a18ff42f4d4f97db30d5c60a5dfac8e7c10a03b0307a92cf1b647570547cf3cd96463976c051eb9c7258629863f156e224c82018862c1a8ad0e70 + checksum: aecafd368fbfb2fc0cda1f2f831fe5a1d8161d2121317c92ac089bcd985085e8a588e810b4471e69946f91c6d2661849400e963231563c519aa1e3dac2cf6187 languageName: node linkType: hard @@ -6455,25 +6424,23 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001541": - version: 1.0.30001551 - resolution: "caniuse-lite@npm:1.0.30001551" - checksum: 3ab880797f2a47ce5e2db38700283219faacbddb4382a730883657b2155240aedda1931aac456bc957f61a41c99e15b42f452e5f68e62272def026fd3bf474a7 +"caniuse-lite@npm:^1.0.30001565": + version: 1.0.30001571 + resolution: "caniuse-lite@npm:1.0.30001571" + checksum: 04f53b9a74776c9214476314613af95c62c43a9ddbc2ae555e176e896cc312110f9b74683f278fd07b8b83ab8ef6bee87b88f466df6ae560461a117fbd678b69 languageName: node linkType: hard -"chai@npm:4.3.10": - version: 4.3.10 - resolution: "chai@npm:4.3.10" +"chai@npm:5.0.0": + version: 5.0.0 + resolution: "chai@npm:5.0.0" dependencies: - assertion-error: "npm:^1.1.0" - check-error: "npm:^1.0.3" - deep-eql: "npm:^4.1.3" - get-func-name: "npm:^2.0.2" - loupe: "npm:^2.3.6" - pathval: "npm:^1.1.1" - type-detect: "npm:^4.0.8" - checksum: 9e545fd60f5efee4f06f7ad62f7b1b142932b08fbb3454db69defd511e7c58771ce51843764212da1e129b2c9d1b029fbf5f98da030fe67a95a0853e8679524f + assertion-error: "npm:^2.0.1" + check-error: "npm:^2.0.0" + deep-eql: "npm:^5.0.1" + loupe: "npm:^3.0.0" + pathval: "npm:^2.0.0" + checksum: c23d1bb3912cc36d12861d7e4010bb992aabf923a8d393bc71e776218c39f5f40778ab9f398ff962dd26857edee07ce732c9ad28a678feb1b76f99384d2e4a90 languageName: node linkType: hard @@ -6523,12 +6490,10 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^1.0.3": - version: 1.0.3 - resolution: "check-error@npm:1.0.3" - dependencies: - get-func-name: "npm:^2.0.2" - checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 +"check-error@npm:^2.0.0": + version: 2.0.0 + resolution: "check-error@npm:2.0.0" + checksum: 120f252c2e1ad82ef82a616662805345c6c361347bfd6203f8a28c53a158811dd0ea21278f29c8136cc9df12fc7f077d1a07124569d98fb396b3072d08f2f092 languageName: node linkType: hard @@ -6902,9 +6867,9 @@ __metadata: linkType: hard "component-emitter@npm:^1.2.1": - version: 1.3.0 - resolution: "component-emitter@npm:1.3.0" - checksum: dfc1ec2e7aa2486346c068f8d764e3eefe2e1ca0b24f57506cd93b2ae3d67829a7ebd7cc16e2bf51368fac2f45f78fcff231718e40b1975647e4a86be65e1d05 + version: 1.3.1 + resolution: "component-emitter@npm:1.3.1" + checksum: 94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d languageName: node linkType: hard @@ -6965,17 +6930,10 @@ __metadata: languageName: node linkType: hard -"consola@npm:^2.15.3": - version: 2.15.3 - resolution: "consola@npm:2.15.3" - checksum: ba5b3c6960b2eafb9d2ff2325444dd1d4eb53115df46eba823a4e7bfe6afbba0eb34747c0de82c7cd8a939db59b0cb5a8b8a54a94bb2e44feeddc26cefde3622 - languageName: node - linkType: hard - -"console-control-strings@npm:^1.1.0": - version: 1.1.0 - resolution: "console-control-strings@npm:1.1.0" - checksum: 27b5fa302bc8e9ae9e98c03c66d76ca289ad0c61ce2fe20ab288d288bee875d217512d2edb2363fc83165e88f1c405180cf3f5413a46e51b4fe1a004840c6cdb +"consola@npm:^3.2.3": + version: 3.2.3 + resolution: "consola@npm:3.2.3" + checksum: 02972dcb048c337357a3628438e5976b8e45bcec22fdcfbe9cd17622992953c4d695d5152f141464a02deac769b1d23028e8ac87f56483838df7a6bbf8e0f5a2 languageName: node linkType: hard @@ -7057,19 +7015,19 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.32.2": - version: 3.33.2 - resolution: "core-js-compat@npm:3.33.2" +"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": + version: 3.34.0 + resolution: "core-js-compat@npm:3.34.0" dependencies: - browserslist: "npm:^4.22.1" - checksum: 9806ac461080f4eef03a6adda77933c8f0bbea16b487ef686a827f9dd0f6ab24ff561415b697155b402d5992ff3bec44a2e01fbe8bd1e8f46acde61a1ecc5910 + browserslist: "npm:^4.22.2" + checksum: e29571cc524b4966e331b5876567f13c2b82ed48ac9b02784f3156b29ee1cd82fe3e60052d78b017c429eb61969fd238c22684bb29180908d335266179a29155 languageName: node linkType: hard -"core-js@npm:3.33.3": - version: 3.33.3 - resolution: "core-js@npm:3.33.3" - checksum: 77b4c9abaf22ae9c60966121b4b2a4a388cebd067d4cf6ae0f22762b2e8060f301eaacebb781e598ba5f43fe2e53fc88489b013faefdfcecadbf12e242263a50 +"core-js@npm:3.34.0": + version: 3.34.0 + resolution: "core-js@npm:3.34.0" + checksum: 054474ab6a0a08a2277ca2c1c953e5789c562bbe144f6a43786b0f4167b4a76c671833bd0a112e275e1d99d84fa157e64814ff23aa01532e08e3b46403d7f7f4 languageName: node linkType: hard @@ -7120,9 +7078,9 @@ __metadata: linkType: hard "csstype@npm:^3.1.0": - version: 3.1.2 - resolution: "csstype@npm:3.1.2" - checksum: 1f39c541e9acd9562996d88bc9fb62d1cb234786ef11ed275567d4b2bd82e1ceacde25debc8de3d3b4871ae02c2933fa02614004c97190711caebad6347debc2 + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: f593cce41ff5ade23f44e77521e3a1bcc2c64107041e1bf6c3c32adc5187d0d60983292fda326154d20b01079e24931aa5b08e4467cc488b60bb1e7f6d478ade languageName: node linkType: hard @@ -7170,7 +7128,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -7219,12 +7177,10 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^4.1.3": - version: 4.1.3 - resolution: "deep-eql@npm:4.1.3" - dependencies: - type-detect: "npm:^4.0.0" - checksum: 12ce93ae63de187e77b076d3d51bfc28b11f98910a22c18714cce112791195e86a94f97788180994614b14562a86c9763f67c69f785e4586f806b5df39bf9301 +"deep-eql@npm:^5.0.1": + version: 5.0.1 + resolution: "deep-eql@npm:5.0.1" + checksum: f8846820213462cdca23700873810c8bc01263dcc6a1e0f8694964b64f48a6dcb1f323ef7bb8678b15553f4b82420eda19092d4ae2e2709c56af7ea77bd8e6ab languageName: node linkType: hard @@ -7256,25 +7212,20 @@ __metadata: languageName: node linkType: hard -"default-browser-id@npm:^3.0.0": - version: 3.0.0 - resolution: "default-browser-id@npm:3.0.0" - dependencies: - bplist-parser: "npm:^0.2.0" - untildify: "npm:^4.0.0" - checksum: 279c7ad492542e5556336b6c254a4eaf31b2c63a5433265655ae6e47301197b6cfb15c595a6fdc6463b2ff8e1a1a1ed3cba56038a60e1527ba4ab1628c6b9941 +"default-browser-id@npm:^5.0.0": + version: 5.0.0 + resolution: "default-browser-id@npm:5.0.0" + checksum: 185bfaecec2c75fa423544af722a3469b20704c8d1942794a86e4364fe7d9e8e9f63241a5b769d61c8151993bc65833a5b959026fa1ccea343b3db0a33aa6deb languageName: node linkType: hard -"default-browser@npm:^4.0.0": - version: 4.0.0 - resolution: "default-browser@npm:4.0.0" +"default-browser@npm:^5.2.1": + version: 5.2.1 + resolution: "default-browser@npm:5.2.1" dependencies: - bundle-name: "npm:^3.0.0" - default-browser-id: "npm:^3.0.0" - execa: "npm:^7.1.1" - titleize: "npm:^3.0.0" - checksum: 40c5af984799042b140300be5639c9742599bda76dc9eba5ac9ad5943c83dd36cebc4471eafcfddf8e0ec817166d5ba89d56f08e66a126c7c7908a179cead1a7 + bundle-name: "npm:^4.1.0" + default-browser-id: "npm:^5.0.0" + checksum: afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840 languageName: node linkType: hard @@ -7337,7 +7288,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4, define-properties@npm:^1.2.0": +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -7598,17 +7549,17 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.535": - version: 1.4.563 - resolution: "electron-to-chromium@npm:1.4.563" - checksum: efcaa02a907179a9fe59ede11d346c06d02b814f889920c3db232a39b907bcb9a7600f5fa3d9b86f0be21873b0ee8014e09d840eb7c97245bfd2119728ff94ed +"electron-to-chromium@npm:^1.4.601": + version: 1.4.616 + resolution: "electron-to-chromium@npm:1.4.616" + checksum: 7793eda8ebfb66621300339fe830bc2b1658530b9e295a7aa37ef7fc1ca7defab4070cf407977f9112d784004a8e2efdcceb793d7e0a81096a7eb06c844db0ba languageName: node linkType: hard -"element-internals-polyfill@npm:1.3.9": - version: 1.3.9 - resolution: "element-internals-polyfill@npm:1.3.9" - checksum: bd9b63e68ca3462ed7623758398d5b8016736438b02be4527e456711bb91afe93af60028ddb928e12f0f1975c958c7b439d4b31a1ec41f4737969cd0202bcced +"element-internals-polyfill@npm:1.3.10": + version: 1.3.10 + resolution: "element-internals-polyfill@npm:1.3.10" + checksum: 156fed2c83b309714d7241d73d741798bfd4177e73cef0f105735b87a5fd0791d8e09d44eddfda5bc4b6ba411777d43994894e2f2ec352d4b144454cb7c2e07f languageName: node linkType: hard @@ -7701,11 +7652,11 @@ __metadata: linkType: hard "envinfo@npm:^7.7.3": - version: 7.10.0 - resolution: "envinfo@npm:7.10.0" + version: 7.11.0 + resolution: "envinfo@npm:7.11.0" bin: envinfo: dist/cli.js - checksum: d4db29c5a405081759c57c0e74ffa6adab09b7477ca105587252643394f13ab128ad4c8f755b15334b5f1901cef091acc76c71b695ce0f27853ebf147c882075 + checksum: 8cba09db181329b243fe02b3384ec275ebf93d5d3663c31e2064697aa96576c7de9b7e1c878a250f8eaec0db8026bace747709dcdc8d8a4ecd9a653cdbc08926 languageName: node linkType: hard @@ -7782,9 +7733,9 @@ __metadata: linkType: hard "es-module-lexer@npm:^1.0.0, es-module-lexer@npm:^1.2.1": - version: 1.3.1 - resolution: "es-module-lexer@npm:1.3.1" - checksum: c6aa137c5f5865fe1d12b4edbe027ff618d3836684cda9e52ae4dec48bfc2599b25db4f1265a12228d4663e21fd0126addfb79f761d513f1a6708c37989137e3 + version: 1.4.1 + resolution: "es-module-lexer@npm:1.4.1" + checksum: cf453613468c417af6e189b03d9521804033fdd5a229a36fedec28d37ea929fccf6822d42abff1126eb01ba1d2aa2845a48d5d1772c0724f8204464d9d3855f6 languageName: node linkType: hard @@ -7994,9 +7945,9 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-import@npm:2.29.0": - version: 2.29.0 - resolution: "eslint-plugin-import@npm:2.29.0" +"eslint-plugin-import@npm:2.29.1": + version: 2.29.1 + resolution: "eslint-plugin-import@npm:2.29.1" dependencies: array-includes: "npm:^3.1.7" array.prototype.findlastindex: "npm:^1.2.3" @@ -8014,10 +7965,10 @@ __metadata: object.groupby: "npm:^1.0.1" object.values: "npm:^1.1.7" semver: "npm:^6.3.1" - tsconfig-paths: "npm:^3.14.2" + tsconfig-paths: "npm:^3.15.0" peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: d6e8d016f38369892c85b866f762c03dee2b337d4f12031756e30d7490879261d1192a3c2f682fd7c4d2b923465f7a1e3d22cfdad5da1b1391c3bd39ea87af1a + checksum: 5865f05c38552145423c535326ec9a7113ab2305c7614c8b896ff905cfabc859c8805cac21e979c9f6f742afa333e6f62f812eabf891a7e8f5f0b853a32593c1 languageName: node linkType: hard @@ -8042,16 +7993,16 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-lit@npm:1.10.1, eslint-plugin-lit@npm:^1.10.1": - version: 1.10.1 - resolution: "eslint-plugin-lit@npm:1.10.1" +"eslint-plugin-lit@npm:1.11.0, eslint-plugin-lit@npm:^1.10.1": + version: 1.11.0 + resolution: "eslint-plugin-lit@npm:1.11.0" dependencies: parse5: "npm:^6.0.1" parse5-htmlparser2-tree-adapter: "npm:^6.0.1" requireindex: "npm:^1.2.0" peerDependencies: eslint: ">= 5" - checksum: e9aea27c2bdf4745b5afa76182d2f14e42e6170b5e5c9f6b1838b57b1e48e6996da7fd65b42237fe0c32d7c25471864396c03171ae9ed684bcfb3b8f71f92aa8 + checksum: c6819c4e2054ebb316f2205bb56590c28193e9986fb5dc5627250e5f2db56b2a8058bebafd994ee3d48db322650d5028d48bfd97366e288491f804882d997bb7 languageName: node linkType: hard @@ -8123,14 +8074,14 @@ __metadata: languageName: node linkType: hard -"eslint@npm:8.55.0": - version: 8.55.0 - resolution: "eslint@npm:8.55.0" +"eslint@npm:8.56.0": + version: 8.56.0 + resolution: "eslint@npm:8.56.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.6.1" "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.55.0" + "@eslint/js": "npm:8.56.0" "@humanwhocodes/config-array": "npm:^0.11.13" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" @@ -8167,7 +8118,7 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: afd016cfbe9e9d667b3f98c14c681a7e518808f6c30856e56cbb02248900eac5bf6dc5e577a7eaec259539486db48ef7d16ef58fb14b1585ba7c84b35490c53c + checksum: ef6193c6e4cef20774b985a5cc2fd4bf6d3c4decd423117cbc4a0196617861745db291217ad3c537bc3a160650cca965bc818f55e1f3e446af1fcb293f9940a5 languageName: node linkType: hard @@ -8304,23 +8255,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^7.1.1": - version: 7.2.0 - resolution: "execa@npm:7.2.0" - dependencies: - cross-spawn: "npm:^7.0.3" - get-stream: "npm:^6.0.1" - human-signals: "npm:^4.3.0" - is-stream: "npm:^3.0.0" - merge-stream: "npm:^2.0.0" - npm-run-path: "npm:^5.1.0" - onetime: "npm:^6.0.0" - signal-exit: "npm:^3.0.7" - strip-final-newline: "npm:^3.0.0" - checksum: 473feff60f9d4dbe799225948de48b5158c1723021d19c4b982afe37bcd111ae84e1b4c9dfe967fae5101b0894b1a62e4dd564a286dfa3e46d7b0cfdbf7fe62b - languageName: node - linkType: hard - "exif-parser@npm:^0.1.12": version: 0.1.12 resolution: "exif-parser@npm:0.1.12" @@ -8487,15 +8421,15 @@ __metadata: linkType: hard "fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.2, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0": - version: 3.3.1 - resolution: "fast-glob@npm:3.3.1" + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" micromatch: "npm:^4.0.4" - checksum: 51bcd15472879dfe51d4b01c5b70bbc7652724d39cdd082ba11276dbd7d84db0f6b33757e1938af8b2768a4bf485d9be0c89153beae24ee8331d6dcc7550379f + checksum: 222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df languageName: node linkType: hard @@ -8537,11 +8471,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.15.0 - resolution: "fastq@npm:1.15.0" + version: 1.16.0 + resolution: "fastq@npm:1.16.0" dependencies: reusify: "npm:^1.0.4" - checksum: 67c01b1c972e2d5b6fea197a1a39d5d582982aea69ff4c504badac71080d8396d4843b165a9686e907c233048f15a86bbccb0e7f83ba771f6fa24bcde059d0c3 + checksum: de151543aab9d91900ed5da88860c46987ece925c628df586fac664235f25e020ec20729e1c032edb5fd2520fd4aa5b537d69e39b689e65e82112cfbecb4479e languageName: node linkType: hard @@ -8554,6 +8488,15 @@ __metadata: languageName: node linkType: hard +"figures@npm:^3.2.0": + version: 3.2.0 + resolution: "figures@npm:3.2.0" + dependencies: + escape-string-regexp: "npm:^1.0.5" + checksum: a3bf94e001be51d3770500789157f067218d4bc681a65e1f69d482de15120bcac822dceb1a7b3803f32e4e3a61a46df44f7f2c8ba95d6375e7491502e0dd3d97 + languageName: node + linkType: hard + "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -8737,13 +8680,13 @@ __metadata: linkType: hard "flat-cache@npm:^3.0.4": - version: 3.1.1 - resolution: "flat-cache@npm:3.1.1" + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" dependencies: flatted: "npm:^3.2.9" keyv: "npm:^4.5.3" rimraf: "npm:^3.0.2" - checksum: 04b57c7cb4bd54f1e80a335f037bff467cc7b2479ecc015ff7e78fd41aa12777757d55836e99c7e5faca2271eb204a96bf109b4d98c36c20c3b98cf1372b5592 + checksum: 02381c6ece5e9fa5b826c9bbea481d7fd77645d96e4b0b1395238124d581d10e56f17f723d897b6d133970f7a57f0fab9148cbbb67237a0a0ffe794ba60c0c70 languageName: node linkType: hard @@ -8986,22 +8929,6 @@ __metadata: languageName: node linkType: hard -"gauge@npm:^4.0.3": - version: 4.0.4 - resolution: "gauge@npm:4.0.4" - dependencies: - aproba: "npm:^1.0.3 || ^2.0.0" - color-support: "npm:^1.1.3" - console-control-strings: "npm:^1.1.0" - has-unicode: "npm:^2.0.1" - signal-exit: "npm:^3.0.7" - string-width: "npm:^4.2.3" - strip-ansi: "npm:^6.0.1" - wide-align: "npm:^1.1.5" - checksum: 09535dd53b5ced6a34482b1fa9f3929efdeac02f9858569cde73cef3ed95050e0f3d095706c1689614059898924b7a74aa14042f51381a1ccc4ee5c29d2389c4 - languageName: node - linkType: hard - "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9030,7 +8957,7 @@ __metadata: languageName: node linkType: hard -"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": +"get-func-name@npm:^2.0.1": version: 2.0.2 resolution: "get-func-name@npm:2.0.2" checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b @@ -9056,7 +8983,7 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": +"get-stream@npm:^6.0.0": version: 6.0.1 resolution: "get-stream@npm:6.0.1" checksum: 781266d29725f35c59f1d214aedc92b0ae855800a980800e2923b3fbc4e56b3cb6e462c42e09a1cf1a00c64e056a78fa407cbe06c7c92b7e5cd49b4b85c2a497 @@ -9165,7 +9092,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.3.10, glob@npm:^10.2.2": +"glob@npm:10.3.10, glob@npm:^10.2.2, glob@npm:^10.3.10": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -9194,7 +9121,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6": +"glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.6": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -9263,11 +9190,11 @@ __metadata: linkType: hard "globals@npm:^13.19.0": - version: 13.23.0 - resolution: "globals@npm:13.23.0" + version: 13.24.0 + resolution: "globals@npm:13.24.0" dependencies: type-fest: "npm:^0.20.2" - checksum: bf6a8616f4a64959c0b9a8eb4dc8a02e7dd0082385f7f06bc9694d9fceabe39f83f83789322cfe0470914dc8b273b7a29af5570b9e1a0507d3fb7348a64703a3 + checksum: 62c5b1997d06674fc7191d3e01e324d3eda4d65ac9cc4e78329fa3b5c4fd42a0e1c8722822497a6964eee075255ce21ccf1eec2d83f92ef3f06653af4d0ee28e languageName: node linkType: hard @@ -9516,13 +9443,6 @@ __metadata: languageName: node linkType: hard -"has-unicode@npm:^2.0.1": - version: 2.0.1 - resolution: "has-unicode@npm:2.0.1" - checksum: 041b4293ad6bf391e21c5d85ed03f412506d6623786b801c4ab39e4e6ca54993f13201bceb544d92963f9e0024e6e7fbf0cb1d84c9d6b31cb9c79c8c990d13d8 - languageName: node - linkType: hard - "has-value@npm:^0.3.1": version: 0.3.1 resolution: "has-value@npm:0.3.1" @@ -9580,10 +9500,10 @@ __metadata: languageName: node linkType: hard -"hls.js@npm:1.4.13": - version: 1.4.13 - resolution: "hls.js@npm:1.4.13" - checksum: 8d54aaeaa6f396be85e0dde4fe6b6e6c0f8a60d821a581aa465ce63041a31bc553af154dd945b3da854a24e626cbd1e7667f7922452ccdab9e5f2984071f7aac +"hls.js@npm:1.4.14": + version: 1.4.14 + resolution: "hls.js@npm:1.4.14" + checksum: 9b4bbb379022da6a0c923d351c4592aac3be271d7458804ee7beaf6fa61f58a2538f16b5b23e180c7d636aa033ba373a32829b803dd654627fac5b647fac9e67 languageName: node linkType: hard @@ -9591,22 +9511,22 @@ __metadata: version: 0.0.0-use.local resolution: "home-assistant-frontend@workspace:." dependencies: - "@babel/core": "npm:7.23.5" - "@babel/helper-define-polyfill-provider": "npm:0.4.3" - "@babel/plugin-proposal-decorators": "npm:7.23.5" - "@babel/plugin-transform-runtime": "npm:7.23.4" - "@babel/preset-env": "npm:7.23.5" + "@babel/core": "npm:7.23.7" + "@babel/helper-define-polyfill-provider": "npm:0.4.4" + "@babel/plugin-proposal-decorators": "npm:7.23.7" + "@babel/plugin-transform-runtime": "npm:7.23.7" + "@babel/preset-env": "npm:7.23.7" "@babel/preset-typescript": "npm:7.23.3" - "@babel/runtime": "npm:7.23.5" + "@babel/runtime": "npm:7.23.7" "@braintree/sanitize-url": "npm:7.0.0" - "@bundle-stats/plugin-webpack-filter": "npm:4.8.3" + "@bundle-stats/plugin-webpack-filter": "npm:4.8.4" "@codemirror/autocomplete": "npm:6.11.1" "@codemirror/commands": "npm:6.3.2" "@codemirror/language": "npm:6.9.3" "@codemirror/legacy-modes": "npm:6.3.3" "@codemirror/search": "npm:6.5.5" "@codemirror/state": "npm:6.3.3" - "@codemirror/view": "npm:6.22.2" + "@codemirror/view": "npm:6.22.3" "@egjs/hammerjs": "npm:2.0.17" "@formatjs/intl-datetimeformat": "npm:6.12.0" "@formatjs/intl-displaynames": "npm:6.6.4" @@ -9655,9 +9575,9 @@ __metadata: "@material/mwc-top-app-bar": "npm:0.27.0" "@material/mwc-top-app-bar-fixed": "npm:0.27.0" "@material/top-app-bar": "npm:=14.0.0-canary.53b3cad2f.0" - "@material/web": "npm:=1.0.1" - "@mdi/js": "npm:7.3.67" - "@mdi/svg": "npm:7.3.67" + "@material/web": "npm:=1.1.1" + "@mdi/js": "npm:7.4.47" + "@mdi/svg": "npm:7.4.47" "@octokit/auth-oauth-device": "npm:6.0.1" "@octokit/plugin-retry": "npm:6.0.1" "@octokit/rest": "npm:20.0.2" @@ -9670,7 +9590,7 @@ __metadata: "@polymer/polymer": "npm:3.5.1" "@rollup/plugin-babel": "npm:6.0.4" "@rollup/plugin-commonjs": "npm:25.0.7" - "@rollup/plugin-json": "npm:6.0.1" + "@rollup/plugin-json": "npm:6.1.0" "@rollup/plugin-node-resolve": "npm:15.2.3" "@rollup/plugin-replace": "npm:5.0.5" "@thomasloven/round-slider": "npm:0.6.0" @@ -9690,10 +9610,10 @@ __metadata: "@types/tar": "npm:6.1.10" "@types/ua-parser-js": "npm:0.7.39" "@types/webspeechapi": "npm:0.0.29" - "@typescript-eslint/eslint-plugin": "npm:6.13.2" - "@typescript-eslint/parser": "npm:6.13.2" - "@vaadin/combo-box": "npm:24.2.5" - "@vaadin/vaadin-themable-mixin": "npm:24.2.5" + "@typescript-eslint/eslint-plugin": "npm:6.16.0" + "@typescript-eslint/parser": "npm:6.16.0" + "@vaadin/combo-box": "npm:24.3.2" + "@vaadin/vaadin-themable-mixin": "npm:24.3.2" "@vibrant/color": "npm:3.2.1-alpha.1" "@vibrant/core": "npm:3.2.1-alpha.1" "@vibrant/quantizer-mmcq": "npm:3.2.1-alpha.1" @@ -9705,25 +9625,25 @@ __metadata: app-datepicker: "npm:5.1.1" babel-loader: "npm:9.1.3" babel-plugin-template-html-minifier: "npm:4.1.0" - chai: "npm:4.3.10" + chai: "npm:5.0.0" chart.js: "npm:4.4.1" comlink: "npm:4.4.1" - core-js: "npm:3.33.3" + core-js: "npm:3.34.0" cropperjs: "npm:1.6.1" date-fns: "npm:2.30.0" date-fns-tz: "npm:2.0.0" deep-clone-simple: "npm:1.1.1" deep-freeze: "npm:0.0.1" del: "npm:7.1.0" - element-internals-polyfill: "npm:1.3.9" - eslint: "npm:8.55.0" + element-internals-polyfill: "npm:1.3.10" + eslint: "npm:8.56.0" eslint-config-airbnb-base: "npm:15.0.0" eslint-config-airbnb-typescript: "npm:17.1.0" eslint-config-prettier: "npm:9.1.0" eslint-import-resolver-webpack: "npm:0.13.8" eslint-plugin-disable: "npm:2.0.3" - eslint-plugin-import: "npm:2.29.0" - eslint-plugin-lit: "npm:1.10.1" + eslint-plugin-import: "npm:2.29.1" + eslint-plugin-lit: "npm:1.11.0" eslint-plugin-lit-a11y: "npm:4.1.1" eslint-plugin-unused-imports: "npm:3.0.0" eslint-plugin-wc: "npm:2.0.4" @@ -9738,7 +9658,7 @@ __metadata: gulp-merge-json: "npm:2.1.2" gulp-rename: "npm:2.0.0" gulp-zopfli-green: "npm:6.0.1" - hls.js: "npm:1.4.13" + hls.js: "npm:1.4.14" home-assistant-js-websocket: "npm:9.1.0" html-minifier-terser: "npm:7.2.0" husky: "npm:8.0.3" @@ -9751,17 +9671,17 @@ __metadata: leaflet-draw: "npm:1.0.4" lint-staged: "npm:15.2.0" lit: "npm:2.8.0" - lit-analyzer: "npm:2.0.1" + lit-analyzer: "npm:2.0.2" lodash.template: "npm:4.5.0" luxon: "npm:3.4.4" magic-string: "npm:0.30.5" map-stream: "npm:0.0.7" - marked: "npm:11.0.1" + marked: "npm:11.1.0" memoize-one: "npm:6.0.0" mocha: "npm:10.2.0" node-vibrant: "npm:3.2.1-alpha.1" object-hash: "npm:3.0.0" - open: "npm:9.1.0" + open: "npm:10.0.2" pinst: "npm:3.0.0" prettier: "npm:3.1.1" proxy-polyfill: "npm:0.3.2" @@ -9772,7 +9692,7 @@ __metadata: rollup: "npm:2.79.1" rollup-plugin-string: "npm:3.0.0" rollup-plugin-terser: "npm:7.0.2" - rollup-plugin-visualizer: "npm:5.11.0" + rollup-plugin-visualizer: "npm:5.12.0" rrule: "npm:2.8.1" serve-handler: "npm:6.1.5" sinon: "npm:17.0.1" @@ -9782,7 +9702,7 @@ __metadata: superstruct: "npm:1.0.3" systemjs: "npm:6.14.2" tar: "npm:6.2.0" - terser-webpack-plugin: "npm:5.3.9" + terser-webpack-plugin: "npm:5.3.10" tinykeys: "npm:2.1.0" ts-lit-plugin: "npm:2.0.1" tsparticles-engine: "npm:2.12.0" @@ -9794,14 +9714,14 @@ __metadata: vinyl-source-stream: "npm:2.0.0" vis-data: "npm:7.1.9" vis-network: "npm:9.1.9" - vue: "npm:2.7.15" + vue: "npm:2.7.16" vue2-daterange-picker: "npm:0.6.8" webpack: "npm:5.89.0" webpack-cli: "npm:5.1.4" webpack-dev-server: "npm:4.15.1" webpack-manifest-plugin: "npm:5.0.0" webpack-stats-plugin: "npm:1.1.3" - webpackbar: "npm:5.0.2" + webpackbar: "npm:6.0.0" weekstart: "npm:2.0.0" workbox-build: "npm:7.0.0" workbox-cacheable-response: "npm:7.0.0" @@ -9959,14 +9879,13 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^5.0.0": - version: 5.0.0 - resolution: "http-proxy-agent@npm:5.0.0" +"http-proxy-agent@npm:^7.0.0": + version: 7.0.0 + resolution: "http-proxy-agent@npm:7.0.0" dependencies: - "@tootallnate/once": "npm:2" - agent-base: "npm:6" - debug: "npm:4" - checksum: 5ee19423bc3e0fd5f23ce991b0755699ad2a46a440ce9cec99e8126bb98448ad3479d2c0ea54be5519db5b19a4ffaa69616bac01540db18506dd4dac3dc418f0 + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: dbaaf3d9f3fc4df4a5d7ec45d456ec50f575240b557160fa63427b447d1f812dd7fe4a4f17d2e1ba003d231f07edf5a856ea6d91cb32d533062ff20a7803ccac languageName: node linkType: hard @@ -9999,13 +9918,13 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^5.0.0": - version: 5.0.1 - resolution: "https-proxy-agent@npm:5.0.1" +"https-proxy-agent@npm:^7.0.1": + version: 7.0.2 + resolution: "https-proxy-agent@npm:7.0.2" dependencies: - agent-base: "npm:6" + agent-base: "npm:^7.0.2" debug: "npm:4" - checksum: f0dce7bdcac5e8eaa0be3c7368bb8836ed010fb5b6349ffb412b172a203efe8f807d9a6681319105ea1b6901e1972c7b5ea899672a7b9aad58309f766dcbe0df + checksum: 9ec844f78fd643608239c9c3f6819918631df5cd3e17d104cc507226a39b5d4adda9d790fc9fd63ac0d2bb8a761b2f9f60faa80584a9bf9d7f2e8c5ed0acd330 languageName: node linkType: hard @@ -10016,13 +9935,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^4.3.0": - version: 4.3.1 - resolution: "human-signals@npm:4.3.1" - checksum: fa59894c358fe9f2b5549be2fb083661d5e1dff618d3ac70a49ca73495a72e873fbf6c0878561478e521e17d498292746ee391791db95ffe5747bfb5aef8765b - languageName: node - linkType: hard - "human-signals@npm:^5.0.0": version: 5.0.0 resolution: "human-signals@npm:5.0.0" @@ -10030,15 +9942,6 @@ __metadata: languageName: node linkType: hard -"humanize-ms@npm:^1.2.1": - version: 1.2.1 - resolution: "humanize-ms@npm:1.2.1" - dependencies: - ms: "npm:^2.0.0" - checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 - languageName: node - linkType: hard - "husky@npm:8.0.3": version: 8.0.3 resolution: "husky@npm:8.0.3" @@ -10088,9 +9991,9 @@ __metadata: linkType: hard "ignore@npm:^5.2.0, ignore@npm:^5.2.4": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 4f7caf5d2005da21a382d4bd1d2aa741a3bed51de185c8562dd7f899a81a620ac4fd0619b06f7029a38ae79e4e4c134399db3bd0192c703c3ef54bb82df3086c + version: 5.3.0 + resolution: "ignore@npm:5.3.0" + checksum: 51594355cea4c6ad6b28b3b85eb81afa7b988a1871feefd7062baf136c95aa06760ee934fa9590e43d967bd377ce84a4cf6135fbeb6063e063f1182a0e9a3bcd languageName: node linkType: hard @@ -10283,21 +10186,12 @@ __metadata: languageName: node linkType: hard -"is-accessor-descriptor@npm:^0.1.6": - version: 0.1.6 - resolution: "is-accessor-descriptor@npm:0.1.6" - dependencies: - kind-of: "npm:^3.0.2" - checksum: 3d629a086a9585bc16a83a8e8a3416f400023301855cafb7ccc9a1d63145b7480f0ad28877dcc2cce09492c4ec1c39ef4c071996f24ee6ac626be4217b8ffc8a - languageName: node - linkType: hard - -"is-accessor-descriptor@npm:^1.0.0": - version: 1.0.0 - resolution: "is-accessor-descriptor@npm:1.0.0" +"is-accessor-descriptor@npm:^1.0.1": + version: 1.0.1 + resolution: "is-accessor-descriptor@npm:1.0.1" dependencies: - kind-of: "npm:^6.0.0" - checksum: 8e475968e9b22f9849343c25854fa24492dbe8ba0dea1a818978f9f1b887339190b022c9300d08c47fe36f1b913d70ce8cbaca00369c55a56705fdb7caed37fe + hasown: "npm:^2.0.0" + checksum: df0d1da1a320e57c594e6f9b52dab8a6bece6dc90e51689d05ac8e5247164aa3eb3e9c66b37027bebfc0ea5fcce6d9503dbc41dccd82f4b57add79a307735365 languageName: node linkType: hard @@ -10388,21 +10282,12 @@ __metadata: languageName: node linkType: hard -"is-data-descriptor@npm:^0.1.4": - version: 0.1.4 - resolution: "is-data-descriptor@npm:0.1.4" - dependencies: - kind-of: "npm:^3.0.2" - checksum: 5c622e078ba933a78338ae398a3d1fc5c23332b395312daf4f74bab4afb10d061cea74821add726cb4db8b946ba36217ee71a24fe71dd5bca4632edb7f6aad87 - languageName: node - linkType: hard - -"is-data-descriptor@npm:^1.0.0": - version: 1.0.0 - resolution: "is-data-descriptor@npm:1.0.0" +"is-data-descriptor@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-descriptor@npm:1.0.1" dependencies: - kind-of: "npm:^6.0.0" - checksum: b8b1f13a535800a9f35caba2743b2cfd1e76312c0f94248c333d3b724d6ac6e07f06011e8b00eb2442f27dfc8fb71faf3dd52ced6bee41bb836be3df5d7811ee + hasown: "npm:^2.0.0" + checksum: 49b36e903b31623b0c5b416e182e366810ef97a3a19ab0e6cd501eb5599112680b7d9e768b07a84fb52aa2510a92b3eb51a3e18ce8d5f7978a49f4b50e6ec6dd languageName: node linkType: hard @@ -10416,24 +10301,22 @@ __metadata: linkType: hard "is-descriptor@npm:^0.1.0": - version: 0.1.6 - resolution: "is-descriptor@npm:0.1.6" + version: 0.1.7 + resolution: "is-descriptor@npm:0.1.7" dependencies: - is-accessor-descriptor: "npm:^0.1.6" - is-data-descriptor: "npm:^0.1.4" - kind-of: "npm:^5.0.0" - checksum: b946ba842187c2784a5a0d67bd0e0271b14678f4fdce7d2295dfda9201f3408f55f56e11e5e66bfa4d2b9d45655b6105ad872ad7d37fb63f582587464fd414d7 + is-accessor-descriptor: "npm:^1.0.1" + is-data-descriptor: "npm:^1.0.1" + checksum: 38783182c3d83f839a9fa3e87b4d6de11fa9639833ed98993ea51aea2296b2da155121956e148695a738228871d1057c5f963d0b1c857bb8a4a38d8dd9ceeb56 languageName: node linkType: hard "is-descriptor@npm:^1.0.0, is-descriptor@npm:^1.0.2": - version: 1.0.2 - resolution: "is-descriptor@npm:1.0.2" + version: 1.0.3 + resolution: "is-descriptor@npm:1.0.3" dependencies: - is-accessor-descriptor: "npm:^1.0.0" - is-data-descriptor: "npm:^1.0.0" - kind-of: "npm:^6.0.2" - checksum: e68059b333db331d5ea68cb367ce12fc6810853ced0e2221e6747143bbdf223dee73ebe8f331bafe04e34fdbe3da584b6af3335e82eabfaa33d5026efa33ca34 + is-accessor-descriptor: "npm:^1.0.1" + is-data-descriptor: "npm:^1.0.1" + checksum: b940d04d93adaffb749b3ca7f7f6d73dd3c5582b674f372513ecb5511a8a3f3ff4a24f4c1161cb10e48fe4886f9e84c09fa71785def27905ca8df1197e563dc6 languageName: node linkType: hard @@ -10829,6 +10712,15 @@ __metadata: languageName: node linkType: hard +"is-wsl@npm:^3.1.0": + version: 3.1.0 + resolution: "is-wsl@npm:3.1.0" + dependencies: + is-inside-container: "npm:^1.0.0" + checksum: f9734c81f2f9cf9877c5db8356bfe1ff61680f1f4c1011e91278a9c0564b395ae796addb4bf33956871041476ec82c3e5260ed57b22ac91794d4ae70a1d2f0a9 + languageName: node + linkType: hard + "isarray@npm:0.0.1": version: 0.0.1 resolution: "isarray@npm:0.0.1" @@ -10864,6 +10756,13 @@ __metadata: languageName: node linkType: hard +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + "isobject@npm:^2.0.0": version: 2.1.0 resolution: "isobject@npm:2.1.0" @@ -11130,14 +11029,14 @@ __metadata: languageName: node linkType: hard -"kind-of@npm:^5.0.0, kind-of@npm:^5.0.2": +"kind-of@npm:^5.0.2": version: 5.1.0 resolution: "kind-of@npm:5.1.0" checksum: acf7cc73881f27629f700a80de77ff7fe4abc9430eac7ddb09117f75126e578ee8d7e44c4dacb6a9e802d5d881abf007ee6af3cfbe55f8b5cf0a7fdc49a02aa3 languageName: node linkType: hard -"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2": +"kind-of@npm:^6.0.2": version: 6.0.3 resolution: "kind-of@npm:6.0.3" checksum: 5873d303fb36aad875b7538798867da2ae5c9e328d67194b0162a3659a627d22f742fc9c4ae95cd1704132a24b00cae5041fc00c0f6ef937dc17080dc4dbb962 @@ -11389,9 +11288,9 @@ __metadata: languageName: node linkType: hard -"lit-analyzer@npm:2.0.1, lit-analyzer@npm:^2.0.1": - version: 2.0.1 - resolution: "lit-analyzer@npm:2.0.1" +"lit-analyzer@npm:2.0.2, lit-analyzer@npm:^2.0.1": + version: 2.0.2 + resolution: "lit-analyzer@npm:2.0.2" dependencies: "@vscode/web-custom-data": "npm:^0.4.2" chalk: "npm:^2.4.2" @@ -11404,7 +11303,7 @@ __metadata: web-component-analyzer: "npm:^2.0.0" bin: lit-analyzer: cli.js - checksum: 06661790554ae80d8dcb4e3083d6d58c9000bc840fbbeac2edf8e7bc09332b8676b0ca197209ca75bf418cd59a2d8ac05ddeb98be084bf0218d7896335d2c87e + checksum: 247de26c9de2a340d9bf0d82ce87c8ff1a32c399111c5e66485e6831e204d3e3393614d7a430b24869c392861a075dba581647185c66c4febec9cebf4c3433e8 languageName: node linkType: hard @@ -11625,12 +11524,12 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.6": - version: 2.3.7 - resolution: "loupe@npm:2.3.7" +"loupe@npm:^3.0.0": + version: 3.0.2 + resolution: "loupe@npm:3.0.2" dependencies: get-func-name: "npm:^2.0.1" - checksum: 635c8f0914c2ce7ecfe4e239fbaf0ce1d2c00e4246fafcc4ed000bfdb1b8f89d05db1a220054175cca631ebf3894872a26fffba0124477fcb562f78762848fb1 + checksum: 256467bf10afaca4a5dd79b32e36fcd042bc2a247232e940c62bcc07cb114c2d7a549218eb103598e7cdb8bd32c6601fe230d80e03b8d49782973d4da11c08ed languageName: node linkType: hard @@ -11643,6 +11542,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.1.0 + resolution: "lru-cache@npm:10.1.0" + checksum: 207278d6fa711fb1f94a0835d4d4737441d2475302482a14785b10515e4c906a57ebf9f35bf060740c9560e91c7c1ad5a04fd7ed030972a9ba18bce2a228e95b + languageName: node + linkType: hard + "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -11661,20 +11567,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.7.1": - version: 7.18.3 - resolution: "lru-cache@npm:7.18.3" - checksum: 6029ca5aba3aacb554e919d7ef804fffd4adfc4c83db00fac8248c7c78811fb6d4b6f70f7fd9d55032b3823446546a007edaa66ad1f2377ae833bd983fac5d98 - languageName: node - linkType: hard - -"lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.0.1 - resolution: "lru-cache@npm:10.0.1" - checksum: 5bb91a97a342a41fd049c3494b44d9e21a7d4843f9284d0a0b26f00bb0e436f1f627d0641c78f88be16b86b4231546c5ee4f284733fb530c7960f0bcd7579026 - languageName: node - linkType: hard - "luxon@npm:3.4.4": version: 3.4.4 resolution: "luxon@npm:3.4.4" @@ -11700,26 +11592,22 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^11.0.3": - version: 11.1.1 - resolution: "make-fetch-happen@npm:11.1.1" +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" dependencies: - agentkeepalive: "npm:^4.2.1" - cacache: "npm:^17.0.0" + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" http-cache-semantics: "npm:^4.1.1" - http-proxy-agent: "npm:^5.0.0" - https-proxy-agent: "npm:^5.0.0" is-lambda: "npm:^1.0.1" - lru-cache: "npm:^7.7.1" - minipass: "npm:^5.0.0" + minipass: "npm:^7.0.2" minipass-fetch: "npm:^3.0.0" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" negotiator: "npm:^0.6.3" promise-retry: "npm:^2.0.1" - socks-proxy-agent: "npm:^7.0.0" ssri: "npm:^10.0.0" - checksum: b4b442cfaaec81db159f752a5f2e3ee3d7aa682782868fa399200824ec6298502e01bdc456e443dc219bcd5546c8e4471644d54109c8599841dc961d17a805fa + checksum: ded5a91a02b76381b06a4ec4d5c1d23ebbde15d402b3c3e4533b371dac7e2f7ca071ae71ae6dae72aa261182557b7b1b3fd3a705b39252dc17f74fa509d3e76f languageName: node linkType: hard @@ -11755,12 +11643,21 @@ __metadata: languageName: node linkType: hard -"marked@npm:11.0.1": - version: 11.0.1 - resolution: "marked@npm:11.0.1" +"markdown-table@npm:^2.0.0": + version: 2.0.0 + resolution: "markdown-table@npm:2.0.0" + dependencies: + repeat-string: "npm:^1.0.0" + checksum: 8018cd1a1733ffda916a0548438e50f3d21b6c6b71fb23696b33c0b5922a8cc46035eb4b204a59c6054f063076f934461ae094599656a63f87c1c3a80bd3c229 + languageName: node + linkType: hard + +"marked@npm:11.1.0": + version: 11.1.0 + resolution: "marked@npm:11.1.0" bin: marked: bin/marked.js - checksum: a732d6d2ad1b74fc0e94eea266e87fe17777bce4f1c631230384b843c27bd03c18fce337a9effd97c893ef4583c19d8ddc1c965aa71b602375efb89de14d5e67 + checksum: 4636b16283c1963a715e97578d9fd91588b11949276e633a4de53dc408bcdab7b846d2b5c2cf3239f6d2dc8affe5294a0895954b5e3d9562d77301d8847a8915 languageName: node linkType: hard @@ -11954,21 +11851,21 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^5.0.1": - version: 5.1.6 - resolution: "minimatch@npm:5.1.6" +"minimatch@npm:9.0.3, minimatch@npm:^9.0.1": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" dependencies: brace-expansion: "npm:^2.0.1" - checksum: 126b36485b821daf96d33b5c821dac600cc1ab36c87e7a532594f9b1652b1fa89a1eebcaad4dff17c764dce1a7ac1531327f190fed5f97d8f6e5f889c116c429 + checksum: c81b47d28153e77521877649f4bab48348d10938df9e8147a58111fe00ef89559a2938de9f6632910c4f7bf7bb5cd81191a546167e58d357f0cfb1e18cecc1c5 languageName: node linkType: hard -"minimatch@npm:^9.0.1": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" +"minimatch@npm:^5.0.1": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" dependencies: brace-expansion: "npm:^2.0.1" - checksum: c81b47d28153e77521877649f4bab48348d10938df9e8147a58111fe00ef89559a2938de9f6632910c4f7bf7bb5cd81191a546167e58d357f0cfb1e18cecc1c5 + checksum: 126b36485b821daf96d33b5c821dac600cc1ab36c87e7a532594f9b1652b1fa89a1eebcaad4dff17c764dce1a7ac1531327f190fed5f97d8f6e5f889c116c429 languageName: node linkType: hard @@ -11979,12 +11876,12 @@ __metadata: languageName: node linkType: hard -"minipass-collect@npm:^1.0.2": - version: 1.0.2 - resolution: "minipass-collect@npm:1.0.2" +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" dependencies: - minipass: "npm:^3.0.0" - checksum: 14df761028f3e47293aee72888f2657695ec66bd7d09cae7ad558da30415fdc4752bbfee66287dcc6fd5e6a2fa3466d6c484dc1cbd986525d9393b9523d97f10 + minipass: "npm:^7.0.3" + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 languageName: node linkType: hard @@ -12053,7 +11950,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.3": +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": version: 7.0.4 resolution: "minipass@npm:7.0.4" checksum: e864bd02ceb5e0707696d58f7ce3a0b89233f0d686ef0d447a66db705c0846a8dc6f34865cd85256c1472ff623665f616b90b8ff58058b2ad996c5de747d2d18 @@ -12146,7 +12043,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1": +"ms@npm:2.1.3, ms@npm:^2.1.1": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -12197,12 +12094,12 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.6": - version: 3.3.6 - resolution: "nanoid@npm:3.3.6" +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" bin: nanoid: bin/nanoid.cjs - checksum: 67235c39d1bc05851383dadde5cf77ae1c90c2a1d189e845c7f20f646f0488d875ad5f5226bbba072a88cebbb085a3f784a6673117daf785bdf614a852550362 + checksum: ac1eb60f615b272bccb0e2b9cd933720dad30bf9708424f691b8113826bb91aca7e9d14ef5d9415a6ba15c266b37817256f58d8ce980c82b0ba3185352565679 languageName: node linkType: hard @@ -12284,30 +12181,29 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 9.4.0 - resolution: "node-gyp@npm:9.4.0" + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" - glob: "npm:^7.1.4" + glob: "npm:^10.3.10" graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^11.0.3" - nopt: "npm:^6.0.0" - npmlog: "npm:^6.0.0" - rimraf: "npm:^3.0.2" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^3.0.0" semver: "npm:^7.3.5" tar: "npm:^6.1.2" - which: "npm:^2.0.2" + which: "npm:^4.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 458317127c63877365f227b18ef2362b013b7f8440b35ae722935e61b31e6b84ec0e3625ab07f90679e2f41a1d5a7df6c4049fdf8e7b3c81fcf22775147b47ac + checksum: 578cf0c821f258ce4b6ebce4461eca4c991a4df2dee163c0624f2fe09c7d6d37240be4942285a0048d307230248ee0b18382d6623b9a0136ce9533486deddfa8 languageName: node linkType: hard -"node-releases@npm:^2.0.13": - version: 2.0.13 - resolution: "node-releases@npm:2.0.13" - checksum: c9bb813aab2717ff8b3015ecd4c7c5670a5546e9577699a7c84e8d69230cd3b1ce8f863f8e9b50f18b19a5ffa4b9c1a706bbbfe4c378de955fedbab04488a338 +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 0f7607ec7db5ef1dc616899a5f24ae90c869b6a54c2d4f36ff6d84a282ab9343c7ff3ca3670fe4669171bb1e8a9b3e286e1ef1c131f09a83d70554f855d54f24 languageName: node linkType: hard @@ -12340,14 +12236,14 @@ __metadata: languageName: node linkType: hard -"nopt@npm:^6.0.0": - version: 6.0.0 - resolution: "nopt@npm:6.0.0" +"nopt@npm:^7.0.0": + version: 7.2.0 + resolution: "nopt@npm:7.2.0" dependencies: - abbrev: "npm:^1.0.0" + abbrev: "npm:^2.0.0" bin: nopt: bin/nopt.js - checksum: 3c1128e07cd0241ae66d6e6a472170baa9f3e84dd4203950ba8df5bafac4efa2166ce917a57ef02b01ba7c40d18b2cc64b29b225fd3640791fe07b24f0b33a32 + checksum: 1e7489f17cbda452c8acaf596a8defb4ae477d2a9953b76eb96f4ec3f62c6b421cd5174eaa742f88279871fde9586d8a1d38fb3f53fa0c405585453be31dff4c languageName: node linkType: hard @@ -12407,23 +12303,11 @@ __metadata: linkType: hard "npm-run-path@npm:^5.1.0": - version: 5.1.0 - resolution: "npm-run-path@npm:5.1.0" + version: 5.2.0 + resolution: "npm-run-path@npm:5.2.0" dependencies: path-key: "npm:^4.0.0" - checksum: dc184eb5ec239d6a2b990b43236845332ef12f4e0beaa9701de724aa797fe40b6bbd0157fb7639d24d3ab13f5d5cf22d223a19c6300846b8126f335f788bee66 - languageName: node - linkType: hard - -"npmlog@npm:^6.0.0": - version: 6.0.2 - resolution: "npmlog@npm:6.0.2" - dependencies: - are-we-there-yet: "npm:^3.0.0" - console-control-strings: "npm:^1.1.0" - gauge: "npm:^4.0.3" - set-blocking: "npm:^2.0.0" - checksum: 82b123677e62deb9e7472e27b92386c09e6e254ee6c8bcd720b3011013e4168bc7088e984f4fbd53cb6e12f8b4690e23e4fa6132689313e0d0dc4feea45489bb + checksum: c5325e016014e715689c4014f7e0be16cc4cbf529f32a1723e511bc4689b5f823b704d2bca61ac152ce2bda65e0205dc8b3ba0ec0f5e4c3e162d302f6f5b9efb languageName: node linkType: hard @@ -12476,14 +12360,14 @@ __metadata: linkType: hard "object.assign@npm:^4.0.4, object.assign@npm:^4.1.0, object.assign@npm:^4.1.2, object.assign@npm:^4.1.4": - version: 4.1.4 - resolution: "object.assign@npm:4.1.4" + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" + call-bind: "npm:^1.0.5" + define-properties: "npm:^1.2.1" has-symbols: "npm:^1.0.3" object-keys: "npm:^1.1.1" - checksum: fd82d45289df0a952d772817622ecbaeb4ec933d3abb53267aede083ee38f6a395af8fadfbc569ee575115b0b7c9b286e7cfb2b7a2557b1055f7acbce513bc29 + checksum: dbb22da4cda82e1658349ea62b80815f587b47131b3dd7a4ab7f84190ab31d206bbd8fe7e26ae3220c55b65725ac4529825f6142154211220302aa6b1518045d languageName: node linkType: hard @@ -12637,15 +12521,15 @@ __metadata: languageName: node linkType: hard -"open@npm:9.1.0": - version: 9.1.0 - resolution: "open@npm:9.1.0" +"open@npm:10.0.2": + version: 10.0.2 + resolution: "open@npm:10.0.2" dependencies: - default-browser: "npm:^4.0.0" + default-browser: "npm:^5.2.1" define-lazy-prop: "npm:^3.0.0" is-inside-container: "npm:^1.0.0" - is-wsl: "npm:^2.2.0" - checksum: b45bcc7a6795804a2f560f0ca9f5e5344114bc40754d10c28a811c0c8f7027356979192931a6a7df2ab9e5bab3058988c99ae55f4fb71db2ce9fc77c40f619aa + is-wsl: "npm:^3.1.0" + checksum: 6f7f9e08204af00930f2998690293df1a919a61c98b225ff9e3aa09a765254b8a98bec101644ffe991452c6aabea0c6f9e49670b559d48a44bfc5238f6b58351 languageName: node linkType: hard @@ -13067,10 +12951,10 @@ __metadata: languageName: node linkType: hard -"pathval@npm:^1.1.1": - version: 1.1.1 - resolution: "pathval@npm:1.1.1" - checksum: b50a4751068aa3a5428f5a0b480deecedc6f537666a3630a0c2ae2d5e7c0f4bf0ee77b48404441ec1220bef0c91625e6030b3d3cf5a32ab0d9764018d1d9dbb6 +"pathval@npm:^2.0.0": + version: 2.0.0 + resolution: "pathval@npm:2.0.0" + checksum: b91575bf9cdf01757afd7b5e521eb8a0b874a49bc972d08e0047cfea0cd3c019f5614521d4bc83d2855e3fcc331db6817dfd533dd8f3d90b16bc76fad2450fc1 languageName: node linkType: hard @@ -13230,13 +13114,13 @@ __metadata: linkType: hard "postcss@npm:^8.4.14": - version: 8.4.31 - resolution: "postcss@npm:8.4.31" + version: 8.4.32 + resolution: "postcss@npm:8.4.32" dependencies: - nanoid: "npm:^3.3.6" + nanoid: "npm:^3.3.7" picocolors: "npm:^1.0.0" source-map-js: "npm:^1.0.2" - checksum: 1a6653e72105907377f9d4f2cd341d8d90e3fde823a5ddea1e2237aaa56933ea07853f0f2758c28892a1d70c53bbaca200eb8b80f8ed55f13093003dbec5afa0 + checksum: 28084864122f29148e1f632261c408444f5ead0e0b9ea9bd9729d0468818ebe73fe5dc0075acd50c1365dbe639b46a79cba27d355ec857723a24bc9af0f18525 languageName: node linkType: hard @@ -13263,6 +13147,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^1.18.2 || ^2.0.0": + version: 2.8.8 + resolution: "prettier@npm:2.8.8" + bin: + prettier: bin-prettier.js + checksum: 00cdb6ab0281f98306cd1847425c24cbaaa48a5ff03633945ab4c701901b8e96ad558eb0777364ffc312f437af9b5a07d0f45346266e8245beaf6247b9c62b24 + languageName: node + linkType: hard + "pretty-bytes@npm:^5.3.0": version: 5.6.0 resolution: "pretty-bytes@npm:5.6.0" @@ -13284,6 +13177,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 + languageName: node + linkType: hard + "process-nextick-args@npm:^2.0.0, process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -13570,9 +13470,9 @@ __metadata: linkType: hard "regenerator-runtime@npm:^0.14.0": - version: 0.14.0 - resolution: "regenerator-runtime@npm:0.14.0" - checksum: 6c19495baefcf5fbb18a281b56a97f0197b5f219f42e571e80877f095320afac0bdb31dab8f8186858e6126950068c3f17a1226437881e3e70446ea66751897c + version: 0.14.1 + resolution: "regenerator-runtime@npm:0.14.1" + checksum: 5db3161abb311eef8c45bcf6565f4f378f785900ed3945acf740a9888c792f75b98ecb77f0775f3bf95502ff423529d23e94f41d80c8256e8fa05ed4b07cf471 languageName: node linkType: hard @@ -13673,7 +13573,7 @@ __metadata: languageName: node linkType: hard -"repeat-string@npm:^1.6.1": +"repeat-string@npm:^1.0.0, repeat-string@npm:^1.6.1": version: 1.6.1 resolution: "repeat-string@npm:1.6.1" checksum: 1b809fc6db97decdc68f5b12c4d1a671c8e3f65ec4a40c238bc5200e44e85bcc52a54f78268ab9c29fcf5fe4f1343e805420056d1f30fa9a9ee4c2d93e3cc6c0 @@ -13937,9 +13837,9 @@ __metadata: languageName: node linkType: hard -"rollup-plugin-visualizer@npm:5.11.0": - version: 5.11.0 - resolution: "rollup-plugin-visualizer@npm:5.11.0" +"rollup-plugin-visualizer@npm:5.12.0": + version: 5.12.0 + resolution: "rollup-plugin-visualizer@npm:5.12.0" dependencies: open: "npm:^8.4.0" picomatch: "npm:^2.3.1" @@ -13952,7 +13852,7 @@ __metadata: optional: true bin: rollup-plugin-visualizer: dist/bin/cli.js - checksum: 947238aa22706a47a4d3e8ce616855f0e5cb969ed9f61b9a268eaede0a86f461ecb38e27b4e6bf00f4b5e3f63677667f65e0d4af89a659a5160f74add1f192bb + checksum: 47358feb672291d6edcfd94197577c192a84c24cb644119425dae8241fb6f5a52556efd0c501f38b276c07534642a80c0885ef681babb474e83c7b5a3b475b84 languageName: node linkType: hard @@ -13988,12 +13888,10 @@ __metadata: languageName: node linkType: hard -"run-applescript@npm:^5.0.0": - version: 5.0.0 - resolution: "run-applescript@npm:5.0.0" - dependencies: - execa: "npm:^5.0.0" - checksum: d00c2dbfa5b2d774de7451194b8b125f40f65fc183de7d9dcae97f57f59433586d3c39b9001e111c38bfa24c3436c99df1bb4066a2a0c90d39a8c4cd6889af77 +"run-applescript@npm:^7.0.0": + version: 7.0.0 + resolution: "run-applescript@npm:7.0.0" + checksum: b02462454d8b182ad4117e5d4626e9e6782eb2072925c9fac582170b0627ae3c1ea92ee9b2df7daf84b5e9ffe14eb1cf5fb70bc44b15c8a0bfcdb47987e2410c languageName: node linkType: hard @@ -14097,11 +13995,12 @@ __metadata: linkType: hard "selfsigned@npm:^2.1.1": - version: 2.1.1 - resolution: "selfsigned@npm:2.1.1" + version: 2.4.1 + resolution: "selfsigned@npm:2.4.1" dependencies: + "@types/node-forge": "npm:^1.3.0" node-forge: "npm:^1" - checksum: 6005206e0d005448274aceceaded5195b944f67a42b72d212a6169d2e5f4bdc87c15a3fe45732c544db8c7175702091aaf95403ad6632585294a6ec8cca63638 + checksum: 52536623f1cfdeb2f8b9198377f2ce7931c677ea69421238d1dc1ea2983bbe258e56c19e7d1af87035cad7270f19b7e996eaab1212e724d887722502f68e17f2 languageName: node linkType: hard @@ -14340,7 +14239,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 @@ -14456,18 +14355,18 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "socks-proxy-agent@npm:7.0.0" +"socks-proxy-agent@npm:^8.0.1": + version: 8.0.2 + resolution: "socks-proxy-agent@npm:8.0.2" dependencies: - agent-base: "npm:^6.0.2" - debug: "npm:^4.3.3" - socks: "npm:^2.6.2" - checksum: 26c75d9c62a9ed3fd494df60e65e88da442f78e0d4bc19bfd85ac37bd2c67470d6d4bba5202e804561cda6674db52864c9e2a2266775f879bc8d89c1445a5f4c + agent-base: "npm:^7.0.2" + debug: "npm:^4.3.4" + socks: "npm:^2.7.1" + checksum: ea727734bd5b2567597aa0eda14149b3b9674bb44df5937bbb9815280c1586994de734d965e61f1dd45661183d7b41f115fb9e432d631287c9063864cfcc2ecc languageName: node linkType: hard -"socks@npm:^2.6.2": +"socks@npm:^2.7.1": version: 2.7.1 resolution: "socks@npm:2.7.1" dependencies: @@ -14726,10 +14625,10 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.0.1": - version: 3.4.3 - resolution: "std-env@npm:3.4.3" - checksum: 3087e9b2f6f9f40f1562b765c2d0768ad12f04a4d039fa5848e9e951263266b533590464e5d90e412680ec37e4febabf0c8fb3d15c4c7b8c5eb21ebcb09bf393 +"std-env@npm:^3.6.0": + version: 3.7.0 + resolution: "std-env@npm:3.7.0" + checksum: 6ee0cca1add3fd84656b0002cfbc5bfa20340389d9ba4720569840f1caa34bce74322aef4c93f046391583e50649d0cf81a5f8fe1d411e50b659571690a45f12 languageName: node linkType: hard @@ -14770,7 +14669,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -15103,15 +15002,15 @@ __metadata: languageName: node linkType: hard -"terser-webpack-plugin@npm:5.3.9, terser-webpack-plugin@npm:^5.3.7": - version: 5.3.9 - resolution: "terser-webpack-plugin@npm:5.3.9" +"terser-webpack-plugin@npm:5.3.10, terser-webpack-plugin@npm:^5.3.7": + version: 5.3.10 + resolution: "terser-webpack-plugin@npm:5.3.10" dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.17" + "@jridgewell/trace-mapping": "npm:^0.3.20" jest-worker: "npm:^27.4.5" schema-utils: "npm:^3.1.1" serialize-javascript: "npm:^6.0.1" - terser: "npm:^5.16.8" + terser: "npm:^5.26.0" peerDependencies: webpack: ^5.1.0 peerDependenciesMeta: @@ -15121,7 +15020,7 @@ __metadata: optional: true uglify-js: optional: true - checksum: 339737a407e034b7a9d4a66e31d84d81c10433e41b8eae2ca776f0e47c2048879be482a9aa08e8c27565a2a949bc68f6e07f451bf4d9aa347dd61b3d000f5353 + checksum: fb1c2436ae1b4e983be043fa0a3d355c047b16b68f102437d08c736d7960c001e7420e2f722b9d99ce0dc70ca26a68cc63c0b82bc45f5b48671142b352a9d938 languageName: node linkType: hard @@ -15138,9 +15037,9 @@ __metadata: languageName: node linkType: hard -"terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.16.8": - version: 5.22.0 - resolution: "terser@npm:5.22.0" +"terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.26.0": + version: 5.26.0 + resolution: "terser@npm:5.26.0" dependencies: "@jridgewell/source-map": "npm:^0.3.3" acorn: "npm:^8.8.2" @@ -15148,7 +15047,7 @@ __metadata: source-map-support: "npm:~0.5.20" bin: terser: bin/terser - checksum: e5407f9a143e7f9306f1b585b16dbb03df19b93318b55a26b542e12b74cc792dcf6961d9a2cab6778b20d7b591f498c200376d282a300cf9999ca40bccbc047c + checksum: 0282c5c065cbfa1e725d5609b99579252bc20b83cd1d75e8ab8b46d5da2c9d0fcfc453a12624f2d2d4c1240bfa0017a90fcf1e3b88258e5842fca1b0b82be8d8 languageName: node linkType: hard @@ -15240,13 +15139,6 @@ __metadata: languageName: node linkType: hard -"titleize@npm:^3.0.0": - version: 3.0.0 - resolution: "titleize@npm:3.0.0" - checksum: 71fbbeabbfb36ccd840559f67f21e356e1d03da2915b32d2ae1a60ddcc13a124be2739f696d2feb884983441d159a18649e8d956648d591bdad35c430a6b6d28 - languageName: node - linkType: hard - "to-absolute-glob@npm:^2.0.0": version: 2.0.2 resolution: "to-absolute-glob@npm:2.0.2" @@ -15374,15 +15266,15 @@ __metadata: languageName: node linkType: hard -"tsconfig-paths@npm:^3.14.2": - version: 3.14.2 - resolution: "tsconfig-paths@npm:3.14.2" +"tsconfig-paths@npm:^3.15.0": + version: 3.15.0 + resolution: "tsconfig-paths@npm:3.15.0" dependencies: "@types/json5": "npm:^0.0.29" json5: "npm:^1.0.2" minimist: "npm:^1.2.6" strip-bom: "npm:^3.0.0" - checksum: 17f23e98612a60cf23b80dc1d3b7b840879e41fcf603868fc3618a30f061ac7b463ef98cad8c28b68733b9bfe0cc40ffa2bcf29e94cf0d26e4f6addf7ac8527d + checksum: 2041beaedc6c271fc3bedd12e0da0cc553e65d030d4ff26044b771fac5752d0460944c0b5e680f670c2868c95c664a256cec960ae528888db6ded83524e33a14 languageName: node linkType: hard @@ -15505,7 +15397,7 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": +"type-detect@npm:4.0.8, type-detect@npm:^4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8" checksum: 5179e3b8ebc51fce1b13efb75fdea4595484433f9683bbc2dca6d99789dba4e602ab7922d2656f2ce8383987467f7770131d4a7f06a26287db0615d2f4c4ce7d @@ -15526,6 +15418,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: f4254070d9c3d83a6e573bcb95173008d73474ceadbbf620dd32d273940ca18734dff39c2b2480282df9afe5d1675ebed5499a00d791758748ea81f61a38961f + languageName: node + linkType: hard + "type-fest@npm:^3.0.0": version: 3.13.1 resolution: "type-fest@npm:3.13.1" @@ -15716,10 +15615,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~5.25.1": - version: 5.25.3 - resolution: "undici-types@npm:5.25.3" - checksum: 9a57f2dd6fecb2d0f7d9b86aa6f417609a0ffc73247a95aa25c078cf36cbbfe6c164b63b8dace7ad01126e6510f284c185b69c78356bb1d6b279f195acffcaf4 +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 0097779d94bc0fd26f0418b3a05472410408877279141ded2bd449167be1aed7ea5b76f756562cb3586a07f251b90799bab22d9019ceba49c037c76445f7cddd languageName: node linkType: hard @@ -15811,16 +15710,16 @@ __metadata: linkType: hard "universal-user-agent@npm:^6.0.0": - version: 6.0.0 - resolution: "universal-user-agent@npm:6.0.0" - checksum: 5092bbc80dd0d583cef0b62c17df0043193b74f425112ea6c1f69bc5eda21eeec7a08d8c4f793a277eb2202ffe9b44bec852fa3faff971234cd209874d1b79ef + version: 6.0.1 + resolution: "universal-user-agent@npm:6.0.1" + checksum: fdc8e1ae48a05decfc7ded09b62071f571c7fe0bd793d700704c80cea316101d4eac15cc27ed2bb64f4ce166d2684777c3198b9ab16034f547abea0d3aa1c93c languageName: node linkType: hard "universalify@npm:^2.0.0": - version: 2.0.0 - resolution: "universalify@npm:2.0.0" - checksum: 2406a4edf4a8830aa6813278bab1f953a8e40f2f63a37873ffa9a3bc8f9745d06cc8e88f3572cb899b7e509013f7f6fcc3e37e8a6d914167a5381d8440518c44 + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: ecd8469fe0db28e7de9e5289d32bd1b6ba8f7183db34f3bfc4ca53c49891c2d6aa05f3fb3936a81285a905cc509fb641a0c3fc131ec786167eff41236ae32e60 languageName: node linkType: hard @@ -15841,13 +15740,6 @@ __metadata: languageName: node linkType: hard -"untildify@npm:^4.0.0": - version: 4.0.0 - resolution: "untildify@npm:4.0.0" - checksum: 39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 - languageName: node - linkType: hard - "upath@npm:^1.1.1, upath@npm:^1.2.0": version: 1.2.0 resolution: "upath@npm:1.2.0" @@ -16126,13 +16018,13 @@ __metadata: languageName: node linkType: hard -"vue@npm:2.7.15, vue@npm:^2.6.10": - version: 2.7.15 - resolution: "vue@npm:2.7.15" +"vue@npm:2.7.16, vue@npm:^2.6.10": + version: 2.7.16 + resolution: "vue@npm:2.7.16" dependencies: - "@vue/compiler-sfc": "npm:2.7.15" + "@vue/compiler-sfc": "npm:2.7.16" csstype: "npm:^3.1.0" - checksum: 928575f5eee51b99652cfcba0dfb0c924e9571ed45bff9a45abdaaaeb7d55c45339094ecc77cfcf884b40e51c6681cc49699b178f7363af0ca7f88618f7f4ec1 + checksum: 0371f7bfafd9c6f58ffee6f291fc4ca045033f163e090d8afdfb7550fb9ba71770fe673941083038c88b4a45effe45bb8560c235dc3953c1ff8596f0ad4e4d88 languageName: node linkType: hard @@ -16369,17 +16261,21 @@ __metadata: languageName: node linkType: hard -"webpackbar@npm:5.0.2": - version: 5.0.2 - resolution: "webpackbar@npm:5.0.2" +"webpackbar@npm:6.0.0": + version: 6.0.0 + resolution: "webpackbar@npm:6.0.0" dependencies: - chalk: "npm:^4.1.0" - consola: "npm:^2.15.3" + ansi-escapes: "npm:^4.3.2" + chalk: "npm:^4.1.2" + consola: "npm:^3.2.3" + figures: "npm:^3.2.0" + markdown-table: "npm:^2.0.0" pretty-time: "npm:^1.1.0" - std-env: "npm:^3.0.1" + std-env: "npm:^3.6.0" + wrap-ansi: "npm:^7.0.0" peerDependencies: webpack: 3 || 4 || 5 - checksum: 059d5bed5c52a40636e29271285de4a8f9ac2ebef8941b896fc3fb858df2bf6f7c2fdedab80d6637626b91e03686c553ff644af47deb5c44fedf32edf558396f + checksum: aa26c2dff6c2384f39b77e57375af52a65fbd3c54b9a5a8e1c53e79b0c25eaabc8602469ec3742bf93f7d178f5a96e3d6bd4fcbb256808e730eecb91091df466 languageName: node linkType: hard @@ -16480,7 +16376,7 @@ __metadata: languageName: node linkType: hard -"which@npm:^2.0.1, which@npm:^2.0.2": +"which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" dependencies: @@ -16491,6 +16387,17 @@ __metadata: languageName: node linkType: hard +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + "wicg-inert@npm:^3.0.0": version: 3.1.2 resolution: "wicg-inert@npm:3.1.2" @@ -16498,15 +16405,6 @@ __metadata: languageName: node linkType: hard -"wide-align@npm:^1.1.5": - version: 1.1.5 - resolution: "wide-align@npm:1.1.5" - dependencies: - string-width: "npm:^1.0.2 || 2 || 3 || 4" - checksum: d5f8027b9a8255a493a94e4ec1b74a27bff6679d5ffe29316a3215e4712945c84ef73ca4045c7e20ae7d0c72f5f57f296e04a4928e773d4276a2f1222e4c2e99 - languageName: node - linkType: hard - "wildcard@npm:^2.0.0": version: 2.0.1 resolution: "wildcard@npm:2.0.1" @@ -16795,8 +16693,8 @@ __metadata: linkType: hard "ws@npm:^8.13.0": - version: 8.14.2 - resolution: "ws@npm:8.14.2" + version: 8.15.1 + resolution: "ws@npm:8.15.1" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -16805,7 +16703,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 815ff01d9bc20a249b2228825d9739268a03a4408c2e0b14d49b0e2ae89d7f10847e813b587ba26992bdc33e9d03bed131e4cae73ff996baf789d53e99c31186 + checksum: 746a3102d43e8df7b09f5814bec858f12d10185a7abd655537f3291b687d440bb80fc9d1e082f8dee42d4d74307f78a96810e18a2c8e13053b003c6608c1c648 languageName: node linkType: hard