diff --git a/.github/workflows/cast_deployment.yaml b/.github/workflows/cast_deployment.yaml index 3b5955dfae..9733c5ec59 100644 --- a/.github/workflows/cast_deployment.yaml +++ b/.github/workflows/cast_deployment.yaml @@ -21,7 +21,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 with: ref: dev @@ -57,7 +57,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 with: ref: master diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 61290c36bc..4097753114 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Setup Node uses: actions/setup-node@v4.0.2 with: @@ -58,7 +58,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Setup Node uses: actions/setup-node@v4.0.2 with: @@ -76,7 +76,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Setup Node uses: actions/setup-node@v4.0.2 with: @@ -89,7 +89,7 @@ jobs: env: IS_TEST: "true" - name: Upload bundle stats - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.2 with: name: frontend-bundle-stats path: build/stats/*.json @@ -100,7 +100,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Setup Node uses: actions/setup-node@v4.0.2 with: @@ -113,7 +113,7 @@ jobs: env: IS_TEST: "true" - name: Upload bundle stats - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.2 with: name: supervisor-bundle-stats path: build/stats/*.json diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ea1bf0d2d1..b6d12250e9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/demo_deployment.yaml b/.github/workflows/demo_deployment.yaml index accbe3c9df..2bf4fb3a27 100644 --- a/.github/workflows/demo_deployment.yaml +++ b/.github/workflows/demo_deployment.yaml @@ -22,7 +22,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 with: ref: dev @@ -58,7 +58,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 with: ref: master diff --git a/.github/workflows/design_deployment.yaml b/.github/workflows/design_deployment.yaml index 64168418dd..9708d4f1d4 100644 --- a/.github/workflows/design_deployment.yaml +++ b/.github/workflows/design_deployment.yaml @@ -16,7 +16,7 @@ jobs: url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Setup Node uses: actions/setup-node@v4.0.2 diff --git a/.github/workflows/design_preview.yaml b/.github/workflows/design_preview.yaml index 19b73c2609..3a4817eaa0 100644 --- a/.github/workflows/design_preview.yaml +++ b/.github/workflows/design_preview.yaml @@ -21,7 +21,7 @@ jobs: if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview') steps: - name: Check out files from GitHub - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Setup Node uses: actions/setup-node@v4.0.2 diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index d3d8e89246..88e0ed9660 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -20,7 +20,7 @@ jobs: contents: write steps: - name: Checkout the repository - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v5 @@ -57,14 +57,14 @@ jobs: run: tar -czvf translations.tar.gz translations - name: Upload build artifacts - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.2 with: name: wheels path: dist/home_assistant_frontend*.whl if-no-files-found: error - name: Upload translations - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.2 with: name: translations path: translations.tar.gz diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fe7faf0590..b58d1fb4f5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,7 +23,7 @@ jobs: contents: write # Required to upload release assets steps: - name: Checkout the repository - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Verify version uses: home-assistant/actions/helpers/verify-version@master diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml index 04894b0770..403b258621 100644 --- a/.github/workflows/translations.yaml +++ b/.github/workflows/translations.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the repository - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Upload Translations run: | diff --git a/build-scripts/gulp/fetch-nightly-translations.js b/build-scripts/gulp/fetch-nightly-translations.js index 52da690152..a19409b076 100644 --- a/build-scripts/gulp/fetch-nightly-translations.js +++ b/build-scripts/gulp/fetch-nightly-translations.js @@ -9,7 +9,7 @@ import gulp from "gulp"; import jszip from "jszip"; import path from "path"; import process from "process"; -import tar from "tar"; +import { extract } from "tar"; const MAX_AGE = 24; // hours const OWNER = "home-assistant"; @@ -156,7 +156,7 @@ gulp.task("fetch-nightly-translations", async function () { console.log("Unpacking downloaded translations..."); const zip = await jszip.loadAsync(downloadResponse.data); await deleteCurrent; - const extractStream = zip.file(/.*/)[0].nodeStream().pipe(tar.extract()); + const extractStream = zip.file(/.*/)[0].nodeStream().pipe(extract()); await new Promise((resolve, reject) => { extractStream.on("close", resolve).on("error", reject); }); diff --git a/build-scripts/gulp/translations.js b/build-scripts/gulp/translations.js index fd4cccc013..7b670ccc6b 100755 --- a/build-scripts/gulp/translations.js +++ b/build-scripts/gulp/translations.js @@ -1,92 +1,76 @@ -import { createHash } from "crypto"; -import { deleteSync } from "del"; -import { mkdirSync, readdirSync, readFileSync, renameSync } from "fs"; -import { writeFile } from "node:fs/promises"; +import { deleteAsync } from "del"; +import { glob } from "glob"; import gulp from "gulp"; -import flatmap from "gulp-flatmap"; -import transform from "gulp-json-transform"; import merge from "gulp-merge-json"; import rename from "gulp-rename"; -import path from "path"; -import vinylBuffer from "vinyl-buffer"; -import source from "vinyl-source-stream"; +import { createHash } from "node:crypto"; +import { mkdir, readFile } from "node:fs/promises"; +import { basename, join } from "node:path"; +import { Transform } from "node:stream"; +import { finished } from "node:stream/promises"; import env from "../env.cjs"; import paths from "../paths.cjs"; -import { mapFiles } from "../util.cjs"; import "./fetch-nightly-translations.js"; const inFrontendDir = "translations/frontend"; const inBackendDir = "translations/backend"; const workDir = "build/translations"; -const fullDir = workDir + "/full"; -const coreDir = workDir + "/core"; -const outDir = workDir + "/output"; +const outDir = join(workDir, "output"); +const EN_SRC = join(paths.translations_src, "en.json"); + let mergeBackend = false; gulp.task( "translations-enable-merge-backend", - gulp.parallel((done) => { + gulp.parallel(async () => { mergeBackend = true; - done(); }, "allow-setup-fetch-nightly-translations") ); -// Panel translations which should be split from the core translations. -const TRANSLATION_FRAGMENTS = Object.keys( - JSON.parse( - readFileSync( - path.resolve(paths.polymer_dir, "src/translations/en.json"), - "utf-8" - ) - ).ui.panel -); +// Transform stream to apply a function on Vinyl JSON files (buffer mode only). +// The provided function can either return a new object, or an array of +// [object, subdirectory] pairs for fragmentizing the JSON. +class CustomJSON extends Transform { + constructor(func, reviver = null) { + super({ objectMode: true }); + this._func = func; + this._reviver = reviver; + } -function recursiveFlatten(prefix, data) { - let output = {}; - Object.keys(data).forEach((key) => { - if (typeof data[key] === "object") { - output = { - ...output, - ...recursiveFlatten(prefix + key + ".", data[key]), - }; + async _transform(file, _, callback) { + try { + let obj = JSON.parse(file.contents.toString(), this._reviver); + if (this._func) obj = this._func(obj, file.path); + for (const [outObj, dir] of Array.isArray(obj) ? obj : [[obj, ""]]) { + const outFile = file.clone({ contents: false }); + outFile.contents = Buffer.from(JSON.stringify(outObj)); + outFile.dirname += `/${dir}`; + this.push(outFile); + } + callback(null); + } catch (err) { + callback(err); + } + } +} + +// Utility to flatten object keys to single level using separator +const flatten = (data, prefix = "", sep = ".") => { + const output = {}; + for (const [key, value] of Object.entries(data)) { + if (typeof value === "object") { + Object.assign(output, flatten(value, prefix + key + sep, sep)); } else { - output[prefix + key] = data[key]; + output[prefix + key] = value; } - }); + } return output; -} +}; -function flatten(data) { - return recursiveFlatten("", data); -} - -function emptyFilter(data) { - const newData = {}; - Object.keys(data).forEach((key) => { - if (data[key]) { - if (typeof data[key] === "object") { - newData[key] = emptyFilter(data[key]); - } else { - newData[key] = data[key]; - } - } - }); - return newData; -} - -function recursiveEmpty(data) { - const newData = {}; - Object.keys(data).forEach((key) => { - if (data[key]) { - if (typeof data[key] === "object") { - newData[key] = recursiveEmpty(data[key]); - } else { - newData[key] = "TRANSLATED"; - } - } - }); - return newData; -} +// Filter functions that can be passed directly to JSON.parse() +const emptyReviver = (_key, value) => value || undefined; +const testReviver = (_key, value) => + value && typeof value === "string" ? "TRANSLATED" : value; /** * Replace Lokalise key placeholders with their actual values. @@ -95,60 +79,44 @@ function recursiveEmpty(data) { * be included in src/translations/en.json, but still be usable while * developing locally. * - * @link https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing + * @link https://docs.lokalise.com/en/articles/1400528-key-referencing */ -const re_key_reference = /\[%key:([^%]+)%\]/; -function lokaliseTransform(data, original, file) { +const KEY_REFERENCE = /\[%key:([^%]+)%\]/; +const lokaliseTransform = (data, path, original = data) => { const output = {}; - Object.entries(data).forEach(([key, value]) => { - if (value instanceof Object) { - output[key] = lokaliseTransform(value, original, file); + for (const [key, value] of Object.entries(data)) { + if (typeof value === "object") { + output[key] = lokaliseTransform(value, path, original); } else { - output[key] = value.replace(re_key_reference, (_match, lokalise_key) => { + output[key] = value.replace(KEY_REFERENCE, (_match, lokalise_key) => { const replace = lokalise_key.split("::").reduce((tr, k) => { if (!tr) { - throw Error( - `Invalid key placeholder ${lokalise_key} in ${file.path}` - ); + throw Error(`Invalid key placeholder ${lokalise_key} in ${path}`); } return tr[k]; }, original); if (typeof replace !== "string") { - throw Error( - `Invalid key placeholder ${lokalise_key} in ${file.path}` - ); + throw Error(`Invalid key placeholder ${lokalise_key} in ${path}`); } return replace; }); } - }); + } return output; -} +}; -gulp.task("clean-translations", async () => deleteSync([workDir])); +gulp.task("clean-translations", () => deleteAsync([workDir])); -gulp.task("ensure-translations-build-dir", async () => { - mkdirSync(workDir, { recursive: true }); -}); +const makeWorkDir = () => mkdir(workDir, { recursive: true }); -gulp.task("create-test-metadata", () => - env.isProdBuild() - ? Promise.resolve() - : writeFile( - workDir + "/testMetadata.json", - JSON.stringify({ test: { nativeName: "Test" } }) - ) -); - -gulp.task("create-test-translation", () => +const createTestTranslation = () => env.isProdBuild() ? Promise.resolve() : gulp - .src(path.join(paths.translations_src, "en.json")) - .pipe(transform((data, _file) => recursiveEmpty(data))) + .src(EN_SRC) + .pipe(new CustomJSON(null, testReviver)) .pipe(rename("test.json")) - .pipe(gulp.dest(workDir)) -); + .pipe(gulp.dest(workDir)); /** * This task will build a master translation file, to be used as the base for @@ -159,279 +127,171 @@ gulp.task("create-test-translation", () => * project is buildable immediately after merging new translation keys, since * the Lokalise update to translations/en.json will not happen immediately. */ -gulp.task("build-master-translation", () => { - const src = [path.join(paths.translations_src, "en.json")]; - - if (mergeBackend) { - src.push(path.join(inBackendDir, "en.json")); - } - - return gulp - .src(src) - .pipe(transform((data, file) => lokaliseTransform(data, data, file))) +const createMasterTranslation = () => + gulp + .src([EN_SRC, ...(mergeBackend ? [`${inBackendDir}/en.json`] : [])]) + .pipe(new CustomJSON(lokaliseTransform)) .pipe( merge({ fileName: "en.json", + jsonSpace: undefined, }) ) - .pipe(gulp.dest(fullDir)); -}); + .pipe(gulp.dest(workDir)); -gulp.task("build-merged-translations", () => - gulp - .src([ - inFrontendDir + "/*.json", - "!" + inFrontendDir + "/en.json", - ...(env.isProdBuild() ? [] : [workDir + "/test.json"]), - ]) - .pipe(transform((data, file) => lokaliseTransform(data, data, file))) - .pipe( - flatmap((stream, file) => { - // For each language generate a merged json file. It begins with the master - // translation as a failsafe for untranslated strings, and merges all parent - // tags into one file for each specific subtag - // - // TODO: This is a naive interpretation of BCP47 that should be improved. - // Will be OK for now as long as we don't have anything more complicated - // than a base translation + region. - const tr = path.basename(file.history[0], ".json"); - const subtags = tr.split("-"); - const src = [fullDir + "/en.json"]; - for (let i = 1; i <= subtags.length; i++) { - const lang = subtags.slice(0, i).join("-"); - if (lang === "test") { - src.push(workDir + "/test.json"); - } else if (lang !== "en") { - src.push(inFrontendDir + "/" + lang + ".json"); - if (mergeBackend) { - src.push(inBackendDir + "/" + lang + ".json"); - } - } - } - return gulp - .src(src, { allowEmpty: true }) - .pipe(transform((data) => emptyFilter(data))) - .pipe( - merge({ - fileName: tr + ".json", - }) - ) - .pipe(gulp.dest(fullDir)); - }) - ) -); +const FRAGMENTS = ["base"]; -let taskName; +const toggleSupervisorFragment = async () => { + FRAGMENTS[0] = "supervisor"; +}; -const splitTasks = []; -TRANSLATION_FRAGMENTS.forEach((fragment) => { - taskName = "build-translation-fragment-" + fragment; - gulp.task(taskName, () => - // Return only the translations for this fragment. - gulp - .src(fullDir + "/*.json") - .pipe( - transform((data) => ({ - ui: { - panel: { - [fragment]: data.ui.panel[fragment], - }, - }, - })) - ) - .pipe(gulp.dest(workDir + "/" + fragment)) - ); - splitTasks.push(taskName); -}); +const panelFragment = (fragment) => + fragment !== "base" && fragment !== "supervisor"; -taskName = "build-translation-core"; -gulp.task(taskName, () => - // Remove the fragment translations from the core translation. - gulp - .src(fullDir + "/*.json") - .pipe( - transform((data, _file) => { - TRANSLATION_FRAGMENTS.forEach((fragment) => { - delete data.ui.panel[fragment]; - }); - delete data.supervisor; - return data; - }) - ) - .pipe(gulp.dest(coreDir)) -); +const HASHES = new Map(); -splitTasks.push(taskName); - -gulp.task("build-flattened-translations", () => - // Flatten the split versions of our translations, and move them into outDir - gulp - .src( - TRANSLATION_FRAGMENTS.map( - (fragment) => workDir + "/" + fragment + "/*.json" - ).concat(coreDir + "/*.json"), - { base: workDir } - ) - .pipe( - transform((data) => - // Polymer.AppLocalizeBehavior requires flattened json - flatten(data) - ) - ) - .pipe( - rename((filePath) => { - if (filePath.dirname === "core") { - filePath.dirname = ""; - } - // In dev we create the file with the fake hash in the filename - if (!env.isProdBuild()) { - filePath.basename += "-dev"; - } - }) - ) - .pipe(gulp.dest(outDir)) -); - -const fingerprints = {}; - -gulp.task("build-translation-fingerprints", () => { - // Fingerprint full file of each language - const files = readdirSync(fullDir); - - for (let i = 0; i < files.length; i++) { - fingerprints[files[i].split(".")[0]] = { - // In dev we create fake hashes - hash: env.isProdBuild() - ? createHash("md5") - .update(readFileSync(path.join(fullDir, files[i]), "utf-8")) - .digest("hex") - : "dev", - }; +const createTranslations = async () => { + // Parse and store the master to avoid repeating this for each locale, then + // add the panel fragments when processing the app. + const enMaster = JSON.parse(await readFile(`${workDir}/en.json`, "utf-8")); + if (FRAGMENTS[0] === "base") { + FRAGMENTS.push(...Object.keys(enMaster.ui.panel)); } - // In dev we create the file with the fake hash in the filename - if (env.isProdBuild()) { - mapFiles(outDir, ".json", (filename) => { - const parsed = path.parse(filename); + // The downstream pipeline is setup first. It hashes the merged data for + // each locale, then fragmentizes and flattens the data for final output. + const translationFiles = await glob([ + `${inFrontendDir}/!(en).json`, + ...(env.isProdBuild() ? [] : [`${workDir}/test.json`]), + ]); + const hashStream = new Transform({ + objectMode: true, + transform: async (file, _, callback) => { + const hash = env.isProdBuild() + ? createHash("md5").update(file.contents).digest("hex") + : "dev"; + HASHES.set(file.stem, hash); + file.stem += `-${hash}`; + callback(null, file); + }, + }).setMaxListeners(translationFiles.length + 1); + const fragmentsStream = hashStream + .pipe( + new CustomJSON((data) => + FRAGMENTS.map((fragment) => { + switch (fragment) { + case "base": + // Remove the panels and supervisor to create the base translations + return [ + flatten({ + ...data, + ui: { ...data.ui, panel: undefined }, + supervisor: undefined, + }), + "", + ]; + case "supervisor": + // Supervisor key is at the top level + return [flatten(data.supervisor), ""]; + default: + // Create a fragment with only the given panel + return [ + flatten(data.ui.panel[fragment], `ui.panel.${fragment}.`), + fragment, + ]; + } + }) + ) + ) + .pipe(gulp.dest(outDir)); - // nl.json -> nl-.json - if (!(parsed.name in fingerprints)) { - throw new Error(`Unable to find hash for ${filename}`); + // Send the English master downstream first, then for each other locale + // generate merged JSON data to continue piping. It begins with the master + // translation as a failsafe for untranslated strings, and merges all parent + // tags into one file for each specific subtag + // + // TODO: This is a naive interpretation of BCP47 that should be improved. + // Will be OK for now as long as we don't have anything more complicated + // than a base translation + region. + gulp.src(`${workDir}/en.json`).pipe(hashStream, { end: false }); + const mergesFinished = []; + for (const translationFile of translationFiles) { + const locale = basename(translationFile, ".json"); + const subtags = locale.split("-"); + const mergeFiles = []; + for (let i = 1; i <= subtags.length; i++) { + const lang = subtags.slice(0, i).join("-"); + if (lang === "test") { + mergeFiles.push(`${workDir}/test.json`); + } else if (lang !== "en") { + mergeFiles.push(`${inFrontendDir}/${lang}.json`); + if (mergeBackend) { + mergeFiles.push(`${inBackendDir}/${lang}.json`); + } } - - renameSync( - filename, - `${parsed.dir}/${parsed.name}-${fingerprints[parsed.name].hash}${ - parsed.ext - }` - ); - }); + } + const mergeStream = gulp.src(mergeFiles, { allowEmpty: true }).pipe( + merge({ + fileName: `${locale}.json`, + startObj: enMaster, + jsonReviver: emptyReviver, + jsonSpace: undefined, + }) + ); + mergesFinished.push(finished(mergeStream)); + mergeStream.pipe(hashStream, { end: false }); } - const stream = source("translationFingerprints.json"); - stream.write(JSON.stringify(fingerprints)); - process.nextTick(() => stream.end()); - return stream.pipe(vinylBuffer()).pipe(gulp.dest(workDir)); -}); + // Wait for all merges to finish, then it's safe to end writing to the + // downstream pipeline and wait for all fragments to finish writing. + await Promise.all(mergesFinished); + hashStream.end(); + await finished(fragmentsStream); +}; -gulp.task("build-translation-fragment-supervisor", () => +const writeTranslationMetaData = () => gulp - .src(fullDir + "/*.json") - .pipe(transform((data) => data.supervisor)) + .src([`${paths.translations_src}/translationMetadata.json`]) .pipe( - rename((filePath) => { - // In dev we create the file with the fake hash in the filename + new CustomJSON((meta) => { + // Add the test translation in development. if (!env.isProdBuild()) { - filePath.basename += "-dev"; + meta.test = { nativeName: "Test" }; } - }) - ) - .pipe(gulp.dest(workDir + "/supervisor")) -); - -gulp.task("build-translation-flatten-supervisor", () => - gulp - .src(workDir + "/supervisor/*.json") - .pipe( - transform((data) => - // Polymer.AppLocalizeBehavior requires flattened json - flatten(data) - ) - ) - .pipe(gulp.dest(outDir)) -); - -gulp.task("build-translation-write-metadata", () => - gulp - .src([ - path.join(paths.translations_src, "translationMetadata.json"), - ...(env.isProdBuild() ? [] : [workDir + "/testMetadata.json"]), - workDir + "/translationFingerprints.json", - ]) - .pipe(merge({})) - .pipe( - transform((data) => { - const newData = {}; - Object.entries(data).forEach(([key, value]) => { - // Filter out translations without native name. - if (value.nativeName) { - newData[key] = value; - } else { + // Filter out locales without a native name, and add the hashes. + for (const locale of Object.keys(meta)) { + if (!meta[locale].nativeName) { + meta[locale] = undefined; console.warn( - `Skipping language ${key}. Native name was not translated.` + `Skipping locale ${locale} because native name is not translated.` ); + } else { + meta[locale].hash = HASHES.get(locale); } - }); - return newData; + } + return { + fragments: FRAGMENTS.filter(panelFragment), + translations: meta, + }; }) ) - .pipe( - transform((data) => ({ - fragments: TRANSLATION_FRAGMENTS, - translations: data, - })) - ) - .pipe(rename("translationMetadata.json")) - .pipe(gulp.dest(workDir)) -); - -gulp.task( - "create-translations", - gulp.series( - gulp.parallel("create-test-metadata", "create-test-translation"), - "build-master-translation", - "build-merged-translations", - gulp.parallel(...splitTasks), - "build-flattened-translations" - ) -); + .pipe(gulp.dest(workDir)); gulp.task( "build-translations", gulp.series( gulp.parallel( "fetch-nightly-translations", - gulp.series("clean-translations", "ensure-translations-build-dir") + gulp.series("clean-translations", makeWorkDir) ), - "create-translations", - "build-translation-fingerprints", - "build-translation-write-metadata" + createTestTranslation, + createMasterTranslation, + createTranslations, + writeTranslationMetaData ) ); gulp.task( "build-supervisor-translations", - gulp.series( - gulp.parallel( - "fetch-nightly-translations", - gulp.series("clean-translations", "ensure-translations-build-dir") - ), - gulp.parallel("create-test-metadata", "create-test-translation"), - "build-master-translation", - "build-merged-translations", - "build-translation-fragment-supervisor", - "build-translation-flatten-supervisor", - "build-translation-fingerprints", - "build-translation-write-metadata" - ) + gulp.series(toggleSupervisorFragment, "build-translations") ); diff --git a/build-scripts/gulp/webpack.js b/build-scripts/gulp/webpack.js index f55d77f345..51f062f316 100644 --- a/build-scripts/gulp/webpack.js +++ b/build-scripts/gulp/webpack.js @@ -99,7 +99,7 @@ gulp.task("webpack-watch-app", () => { ).watch({ poll: isWsl }, doneHandler()); gulp.watch( path.join(paths.translations_src, "en.json"), - gulp.series("create-translations", "copy-translations-app") + gulp.series("build-translations", "copy-translations-app") ); }); diff --git a/build-scripts/util.cjs b/build-scripts/util.cjs deleted file mode 100644 index 23efdfb229..0000000000 --- a/build-scripts/util.cjs +++ /dev/null @@ -1,16 +0,0 @@ -const path = require("path"); -const fs = require("fs"); - -// Helper function to map recursively over files in a folder and it's subfolders -module.exports.mapFiles = function mapFiles(startPath, filter, mapFunc) { - const files = fs.readdirSync(startPath); - for (let i = 0; i < files.length; i++) { - const filename = path.join(startPath, files[i]); - const stat = fs.lstatSync(filename); - if (stat.isDirectory()) { - mapFiles(filename, filter, mapFunc); - } else if (filename.indexOf(filter) >= 0) { - mapFunc(filename); - } - } -}; diff --git a/build-scripts/webpack.cjs b/build-scripts/webpack.cjs index b08d3b2eeb..0679e3e2ba 100644 --- a/build-scripts/webpack.cjs +++ b/build-scripts/webpack.cjs @@ -10,6 +10,7 @@ const WebpackBar = require("webpackbar"); const { TransformAsyncModulesPlugin, } = require("transform-async-modules-webpack-plugin"); +const { dependencies } = require("../package.json"); const paths = require("./paths.cjs"); const bundle = require("./bundle.cjs"); @@ -156,7 +157,10 @@ const createWebpackConfig = ({ transform: (stats) => JSON.stringify(filterStats(stats)), }), !latestBuild && - new TransformAsyncModulesPlugin({ browserslistEnv: "legacy" }), + new TransformAsyncModulesPlugin({ + browserslistEnv: "legacy", + runtime: { version: dependencies["@babel/runtime"] }, + }), ].filter(Boolean), resolve: { extensions: [".ts", ".js", ".json"], diff --git a/demo/src/stubs/energy.ts b/demo/src/stubs/energy.ts index b459a9f95c..57b07d0968 100644 --- a/demo/src/stubs/energy.ts +++ b/demo/src/stubs/energy.ts @@ -1,4 +1,4 @@ -import { format, startOfToday, startOfTomorrow } from "date-fns/esm"; +import { format, startOfToday, startOfTomorrow } from "date-fns"; import { EnergyInfo, EnergyPreferences, diff --git a/gallery/src/pages/components/ha-selector.ts b/gallery/src/pages/components/ha-selector.ts index 3824d9bb18..0fb6d83263 100644 --- a/gallery/src/pages/components/ha-selector.ts +++ b/gallery/src/pages/components/ha-selector.ts @@ -161,12 +161,14 @@ const LABELS: LabelRegistryEntry[] = [ name: "Energy", icon: null, color: "yellow", + description: null, }, { label_id: "entertainment", name: "Entertainment", icon: "mdi:popcorn", color: "blue", + description: null, }, ]; diff --git a/gallery/src/pages/lovelace/tile-card.ts b/gallery/src/pages/lovelace/tile-card.ts index 62ab5abd23..58c5ad77bd 100644 --- a/gallery/src/pages/lovelace/tile-card.ts +++ b/gallery/src/pages/lovelace/tile-card.ts @@ -2,6 +2,7 @@ import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { customElement, query } from "lit/decorators"; import { CoverEntityFeature } from "../../../../src/data/cover"; import { LightColorMode } from "../../../../src/data/light"; +import { LockEntityFeature } from "../../../../src/data/lock"; import { VacuumEntityFeature } from "../../../../src/data/vacuum"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; @@ -20,6 +21,11 @@ const ENTITIES = [ getEntity("light", "unavailable", "unavailable", { friendly_name: "Unavailable entity", }), + getEntity("lock", "front_door", "locked", { + friendly_name: "Front Door Lock", + device_class: "lock", + supported_features: LockEntityFeature.OPEN, + }), getEntity("climate", "thermostat", "heat", { current_temperature: 73, min_temp: 45, @@ -138,6 +144,24 @@ const CONFIGS = [ - type: "color-temp" `, }, + { + heading: "Lock commands feature", + config: ` +- type: tile + entity: lock.front_door + features: + - type: "lock-commands" + `, + }, + { + heading: "Lock open door feature", + config: ` +- type: tile + entity: lock.front_door + features: + - type: "lock-open-door" + `, + }, { heading: "Vacuum commands feature", config: ` diff --git a/gallery/src/pages/misc/integration-card.ts b/gallery/src/pages/misc/integration-card.ts index ca1e83c0b6..72a99c7c28 100644 --- a/gallery/src/pages/misc/integration-card.ts +++ b/gallery/src/pages/misc/integration-card.ts @@ -36,6 +36,8 @@ const createConfigEntry = ( pref_disable_new_entities: false, pref_disable_polling: false, reason: null, + error_reason_translation_key: null, + error_reason_translation_placeholders: null, ...override, }); diff --git a/gulpfile.js b/gulpfile.js index 6178d2779d..45e0680504 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,4 +1,7 @@ import { globIterate } from "glob"; +import { availableParallelism } from "node:os"; + +process.env.UV_THREADPOOL_SIZE = availableParallelism(); const gulpImports = []; diff --git a/package.json b/package.json index 95e64ad94f..583d05fc24 100644 --- a/package.json +++ b/package.json @@ -25,15 +25,15 @@ "license": "Apache-2.0", "type": "module", "dependencies": { - "@babel/runtime": "7.24.1", + "@babel/runtime": "7.24.4", "@braintree/sanitize-url": "7.0.1", - "@codemirror/autocomplete": "6.15.0", - "@codemirror/commands": "6.3.3", + "@codemirror/autocomplete": "6.16.0", + "@codemirror/commands": "6.5.0", "@codemirror/language": "6.10.1", - "@codemirror/legacy-modes": "6.3.3", + "@codemirror/legacy-modes": "6.4.0", "@codemirror/search": "6.5.6", "@codemirror/state": "6.4.1", - "@codemirror/view": "6.26.1", + "@codemirror/view": "6.26.3", "@egjs/hammerjs": "2.0.17", "@formatjs/intl-datetimeformat": "6.12.3", "@formatjs/intl-displaynames": "6.6.6", @@ -81,7 +81,7 @@ "@material/mwc-top-app-bar": "0.27.0", "@material/mwc-top-app-bar-fixed": "0.27.0", "@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0", - "@material/web": "=1.3.0", + "@material/web": "1.4.1", "@mdi/js": "7.4.47", "@mdi/svg": "7.4.47", "@polymer/paper-item": "3.0.1", @@ -89,8 +89,8 @@ "@polymer/paper-tabs": "3.1.0", "@polymer/polymer": "3.5.1", "@thomasloven/round-slider": "0.6.0", - "@vaadin/combo-box": "24.3.10", - "@vaadin/vaadin-themable-mixin": "24.3.10", + "@vaadin/combo-box": "24.3.11", + "@vaadin/vaadin-themable-mixin": "24.3.11", "@vibrant/color": "3.2.1-alpha.1", "@vibrant/core": "3.2.1-alpha.1", "@vibrant/quantizer-mmcq": "3.2.1-alpha.1", @@ -101,17 +101,17 @@ "chart.js": "4.4.2", "color-name": "2.0.0", "comlink": "4.4.1", - "core-js": "3.36.1", + "core-js": "3.37.0", "cropperjs": "1.6.1", - "date-fns": "2.30.0", - "date-fns-tz": "2.0.1", + "date-fns": "3.6.0", + "date-fns-tz": "3.1.3", "deep-clone-simple": "1.1.1", "deep-freeze": "0.0.1", - "element-internals-polyfill": "1.3.10", + "element-internals-polyfill": "1.3.11", "fuse.js": "7.0.0", "google-timezones-json": "1.2.0", "hls.js": "patch:hls.js@npm%3A1.5.7#~/.yarn/patches/hls.js-npm-1.5.7-f5bbd3d060.patch", - "home-assistant-js-websocket": "9.2.1", + "home-assistant-js-websocket": "9.3.0", "idb-keyval": "6.2.1", "intl-messageformat": "10.5.11", "js-yaml": "4.1.0", @@ -119,7 +119,7 @@ "leaflet-draw": "1.0.4", "lit": "2.8.0", "luxon": "3.4.4", - "marked": "12.0.1", + "marked": "12.0.2", "memoize-one": "6.0.0", "node-vibrant": "3.2.1-alpha.1", "proxy-polyfill": "0.3.2", @@ -150,18 +150,18 @@ "xss": "1.0.15" }, "devDependencies": { - "@babel/core": "7.24.3", + "@babel/core": "7.24.4", "@babel/helper-define-polyfill-provider": "0.6.1", "@babel/plugin-proposal-decorators": "7.24.1", "@babel/plugin-transform-runtime": "7.24.3", - "@babel/preset-env": "7.24.3", + "@babel/preset-env": "7.24.4", "@babel/preset-typescript": "7.24.1", "@bundle-stats/plugin-webpack-filter": "4.12.2", "@koa/cors": "5.0.0", - "@lokalise/node-api": "12.3.0", - "@octokit/auth-oauth-device": "7.0.1", - "@octokit/plugin-retry": "7.0.3", - "@octokit/rest": "20.0.2", + "@lokalise/node-api": "12.4.0", + "@octokit/auth-oauth-device": "7.1.1", + "@octokit/plugin-retry": "7.1.0", + "@octokit/rest": "20.1.0", "@open-wc/dev-server-hmr": "0.1.4", "@rollup/plugin-babel": "6.0.4", "@rollup/plugin-commonjs": "25.0.7", @@ -169,24 +169,24 @@ "@rollup/plugin-node-resolve": "15.2.3", "@rollup/plugin-replace": "5.0.5", "@types/babel__plugin-transform-runtime": "7.9.5", - "@types/chromecast-caf-receiver": "6.0.13", + "@types/chromecast-caf-receiver": "6.0.14", "@types/chromecast-caf-sender": "1.0.9", - "@types/color-name": "1.1.3", + "@types/color-name": "1.1.4", "@types/glob": "8.1.0", "@types/html-minifier-terser": "7.0.2", "@types/js-yaml": "4.0.9", - "@types/leaflet": "1.9.8", + "@types/leaflet": "1.9.11", "@types/leaflet-draw": "1.0.11", "@types/luxon": "3.4.2", "@types/mocha": "10.0.6", "@types/qrcode": "1.5.5", "@types/serve-handler": "6.1.4", "@types/sortablejs": "1.15.8", - "@types/tar": "6.1.11", + "@types/tar": "6.1.13", "@types/ua-parser-js": "0.7.39", "@types/webspeechapi": "0.0.29", - "@typescript-eslint/eslint-plugin": "7.4.0", - "@typescript-eslint/parser": "7.4.0", + "@typescript-eslint/eslint-plugin": "7.7.0", + "@typescript-eslint/parser": "7.7.0", "@web/dev-server": "0.1.38", "@web/dev-server-rollup": "0.4.1", "babel-loader": "9.1.3", @@ -203,12 +203,11 @@ "eslint-plugin-lit": "1.11.0", "eslint-plugin-lit-a11y": "4.1.2", "eslint-plugin-unused-imports": "3.1.0", - "eslint-plugin-wc": "2.0.4", + "eslint-plugin-wc": "2.1.0", "fancy-log": "2.0.0", "fs-extra": "11.2.0", - "glob": "10.3.10", + "glob": "10.3.12", "gulp": "4.0.2", - "gulp-flatmap": "1.0.2", "gulp-json-transform": "0.5.0", "gulp-merge-json": "2.2.1", "gulp-rename": "2.0.0", @@ -220,9 +219,9 @@ "lint-staged": "15.2.2", "lit-analyzer": "2.0.3", "lodash.template": "4.5.0", - "magic-string": "0.30.8", + "magic-string": "0.30.10", "map-stream": "0.0.7", - "mocha": "10.3.0", + "mocha": "10.4.0", "object-hash": "3.0.0", "open": "10.1.0", "pinst": "3.0.0", @@ -235,13 +234,11 @@ "sinon": "17.0.1", "source-map-url": "0.4.1", "systemjs": "6.14.3", - "tar": "6.2.1", + "tar": "7.0.1", "terser-webpack-plugin": "5.3.10", - "transform-async-modules-webpack-plugin": "1.0.4", + "transform-async-modules-webpack-plugin": "1.1.0", "ts-lit-plugin": "2.0.2", - "typescript": "5.4.3", - "vinyl-buffer": "1.0.1", - "vinyl-source-stream": "2.0.0", + "typescript": "5.4.5", "webpack": "5.91.0", "webpack-cli": "5.1.4", "webpack-dev-server": "5.0.4", diff --git a/pyproject.toml b/pyproject.toml index 42670dd060..b25adda887 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240404.2" +version = "20240424.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" diff --git a/renovate.json b/renovate.json index 741ef2c499..f6348e5a1d 100644 --- a/renovate.json +++ b/renovate.json @@ -40,6 +40,11 @@ "matchPackageNames": ["tsparticles-engine"], "matchPackagePrefixes": ["tsparticles-preset-"] }, + { + "description": "Group date-fns with dependent timezone package", + "groupName": "date-fns", + "matchPackageNames": ["date-fns", "date-fns-tz"] + }, { "description": "Group and temporarily disable WDS packages", "groupName": "Web Dev Server", diff --git a/src/common/datetime/calc_date.ts b/src/common/datetime/calc_date.ts index aa2c0e2eae..3c8635fdc0 100644 --- a/src/common/datetime/calc_date.ts +++ b/src/common/datetime/calc_date.ts @@ -1,4 +1,4 @@ -import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz"; +import { toZonedTime, fromZonedTime } from "date-fns-tz"; import { HassConfig } from "home-assistant-js-websocket"; import { FrontendLocaleData, TimeZone } from "../../data/translation"; @@ -8,10 +8,10 @@ const calcZonedDate = ( fn: (date: Date, options?: any) => Date | number | boolean, options? ) => { - const inputZoned = utcToZonedTime(date, tz); + const inputZoned = toZonedTime(date, tz); const fnZoned = fn(inputZoned, options); if (fnZoned instanceof Date) { - return zonedTimeToUtc(fnZoned, tz) as Date; + return fromZonedTime(fnZoned, tz) as Date; } return fnZoned; }; @@ -51,6 +51,6 @@ export const calcDateDifferenceProperty = ( locale, config, locale.time_zone === TimeZone.server - ? utcToZonedTime(startDate, config.time_zone) + ? toZonedTime(startDate, config.time_zone) : startDate ); diff --git a/src/common/entity/compute_state_display.ts b/src/common/entity/compute_state_display.ts index 6d5e36d5c2..0db516e56f 100644 --- a/src/common/entity/compute_state_display.ts +++ b/src/common/entity/compute_state_display.ts @@ -187,11 +187,14 @@ export const computeStateDisplayFromEntityAttributes = ( if ( [ "button", + "conversation", "event", "image", "input_button", + "notify", "scene", "stt", + "tag", "tts", "wake_word", ].includes(domain) || diff --git a/src/common/translations/localize.ts b/src/common/translations/localize.ts index ac1d759efd..f88e03691b 100644 --- a/src/common/translations/localize.ts +++ b/src/common/translations/localize.ts @@ -2,6 +2,7 @@ import IntlMessageFormat from "intl-messageformat"; import type { HTMLTemplateResult } from "lit"; import { polyfillLocaleData } from "../../resources/locale-data-polyfill"; import { Resources, TranslationDict } from "../../types"; +import { fireEvent } from "../dom/fire_event"; // Exclude some patterns from key type checking for now // These are intended to be removed as errors are fixed @@ -81,7 +82,9 @@ export interface FormatsType { */ export const computeLocalize = async ( - cache: any, + cache: HTMLElement & { + _localizationCache?: Record; + }, language: string, resources: Resources, formats?: FormatsType @@ -107,7 +110,7 @@ export const computeLocalize = async ( } const messageKey = key + translatedValue; - let translatedMessage = cache._localizationCache[messageKey] as + let translatedMessage = cache._localizationCache![messageKey] as | IntlMessageFormat | undefined; @@ -121,7 +124,7 @@ export const computeLocalize = async ( } catch (err: any) { return "Translation error: " + err.message; } - cache._localizationCache[messageKey] = translatedMessage; + cache._localizationCache![messageKey] = translatedMessage; } let argObject = {}; @@ -137,6 +140,12 @@ export const computeLocalize = async ( try { return translatedMessage.format(argObject) as string; } catch (err: any) { + // eslint-disable-next-line no-console + console.error("Translation error", key, language, err); + fireEvent(cache, "write_log", { + level: "error", + message: `Failed to format translation for key '${key}' in language '${language}'. ${err}`, + }); return "Translation " + err; } }; diff --git a/src/common/util/select-unit.ts b/src/common/util/select-unit.ts index 7e388a2ddb..8e49c463d4 100644 --- a/src/common/util/select-unit.ts +++ b/src/common/util/select-unit.ts @@ -1,4 +1,4 @@ -import { differenceInDays, differenceInWeeks, startOfWeek } from "date-fns/esm"; +import { differenceInDays, differenceInWeeks, startOfWeek } from "date-fns"; import { FrontendLocaleData } from "../../data/translation"; import { firstWeekdayIndex } from "../datetime/first_weekday"; diff --git a/src/components/chart/chart-date-adapter.ts b/src/components/chart/chart-date-adapter.ts index fac7819453..875282985a 100644 --- a/src/components/chart/chart-date-adapter.ts +++ b/src/components/chart/chart-date-adapter.ts @@ -34,7 +34,7 @@ import { endOfMonth, endOfQuarter, endOfYear, -} from "date-fns/esm"; +} from "date-fns"; import { formatDate, formatDateMonth, diff --git a/src/components/data-table/ha-data-table.ts b/src/components/data-table/ha-data-table.ts index 2c95735e82..e019a5d400 100644 --- a/src/components/data-table/ha-data-table.ts +++ b/src/components/data-table/ha-data-table.ts @@ -1,13 +1,13 @@ -import { mdiArrowDown, mdiArrowUp } from "@mdi/js"; +import { mdiArrowDown, mdiArrowUp, mdiChevronDown } from "@mdi/js"; import deepClone from "deep-clone-simple"; import { - css, CSSResultGroup, - html, LitElement, - nothing, PropertyValues, TemplateResult, + css, + html, + nothing, } from "lit"; import { customElement, @@ -22,7 +22,9 @@ import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { restoreScroll } from "../../common/decorators/restore-scroll"; import { fireEvent } from "../../common/dom/fire_event"; +import { stringCompare } from "../../common/string/compare"; import { debounce } from "../../common/util/debounce"; +import { groupBy } from "../../common/util/group-by"; import { nextRender } from "../../common/util/render-status"; import { haStyleScrollbar } from "../../resources/styles"; import { loadVirtualizer } from "../../resources/virtualizer"; @@ -32,17 +34,6 @@ import type { HaCheckbox } from "../ha-checkbox"; import "../ha-svg-icon"; import "../search-input"; import { filterData, sortData } from "./sort-filter"; -import { groupBy } from "../../common/util/group-by"; -import { stringCompare } from "../../common/string/compare"; - -declare global { - // for fire event - interface HASSDomEvents { - "selection-changed": SelectionChangedEvent; - "row-click": RowClickedEvent; - "sorting-changed": SortingChangedEvent; - } -} export interface RowClickedEvent { id: string; @@ -52,6 +43,10 @@ export interface SelectionChangedEvent { value: string[]; } +export interface CollapsedChangedEvent { + value: string[]; +} + export interface SortingChangedEvent { column: string; direction: SortingDirection; @@ -142,10 +137,14 @@ export class HaDataTable extends LitElement { @property() public groupColumn?: string; + @property({ attribute: false }) public groupOrder?: string[]; + @property() public sortColumn?: string; @property() public sortDirection: SortingDirection = null; + @property({ attribute: false }) public initialCollapsedGroups?: string[]; + @state() private _filterable = false; @state() private _filter = ""; @@ -158,6 +157,8 @@ export class HaDataTable extends LitElement { @state() private _items: DataTableRowData[] = []; + @state() private _collapsedGroups: string[] = []; + private _checkableRowsCount?: number; private _checkedRows: string[] = []; @@ -213,17 +214,19 @@ export class HaDataTable extends LitElement { (column) => column.filterable ); - for (const columnId in this.columns) { - if (this.columns[columnId].direction) { - this.sortDirection = this.columns[columnId].direction!; - this.sortColumn = columnId; + if (!this.sortColumn) { + for (const columnId in this.columns) { + if (this.columns[columnId].direction) { + this.sortDirection = this.columns[columnId].direction!; + this.sortColumn = columnId; - fireEvent(this, "sorting-changed", { - column: columnId, - direction: this.sortDirection, - }); + fireEvent(this, "sorting-changed", { + column: columnId, + direction: this.sortDirection, + }); - break; + break; + } } } @@ -248,13 +251,23 @@ export class HaDataTable extends LitElement { ).length; } + if (!this.hasUpdated && this.initialCollapsedGroups) { + this._collapsedGroups = this.initialCollapsedGroups; + fireEvent(this, "collapsed-changed", { value: this._collapsedGroups }); + } else if (properties.has("groupColumn")) { + this._collapsedGroups = []; + fireEvent(this, "collapsed-changed", { value: this._collapsedGroups }); + } + if ( properties.has("data") || properties.has("columns") || properties.has("_filter") || properties.has("sortColumn") || properties.has("sortDirection") || - properties.has("groupColumn") + properties.has("groupColumn") || + properties.has("groupOrder") || + properties.has("_collapsedGroups") ) { this._sortFilterData(); } @@ -447,6 +460,8 @@ export class HaDataTable extends LitElement { } return html`
item[this.groupColumn!]); @@ -530,13 +541,24 @@ export class HaDataTable extends LitElement { const sorted: { [key: string]: DataTableRowData[]; } = Object.keys(grouped) - .sort((a, b) => - stringCompare( + .sort((a, b) => { + const orderA = this.groupOrder?.indexOf(a) ?? -1; + const orderB = this.groupOrder?.indexOf(b) ?? -1; + if (orderA !== orderB) { + if (orderA === -1) { + return 1; + } + if (orderB === -1) { + return -1; + } + return orderA - orderB; + } + return stringCompare( ["", "-", "—"].includes(a) ? "zzz" : a, ["", "-", "—"].includes(b) ? "zzz" : b, this.hass.locale.language - ) - ) + ); + }) .reduce((obj, key) => { obj[key] = grouped[key]; return obj; @@ -552,23 +574,39 @@ export class HaDataTable extends LitElement { content: html`
- ${groupName === UNDEFINED_GROUP_KEY ? "" : groupName || ""} + + + ${groupName === UNDEFINED_GROUP_KEY + ? this.hass.localize("ui.components.data-table.ungrouped") + : groupName || ""}
`, }); } - - groupedItems.push(...rows); + if (!this._collapsedGroups.includes(groupName)) { + groupedItems.push(...rows); + } }); - this._items = groupedItems; - } else { - this._items = items; + items = groupedItems; + } + + if (this.appendRow) { + items.push({ append: true, content: this.appendRow }); } if (this.hasFab) { - this._items = [...this._items, { empty: true }]; + items.push({ empty: true }); } + + this._items = items; } else { this._items = data; } @@ -649,6 +687,13 @@ export class HaDataTable extends LitElement { fireEvent(this, "row-click", { id: rowId }, { bubbles: false }); }; + private _setTitle(ev: Event) { + const target = ev.currentTarget as HTMLElement; + if (target.scrollWidth > target.offsetWidth) { + target.setAttribute("title", target.innerText); + } + } + private _checkedRowsChanged() { // force scroller to update, change it's items if (this._items.length) { @@ -679,6 +724,18 @@ export class HaDataTable extends LitElement { this._savedScrollPos = (e.target as HTMLDivElement).scrollTop; } + private _collapseGroup = (ev: Event) => { + const groupName = (ev.currentTarget as any).group; + if (this._collapsedGroups.includes(groupName)) { + this._collapsedGroups = this._collapsedGroups.filter( + (grp) => grp !== groupName + ); + } else { + this._collapsedGroups = [...this._collapsedGroups, groupName]; + } + fireEvent(this, "collapsed-changed", { value: this._collapsedGroups }); + }; + static get styles(): CSSResultGroup { return [ haStyleScrollbar, @@ -931,8 +988,21 @@ export class HaDataTable extends LitElement { .group-header { padding-top: 12px; + padding-left: 12px; + padding-inline-start: 12px; width: 100%; font-weight: 500; + display: flex; + align-items: center; + cursor: pointer; + } + + .group-header ha-icon-button { + transition: transform 0.2s ease; + } + + .group-header ha-icon-button.collapsed { + transform: rotate(180deg); } :host { @@ -1031,4 +1101,12 @@ declare global { interface HTMLElementTagNameMap { "ha-data-table": HaDataTable; } + + // for fire event + interface HASSDomEvents { + "selection-changed": SelectionChangedEvent; + "row-click": RowClickedEvent; + "sorting-changed": SortingChangedEvent; + "collapsed-changed": CollapsedChangedEvent; + } } diff --git a/src/components/entity/ha-entity-picker.ts b/src/components/entity/ha-entity-picker.ts index 1ae47cb99a..ccb233fffb 100644 --- a/src/components/entity/ha-entity-picker.ts +++ b/src/components/entity/ha-entity-picker.ts @@ -18,6 +18,12 @@ import "../ha-icon-button"; import "../ha-svg-icon"; import "./state-badge"; import { caseInsensitiveStringCompare } from "../../common/string/compare"; +import { showHelperDetailDialog } from "../../panels/config/helpers/show-dialog-helper-detail"; +import { domainToName } from "../../data/integration"; +import { + isHelperDomain, + HelperDomain, +} from "../../panels/config/helpers/const"; interface HassEntityWithCachedName extends HassEntity, ScorableTextItem { friendly_name: string; @@ -25,6 +31,8 @@ interface HassEntityWithCachedName extends HassEntity, ScorableTextItem { export type HaEntityPickerEntityFilterFunc = (entity: HassEntity) => boolean; +const CREATE_ID = "___create-new-entity___"; + @customElement("ha-entity-picker") export class HaEntityPicker extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -44,6 +52,8 @@ export class HaEntityPicker extends LitElement { @property() public helper?: string; + @property({ type: Array }) public createDomains?: string[]; + /** * Show entities from specific domains. * @type {Array} @@ -130,7 +140,11 @@ export class HaEntityPicker extends LitElement { >` : ""} ${item.friendly_name} - ${item.entity_id} + ${item.entity_id.startsWith(CREATE_ID) + ? this.hass.localize("ui.components.entity.entity-picker.new_entity") + : item.entity_id} `; private _getStates = memoizeOne( @@ -143,7 +157,8 @@ export class HaEntityPicker extends LitElement { includeDeviceClasses: this["includeDeviceClasses"], includeUnitOfMeasurement: this["includeUnitOfMeasurement"], includeEntities: this["includeEntities"], - excludeEntities: this["excludeEntities"] + excludeEntities: this["excludeEntities"], + createDomains: this["createDomains"] ): HassEntityWithCachedName[] => { let states: HassEntityWithCachedName[] = []; @@ -152,6 +167,34 @@ export class HaEntityPicker extends LitElement { } let entityIds = Object.keys(hass.states); + const createItems = createDomains?.length + ? createDomains.map((domain) => { + const newFriendlyName = hass.localize( + "ui.components.entity.entity-picker.create_helper", + { + domain: isHelperDomain(domain) + ? hass.localize( + `ui.panel.config.helpers.types.${domain as HelperDomain}` + ) + : domainToName(hass.localize, domain), + } + ); + + return { + entity_id: CREATE_ID + domain, + state: "on", + last_changed: "", + last_updated: "", + context: { id: "", user_id: null, parent_id: null }, + friendly_name: newFriendlyName, + attributes: { + icon: "mdi:plus", + }, + strings: [domain, newFriendlyName], + }; + }) + : []; + if (!entityIds.length) { return [ { @@ -171,6 +214,7 @@ export class HaEntityPicker extends LitElement { }, strings: [], }, + ...createItems, ]; } @@ -281,9 +325,14 @@ export class HaEntityPicker extends LitElement { }, strings: [], }, + ...createItems, ]; } + if (createItems?.length) { + states.push(...createItems); + } + return states; } ); @@ -310,13 +359,18 @@ export class HaEntityPicker extends LitElement { this.includeDeviceClasses, this.includeUnitOfMeasurement, this.includeEntities, - this.excludeEntities + this.excludeEntities, + this.createDomains ); if (this._initedStates) { this.comboBox.filteredItems = this._states; } this._initedStates = true; } + + if (changedProps.has("createDomains") && this.createDomains?.length) { + this.hass.loadFragmentTranslation("config"); + } } protected render(): TemplateResult { @@ -354,6 +408,18 @@ export class HaEntityPicker extends LitElement { private _valueChanged(ev: ValueChangedEvent) { ev.stopPropagation(); const newValue = ev.detail.value; + + if (newValue && newValue.startsWith(CREATE_ID)) { + const domain = newValue.substring(CREATE_ID.length); + showHelperDetailDialog(this, { + domain, + dialogClosedCallback: (item) => { + if (item.entityId) this._setValue(item.entityId); + }, + }); + return; + } + if (newValue !== this._value) { this._setValue(newValue); } diff --git a/src/components/ha-card.ts b/src/components/ha-card.ts index fc95aa118d..38a154a768 100644 --- a/src/components/ha-card.ts +++ b/src/components/ha-card.ts @@ -14,6 +14,8 @@ export class HaCard extends LitElement { --ha-card-background, var(--card-background-color, white) ); + -webkit-backdrop-filter: var(--ha-card-backdrop-filter, none); + backdrop-filter: var(--ha-card-backdrop-filter, none); box-shadow: var(--ha-card-box-shadow, none); box-sizing: border-box; border-radius: var(--ha-card-border-radius, 12px); diff --git a/src/components/ha-circular-progress.ts b/src/components/ha-circular-progress.ts index 480b0ec1cc..6d53057b92 100644 --- a/src/components/ha-circular-progress.ts +++ b/src/components/ha-circular-progress.ts @@ -1,6 +1,6 @@ import "element-internals-polyfill"; import { MdCircularProgress } from "@material/web/progress/circular-progress"; -import { CSSResult, PropertyValues, css } from "lit"; +import { PropertyValues, css } from "lit"; import { customElement, property } from "lit/decorators"; @customElement("ha-circular-progress") @@ -32,17 +32,15 @@ export class HaCircularProgress extends MdCircularProgress { } } - static get styles(): CSSResult[] { - return [ - ...super.styles, - css` - :host { - --md-sys-color-primary: var(--primary-color); - --md-circular-progress-size: 48px; - } - `, - ]; - } + static override styles = [ + ...super.styles, + css` + :host { + --md-sys-color-primary: var(--primary-color); + --md-circular-progress-size: 48px; + } + `, + ]; } declare global { diff --git a/src/components/ha-control-slider.ts b/src/components/ha-control-slider.ts index 23014308d0..290e061ae3 100644 --- a/src/components/ha-control-slider.ts +++ b/src/components/ha-control-slider.ts @@ -67,6 +67,9 @@ export class HaControlSlider extends LitElement { @property({ attribute: "tooltip-mode" }) public tooltipMode: TooltipMode = "interaction"; + @property({ attribute: "touch-action" }) + public touchAction?: string; + @property({ type: Number }) public value?: number; @@ -152,7 +155,7 @@ export class HaControlSlider extends LitElement { setupListeners() { if (this.slider && !this._mc) { this._mc = new Manager(this.slider, { - touchAction: this.vertical ? "pan-x" : "pan-y", + touchAction: this.touchAction ?? (this.vertical ? "pan-x" : "pan-y"), }); this._mc.add( new Pan({ diff --git a/src/components/ha-control-switch.ts b/src/components/ha-control-switch.ts index 2626b2ea20..0e75b66549 100644 --- a/src/components/ha-control-switch.ts +++ b/src/components/ha-control-switch.ts @@ -33,6 +33,9 @@ export class HaControlSwitch extends LitElement { // SVG icon path (if you need a non SVG icon instead, use the provided off icon slot to pass an in) @property({ type: String }) pathOff?: string; + @property({ attribute: "touch-action" }) + public touchAction?: string; + private _mc?: HammerManager; protected firstUpdated(changedProperties: PropertyValues): void { @@ -73,7 +76,7 @@ export class HaControlSwitch extends LitElement { setupListeners() { if (this.switch && !this._mc) { this._mc = new Manager(this.switch, { - touchAction: this.vertical ? "pan-x" : "pan-y", + touchAction: this.touchAction ?? (this.vertical ? "pan-x" : "pan-y"), }); this._mc.add( new Swipe({ diff --git a/src/components/ha-dialog.ts b/src/components/ha-dialog.ts index 19401d826d..4d8980a037 100644 --- a/src/components/ha-dialog.ts +++ b/src/components/ha-dialog.ts @@ -75,8 +75,14 @@ export class HaDialog extends DialogBase { var(--divider-color) ); z-index: var(--dialog-z-index, 8); - -webkit-backdrop-filter: var(--dialog-backdrop-filter, none); - backdrop-filter: var(--dialog-backdrop-filter, none); + -webkit-backdrop-filter: var( + --ha-dialog-scrim-backdrop-filter, + var(--dialog-backdrop-filter, none) + ); + backdrop-filter: var( + --ha-dialog-scrim-backdrop-filter, + var(--dialog-backdrop-filter, none) + ); --mdc-dialog-box-shadow: var(--dialog-box-shadow, none); --mdc-typography-headline6-font-weight: 400; --mdc-typography-headline6-font-size: 1.574rem; @@ -119,6 +125,8 @@ export class HaDialog extends DialogBase { margin-top: var(--dialog-surface-margin-top); min-height: var(--mdc-dialog-min-height, auto); border-radius: var(--ha-dialog-border-radius, 28px); + -webkit-backdrop-filter: var(--ha-dialog-surface-backdrop-filter, none); + backdrop-filter: var(--ha-dialog-surface-backdrop-filter, none); } :host([flexContent]) .mdc-dialog .mdc-dialog__content { display: flex; diff --git a/src/components/ha-filter-devices.ts b/src/components/ha-filter-devices.ts index 97f17f9c83..a88b957ed7 100644 --- a/src/components/ha-filter-devices.ts +++ b/src/components/ha-filter-devices.ts @@ -94,7 +94,7 @@ export class HaFilterDevices extends LitElement { ? nothing : html` ${computeDeviceName(device, this.hass)} `; diff --git a/src/components/ha-filter-entities.ts b/src/components/ha-filter-entities.ts index 585d35a527..ee92c9d0c3 100644 --- a/src/components/ha-filter-entities.ts +++ b/src/components/ha-filter-entities.ts @@ -108,7 +108,7 @@ export class HaFilterEntities extends LitElement { ? nothing : html` html` ${item.icon ? html` + [ + { + name: "", + type: "grid", + schema: [ + { + name: "latitude", + required: true, + selector: { number: { step: "any" } }, + }, + { + name: "longitude", + required: true, + selector: { number: { step: "any" } }, + }, + ], + }, + ...(radius + ? [ + { + name: "radius", + required: true, + default: 1000, + disabled: !!radius_readonly, + selector: { number: { min: 0, step: 1, mode: "box" } as const }, + } as const, + ] + : []), + ] as const + ); + + protected willUpdate() { + if (!this.value) { + this.value = { + latitude: this.hass.config.latitude, + longitude: this.hass.config.longitude, + radius: this.selector.location?.radius ? 1000 : undefined, + }; + } + } + protected render() { return html`

${this.label ? this.label : ""}

@@ -35,6 +80,17 @@ export class HaLocationSelector extends LitElement { @location-updated=${this._locationChanged} @radius-updated=${this._radiusChanged} > + `; } @@ -66,7 +122,8 @@ export class HaLocationSelector extends LitElement { ? "mdi:map-marker-radius" : "mdi:map-marker", location_editable: true, - radius_editable: true, + radius_editable: + !!selector.location?.radius && !selector.location?.radius_readonly, }, ]; } @@ -80,14 +137,39 @@ export class HaLocationSelector extends LitElement { } private _radiusChanged(ev: CustomEvent) { - const radius = ev.detail.radius; + const radius = Math.round(ev.detail.radius); fireEvent(this, "value-changed", { value: { ...this.value, radius } }); } + private _valueChanged(ev: CustomEvent) { + ev.stopPropagation(); + const value = ev.detail.value; + const radius = Math.round(ev.detail.value.radius); + + fireEvent(this, "value-changed", { + value: { + latitude: value.latitude, + longitude: value.longitude, + ...(this.selector.location?.radius && + !this.selector.location?.radius_readonly + ? { + radius, + } + : {}), + }, + }); + } + + private _computeLabel = ( + entry: SchemaUnion> + ): string => + this.hass.localize(`ui.components.selectors.location.${entry.name}`); + static styles = css` ha-locations-editor { display: block; height: 400px; + margin-bottom: 16px; } p { margin-top: 0; diff --git a/src/components/ha-selector/ha-selector-target.ts b/src/components/ha-selector/ha-selector-target.ts index fafc97b62b..a37557c1bd 100644 --- a/src/components/ha-selector/ha-selector-target.ts +++ b/src/components/ha-selector/ha-selector-target.ts @@ -82,6 +82,7 @@ export class HaTargetSelector extends LitElement { .deviceFilter=${this._filterDevices} .entityFilter=${this._filterEntities} .disabled=${this.disabled} + .createDomains=${this.selector.target?.create_domains} >`; } diff --git a/src/components/ha-service-control.ts b/src/components/ha-service-control.ts index 8310aee8f4..83da022e29 100644 --- a/src/components/ha-service-control.ts +++ b/src/components/ha-service-control.ts @@ -33,6 +33,7 @@ import { expandFloorTarget, expandLabelTarget, Selector, + TargetSelector, } from "../data/selector"; import { HomeAssistant, ValueChangedEvent } from "../types"; import { documentationUrl } from "../util/documentation-url"; @@ -43,6 +44,7 @@ import "./ha-service-picker"; import "./ha-settings-row"; import "./ha-yaml-editor"; import type { HaYamlEditor } from "./ha-yaml-editor"; +import { isHelperDomain } from "../panels/config/helpers/const"; const attributeFilter = (values: any[], attribute: any) => { if (typeof attribute === "object") { @@ -363,6 +365,15 @@ export class HaServiceControl extends LitElement { return false; } + private _targetSelector = memoizeOne( + (targetSelector: TargetSelector | null | undefined, domain?: string) => { + const create_domains = isHelperDomain(domain) ? [domain] : undefined; + return targetSelector + ? { target: { ...targetSelector, create_domains } } + : { target: { create_domains } }; + } + ); + protected render() { const serviceData = this._getServiceInfo( this._value?.service, @@ -401,157 +412,152 @@ export class HaServiceControl extends LitElement { )) || serviceData?.description; - return html` - ${this.hidePicker - ? nothing - : html``} + ${this.hideDescription + ? nothing + : html` +
+ ${description ? html`

${description}

` : ""} + ${this._manifest + ? html` + + ` + : nothing} +
+ `} + ${serviceData && "target" in serviceData + ? html` + ${hasOptional + ? html`
` + : ""} + ${this.hass.localize("ui.components.service-control.target")} + ${this.hass.localize( + "ui.components.service-control.target_description" + )}`} - ${this.hideDescription - ? nothing - : html` -
- ${description ? html`

${description}

` : ""} - ${this._manifest - ? html` - - ` - : nothing} -
- `} - ${serviceData && "target" in serviceData - ? html` - ${hasOptional - ? html`
` - : ""} - ${this.hass.localize( - "ui.components.service-control.target" - )} - ${this.hass.localize( - "ui.components.service-control.target_description" - )}
` - : entityId - ? html`` - : ""} - ${shouldRenderServiceDataYaml - ? html`
` + : entityId + ? html`` - : filteredFields?.map((dataField) => { - const selector = dataField?.selector ?? { text: undefined }; - const type = Object.keys(selector)[0]; - const enhancedSelector = [ - "action", - "condition", - "trigger", - ].includes(type) - ? { - [type]: { - ...selector[type], - path: [dataField.key], - }, - } - : selector; + .disabled=${this.disabled} + .value=${this._value?.data?.entity_id} + .label=${this.hass.localize( + `component.${domain}.services.${serviceName}.fields.entity_id.description` + ) || entityId.description} + @value-changed=${this._entityPicked} + allow-custom-entity + >` + : ""} + ${shouldRenderServiceDataYaml + ? html`` + : filteredFields?.map((dataField) => { + const selector = dataField?.selector ?? { text: undefined }; + const type = Object.keys(selector)[0]; + const enhancedSelector = ["action", "condition", "trigger"].includes( + type + ) + ? { + [type]: { + ...selector[type], + path: [dataField.key], + }, + } + : selector; - const showOptional = showOptionalToggle(dataField); + const showOptional = showOptionalToggle(dataField); - return dataField.selector && - (!dataField.advanced || - this.showAdvanced || - (this._value?.data && - this._value.data[dataField.key] !== undefined)) - ? html` - ${!showOptional - ? hasOptional - ? html`
` - : "" - : html``} - ${this.hass.localize( - `component.${domain}.services.${serviceName}.fields.${dataField.key}.name` - ) || - dataField.name || - dataField.key} - ${this.hass.localize( - `component.${domain}.services.${serviceName}.fields.${dataField.key}.description` - ) || dataField?.description} - -
` - : ""; - })} - `; + return dataField.selector && + (!dataField.advanced || + this.showAdvanced || + (this._value?.data && + this._value.data[dataField.key] !== undefined)) + ? html` + ${!showOptional + ? hasOptional + ? html`
` + : "" + : html``} + ${this.hass.localize( + `component.${domain}.services.${serviceName}.fields.${dataField.key}.name` + ) || + dataField.name || + dataField.key} + ${this.hass.localize( + `component.${domain}.services.${serviceName}.fields.${dataField.key}.description` + ) || dataField?.description} + +
` + : ""; + })} `; } private _localizeValueCallback = (key: string) => { diff --git a/src/components/ha-slider.ts b/src/components/ha-slider.ts index 31607a62f5..5c4d40d0b8 100644 --- a/src/components/ha-slider.ts +++ b/src/components/ha-slider.ts @@ -1,7 +1,7 @@ import { customElement } from "lit/decorators"; import "element-internals-polyfill"; import { MdSlider } from "@material/web/slider/slider"; -import { CSSResult, css } from "lit"; +import { css } from "lit"; import { mainWindow } from "../common/dom/get_main_window"; @customElement("ha-slider") @@ -11,8 +11,8 @@ export class HaSlider extends MdSlider { this.dir = mainWindow.document.dir; } - static override styles: CSSResult[] = [ - ...MdSlider.styles, + static override styles = [ + ...super.styles, css` :host { --md-sys-color-primary: var(--primary-color); diff --git a/src/components/ha-sortable.ts b/src/components/ha-sortable.ts index b3a565dd47..e86c32dd77 100644 --- a/src/components/ha-sortable.ts +++ b/src/components/ha-sortable.ts @@ -82,7 +82,7 @@ export class HaSortable extends LitElement { public connectedCallback() { super.connectedCallback(); this._shouldBeDestroy = false; - if (this.hasUpdated) { + if (this.hasUpdated && !this.disabled) { this._createSortable(); } } diff --git a/src/components/ha-sub-menu.ts b/src/components/ha-sub-menu.ts index 9d01b2019f..584d30dfa7 100644 --- a/src/components/ha-sub-menu.ts +++ b/src/components/ha-sub-menu.ts @@ -1,18 +1,17 @@ import { customElement } from "lit/decorators"; import "element-internals-polyfill"; -import { CSSResult, css } from "lit"; +import { css } from "lit"; import { MdSubMenu } from "@material/web/menu/sub-menu"; @customElement("ha-sub-menu") -// @ts-expect-error export class HaSubMenu extends MdSubMenu { async show() { super.show(); this.menu.hasOverflow = false; } - static override styles: CSSResult[] = [ - MdSubMenu.styles, + static override styles = [ + ...super.styles, css` :host { --ha-icon-display: block; diff --git a/src/components/ha-target-picker.ts b/src/components/ha-target-picker.ts index 21d32d3ea3..c20a465e44 100644 --- a/src/components/ha-target-picker.ts +++ b/src/components/ha-target-picker.ts @@ -65,6 +65,8 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) { @property() public helper?: string; + @property({ type: Array }) public createDomains?: string[]; + /** * Show only targets with entities from specific domains. * @type {Array} @@ -468,6 +470,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) { .includeDeviceClasses=${this.includeDeviceClasses} .includeDomains=${this.includeDomains} .excludeEntities=${ensureArray(this.value?.entity_id)} + .createDomains=${this.createDomains} @value-changed=${this._targetPicked} @click=${this._preventDefault} allow-custom-entity diff --git a/src/components/trace/hat-trace-timeline.ts b/src/components/trace/hat-trace-timeline.ts index eab5998d1d..9a440e6ed1 100644 --- a/src/components/trace/hat-trace-timeline.ts +++ b/src/components/trace/hat-trace-timeline.ts @@ -797,6 +797,7 @@ export class HaAutomationTracer extends LitElement { description: html`${this.hass.localize( `ui.panel.config.automation.trace.messages.${message}`, { + reason: this.trace.script_execution, time: renderFinishedAt(), executiontime: renderRuntime(), } diff --git a/src/data/cloud.ts b/src/data/cloud.ts index 5db22590c4..e3d62b513b 100644 --- a/src/data/cloud.ts +++ b/src/data/cloud.ts @@ -1,6 +1,8 @@ import { EntityFilter } from "../common/entity/entity_filter"; import { HomeAssistant } from "../types"; +type StrictConnectionMode = "disabled" | "guard_page" | "drop_connection"; + interface CloudStatusNotLoggedIn { logged_in: false; cloud: "disconnected" | "connecting" | "connected"; @@ -19,6 +21,7 @@ export interface CloudPreferences { alexa_enabled: boolean; remote_enabled: boolean; remote_allow_remote_enable: boolean; + strict_connection: StrictConnectionMode; google_secure_devices_pin: string | undefined; cloudhooks: { [webhookId: string]: CloudWebhook }; alexa_report_state: boolean; @@ -141,6 +144,7 @@ export const updateCloudPref = ( google_secure_devices_pin?: CloudPreferences["google_secure_devices_pin"]; tts_default_voice?: CloudPreferences["tts_default_voice"]; remote_allow_remote_enable?: CloudPreferences["remote_allow_remote_enable"]; + strict_connection?: CloudPreferences["strict_connection"]; } ) => hass.callWS({ diff --git a/src/data/config_entries.ts b/src/data/config_entries.ts index ab3d7480fd..37af47885d 100644 --- a/src/data/config_entries.ts +++ b/src/data/config_entries.ts @@ -23,6 +23,8 @@ export interface ConfigEntry { pref_disable_polling: boolean; disabled_by: "user" | null; reason: string | null; + error_reason_translation_key: string | null; + error_reason_translation_placeholders: Record | null; } export type ConfigEntryMutableParams = Partial< diff --git a/src/data/energy.ts b/src/data/energy.ts index d322723ae2..61d23aca0e 100644 --- a/src/data/energy.ts +++ b/src/data/energy.ts @@ -9,7 +9,7 @@ import { startOfDay, isFirstDayOfMonth, isLastDayOfMonth, -} from "date-fns/esm"; +} from "date-fns"; import { Collection, getCollection } from "home-assistant-js-websocket"; import { calcDate, @@ -95,6 +95,7 @@ export type EnergySolarForecasts = { export interface DeviceConsumptionEnergyPreference { // This is an ever increasing value stat_consumption: string; + name?: string; } export interface FlowFromGridSourceEnergyPreference { diff --git a/src/data/history.ts b/src/data/history.ts index e0fc8bd328..53b83896e8 100644 --- a/src/data/history.ts +++ b/src/data/history.ts @@ -422,7 +422,8 @@ export const computeHistory = ( entityIds: string[], localize: LocalizeFunc, sensorNumericalDeviceClasses: string[], - splitDeviceClasses = false + splitDeviceClasses = false, + forceNumeric = false ): HistoryResult => { const lineChartDevices: { [unit: string]: HistoryStates } = {}; const timelineDevices: TimelineEntity[] = []; @@ -468,6 +469,7 @@ export const computeHistory = ( let unit: string | undefined; const isNumeric = + forceNumeric || isNumericFromDomain(domain) || (currentState != null && isNumericFromAttributes(currentState.attributes)) || diff --git a/src/data/label_registry.ts b/src/data/label_registry.ts index ca3512cd93..cc6b318354 100644 --- a/src/data/label_registry.ts +++ b/src/data/label_registry.ts @@ -9,12 +9,14 @@ export interface LabelRegistryEntry { name: string; icon: string | null; color: string | null; + description: string | null; } export interface LabelRegistryEntryMutableParams { name: string; icon?: string | null; color?: string | null; + description?: string | null; } export const fetchLabelRegistry = (conn: Connection) => diff --git a/src/data/lock.ts b/src/data/lock.ts index 7d155369f4..26d4217802 100644 --- a/src/data/lock.ts +++ b/src/data/lock.ts @@ -5,9 +5,7 @@ import { import { getExtendedEntityRegistryEntry } from "./entity_registry"; import { showEnterCodeDialog } from "../dialogs/enter-code/show-enter-code-dialog"; import { HomeAssistant } from "../types"; - -export const FORMAT_TEXT = "text"; -export const FORMAT_NUMBER = "number"; +import { UNAVAILABLE } from "./entity"; export const enum LockEntityFeature { OPEN = 1, @@ -24,6 +22,33 @@ export interface LockEntity extends HassEntityBase { type ProtectedLockService = "lock" | "unlock" | "open"; +export function isLocked(stateObj: LockEntity) { + return stateObj.state === "locked"; +} + +export function isUnlocking(stateObj: LockEntity) { + return stateObj.state === "unlocking"; +} + +export function isLocking(stateObj: LockEntity) { + return stateObj.state === "locking"; +} + +export function isJammed(stateObj: LockEntity) { + return stateObj.state === "jammed"; +} + +export function isAvailable(stateObj: LockEntity) { + if (stateObj.state === UNAVAILABLE) { + return false; + } + const assumedState = stateObj.attributes.assumed_state === true; + return ( + assumedState || + (!isLocking(stateObj) && !isUnlocking(stateObj) && !isJammed(stateObj)) + ); +} + export const callProtectedLockService = async ( element: HTMLElement, hass: HomeAssistant, diff --git a/src/data/selector.ts b/src/data/selector.ts index 3abb7ae6fc..f49eae11a1 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -270,7 +270,11 @@ export interface LanguageSelector { } export interface LocationSelector { - location: { radius?: boolean; icon?: string } | null; + location: { + radius?: boolean; + radius_readonly?: boolean; + icon?: string; + } | null; } export interface LocationSelectorValue { @@ -401,6 +405,7 @@ export interface TargetSelector { target: { entity?: EntitySelectorFilter | readonly EntitySelectorFilter[]; device?: DeviceSelectorFilter | readonly DeviceSelectorFilter[]; + create_domains?: string[]; } | null; } diff --git a/src/data/zone.ts b/src/data/zone.ts index 52ea733317..d59e33e87f 100644 --- a/src/data/zone.ts +++ b/src/data/zone.ts @@ -11,6 +11,11 @@ export interface Zone { radius?: number; } +export interface HomeZoneMutableParams { + latitude: number; + longitude: number; +} + export interface ZoneMutableParams { name: string; icon?: string; diff --git a/src/dialogs/more-info/components/lights/light-color-temp-picker.ts b/src/dialogs/more-info/components/lights/light-color-temp-picker.ts index a1f5726cac..7c300193e0 100644 --- a/src/dialogs/more-info/components/lights/light-color-temp-picker.ts +++ b/src/dialogs/more-info/components/lights/light-color-temp-picker.ts @@ -78,6 +78,7 @@ class LightColorTempPicker extends LitElement { return html`
- ${this.stateObj.state === "jammed" + ${isJammed(this.stateObj) ? html`
@@ -125,7 +124,7 @@ class MoreInfoLock extends LitElement { ` : html` @@ -139,7 +138,7 @@ class MoreInfoLock extends LitElement { : nothing}
- ${isJammed + ${isJammed(this.stateObj) ? html` diff --git a/src/dialogs/more-info/ha-more-info-history.ts b/src/dialogs/more-info/ha-more-info-history.ts index 8917054a13..878e821814 100644 --- a/src/dialogs/more-info/ha-more-info-history.ts +++ b/src/dialogs/more-info/ha-more-info-history.ts @@ -1,4 +1,4 @@ -import { startOfYesterday, subHours } from "date-fns/esm"; +import { startOfYesterday, subHours } from "date-fns"; import { LitElement, PropertyValues, css, html, nothing } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { isComponentLoaded } from "../../common/config/is_component_loaded"; diff --git a/src/dialogs/more-info/ha-more-info-logbook.ts b/src/dialogs/more-info/ha-more-info-logbook.ts index c42f72c57d..59d81327d1 100644 --- a/src/dialogs/more-info/ha-more-info-logbook.ts +++ b/src/dialogs/more-info/ha-more-info-logbook.ts @@ -1,4 +1,4 @@ -import { startOfYesterday } from "date-fns/esm"; +import { startOfYesterday } from "date-fns"; import { css, html, LitElement, PropertyValues, nothing } from "lit"; import { customElement, property } from "lit/decorators"; import memoizeOne from "memoize-one"; diff --git a/src/external_app/external_app_entrypoint.ts b/src/external_app/external_app_entrypoint.ts index 2f070044e2..e4c52b3b4b 100644 --- a/src/external_app/external_app_entrypoint.ts +++ b/src/external_app/external_app_entrypoint.ts @@ -9,7 +9,19 @@ import { fireEvent } from "../common/dom/fire_event"; import { mainWindow } from "../common/dom/get_main_window"; import { showAutomationEditor } from "../data/automation"; import { HomeAssistantMain } from "../layouts/home-assistant-main"; -import type { EMIncomingMessageCommands } from "./external_messaging"; +import type { + EMIncomingMessageBarCodeScanAborted, + EMIncomingMessageBarCodeScanResult, + EMIncomingMessageCommands, +} from "./external_messaging"; + +const barCodeListeners = new Set< + ( + msg: + | EMIncomingMessageBarCodeScanResult + | EMIncomingMessageBarCodeScanAborted + ) => boolean +>(); export const attachExternalToApp = (hassMainEl: HomeAssistantMain) => { window.addEventListener("haptic", (ev) => @@ -24,6 +36,19 @@ export const attachExternalToApp = (hassMainEl: HomeAssistantMain) => { ); }; +export const addExternalBarCodeListener = ( + listener: ( + msg: + | EMIncomingMessageBarCodeScanResult + | EMIncomingMessageBarCodeScanAborted + ) => boolean +) => { + barCodeListeners.add(listener); + return () => { + barCodeListeners.delete(listener); + }; +}; + const handleExternalMessage = ( hassMainEl: HomeAssistantMain, msg: EMIncomingMessageCommands @@ -88,6 +113,22 @@ const handleExternalMessage = ( success: true, result: null, }); + } else if (msg.command === "bar_code/scan_result") { + barCodeListeners.forEach((listener) => listener(msg)); + bus.fireMessage({ + id: msg.id, + type: "result", + success: true, + result: null, + }); + } else if (msg.command === "bar_code/aborted") { + barCodeListeners.forEach((listener) => listener(msg)); + bus.fireMessage({ + id: msg.id, + type: "result", + success: true, + result: null, + }); } else { return false; } diff --git a/src/external_app/external_messaging.ts b/src/external_app/external_messaging.ts index a994a669b9..e533a453cb 100644 --- a/src/external_app/external_messaging.ts +++ b/src/external_app/external_messaging.ts @@ -37,9 +37,11 @@ interface EMOutgoingMessageConfigGet extends EMMessage { interface EMOutgoingMessageBarCodeScan extends EMMessage { type: "bar_code/scan"; - title: string; - description: string; - alternative_option_label?: string; + payload: { + title: string; + description: string; + alternative_option_label?: string; + }; } interface EMOutgoingMessageBarCodeClose extends EMMessage { @@ -48,7 +50,9 @@ interface EMOutgoingMessageBarCodeClose extends EMMessage { interface EMOutgoingMessageBarCodeNotify extends EMMessage { type: "bar_code/notify"; - message: string; + payload: { + message: string; + }; } interface EMOutgoingMessageMatterCommission extends EMMessage { diff --git a/src/layouts/hass-tabs-subpage-data-table.ts b/src/layouts/hass-tabs-subpage-data-table.ts index 2c7aab1dc1..491e36d2c9 100644 --- a/src/layouts/hass-tabs-subpage-data-table.ts +++ b/src/layouts/hass-tabs-subpage-data-table.ts @@ -41,14 +41,6 @@ import type { HomeAssistant, Route } from "../types"; import "./hass-tabs-subpage"; import type { PageNavigation } from "./hass-tabs-subpage"; -declare global { - // for fire event - interface HASSDomEvents { - "search-changed": { value: string }; - "clear-filter": undefined; - } -} - @customElement("hass-tabs-subpage-data-table") export class HaTabsSubpageDataTable extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -63,6 +55,8 @@ export class HaTabsSubpageDataTable extends LitElement { @property({ type: Boolean, attribute: "main-page" }) public mainPage = false; + @property({ attribute: false }) public initialCollapsedGroups: string[] = []; + /** * Object with the columns. * @type {Object} @@ -166,8 +160,15 @@ export class HaTabsSubpageDataTable extends LitElement { @property({ type: Boolean }) public showFilters = false; + @property({ attribute: false }) public initialSorting?: { + column: string; + direction: SortingDirection; + }; + @property() public initialGroupColumn?: string; + @property({ attribute: false }) public groupOrder?: string[]; + @state() private _sortColumn?: string; @state() private _sortDirection: SortingDirection = null; @@ -190,9 +191,16 @@ export class HaTabsSubpageDataTable extends LitElement { this._dataTable.clearSelection(); } - protected firstUpdated() { + protected willUpdate() { + if (this.hasUpdated) { + return; + } if (this.initialGroupColumn) { - this._groupColumn = this.initialGroupColumn; + this._setGroupColumn(this.initialGroupColumn); + } + if (this.initialSorting) { + this._sortColumn = this.initialSorting.column; + this._sortDirection = this.initialSorting.direction; } } @@ -418,6 +426,8 @@ export class HaTabsSubpageDataTable extends LitElement { .sortColumn=${this._sortColumn} .sortDirection=${this._sortDirection} .groupColumn=${this._groupColumn} + .groupOrder=${this.groupOrder} + .initialCollapsedGroups=${this.initialCollapsedGroups} > ${!this.narrow ? html` @@ -496,9 +506,7 @@ export class HaTabsSubpageDataTable extends LitElement { ${this.showFilters && !showPane ? html` ${localize("ui.components.subpage-data-table.filters", { - number: this.data.length, - })}${localize("ui.components.subpage-data-table.filters")} ${this.filters ? html` this._checkVisibility(), diff --git a/src/panels/calendar/dialog-calendar-event-detail.ts b/src/panels/calendar/dialog-calendar-event-detail.ts index 4080c02237..8340b79ba0 100644 --- a/src/panels/calendar/dialog-calendar-event-detail.ts +++ b/src/panels/calendar/dialog-calendar-event-detail.ts @@ -1,7 +1,7 @@ import "@material/mwc-button"; import { mdiCalendarClock } from "@mdi/js"; import { toDate } from "date-fns-tz"; -import { addDays, isSameDay } from "date-fns/esm"; +import { addDays, isSameDay } from "date-fns"; import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { property, state } from "lit/decorators"; import { formatDate } from "../../common/datetime/format_date"; diff --git a/src/panels/calendar/dialog-calendar-event-editor.ts b/src/panels/calendar/dialog-calendar-event-editor.ts index c72d3a6b0e..ad9dfbe9f9 100644 --- a/src/panels/calendar/dialog-calendar-event-editor.ts +++ b/src/panels/calendar/dialog-calendar-event-editor.ts @@ -6,7 +6,7 @@ import { addMilliseconds, differenceInMilliseconds, startOfHour, -} from "date-fns/esm"; +} from "date-fns"; import { HassEntity } from "home-assistant-js-websocket"; import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; diff --git a/src/panels/config/areas/ha-config-areas-dashboard.ts b/src/panels/config/areas/ha-config-areas-dashboard.ts index 1b00b463d8..b63be2f409 100644 --- a/src/panels/config/areas/ha-config-areas-dashboard.ts +++ b/src/panels/config/areas/ha-config-areas-dashboard.ts @@ -511,6 +511,7 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { display: flex; justify-content: space-between; align-items: center; + overflow-wrap: anywhere; } .warning { color: var(--error-color); diff --git a/src/panels/config/automation/ha-automation-picker.ts b/src/panels/config/automation/ha-automation-picker.ts index b48a6dc20f..d11b038beb 100644 --- a/src/panels/config/automation/ha-automation-picker.ts +++ b/src/panels/config/automation/ha-automation-picker.ts @@ -19,7 +19,7 @@ import { mdiToggleSwitchOffOutline, mdiTransitConnection, } from "@mdi/js"; -import { differenceInDays } from "date-fns/esm"; +import { differenceInDays } from "date-fns"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { CSSResultGroup, @@ -37,15 +37,21 @@ import { computeCssColor } from "../../../common/color/compute-color"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { formatShortDateTime } from "../../../common/datetime/format_date_time"; import { relativeTime } from "../../../common/datetime/relative_time"; +import { storage } from "../../../common/decorators/storage"; import { HASSDomEvent, fireEvent } from "../../../common/dom/fire_event"; import { computeStateName } from "../../../common/entity/compute_state_name"; import { navigate } from "../../../common/navigate"; import { LocalizeFunc } from "../../../common/translations/localize"; +import { + hasRejectedItems, + rejectedItems, +} from "../../../common/util/promise-all-settled-results"; import "../../../components/chips/ha-assist-chip"; import type { DataTableColumnContainer, RowClickedEvent, SelectionChangedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/data-table/ha-data-table-labels"; import "../../../components/entity/ha-entity-toggle"; @@ -105,10 +111,6 @@ import { showCategoryRegistryDetailDialog } from "../category/show-dialog-catego import { configSections } from "../ha-panel-config"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; import { showNewAutomationDialog } from "./show-dialog-new-automation"; -import { - hasRejectedItems, - rejectedItems, -} from "../../../common/util/promise-all-settled-results"; type AutomationItem = AutomationEntity & { name: string; @@ -156,6 +158,19 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { @state() private _overflowAutomation?: AutomationItem; + @storage({ key: "automation-table-sort", state: false, subscribe: false }) + private _activeSorting?: SortingChangedEvent; + + @storage({ key: "automation-table-grouping", state: false, subscribe: false }) + private _activeGrouping?: string; + + @storage({ + key: "automation-table-collapsed", + state: false, + subscribe: false, + }) + private _activeCollapsed?: string; + @query("#overflow-menu") private _overflowMenu!: HaMenu; private _sizeController = new ResizeController(this, { @@ -424,9 +439,11 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { ${this.hass.localize("ui.panel.config.labels.add_label")}
`; + const labelsInOverflow = (this._sizeController.value && this._sizeController.value < 700) || (!this._sizeController.value && this.hass.dockedSidebar === "docked"); + const automations = this._automations( this.automations, this._entityReg, @@ -468,7 +485,12 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { this.hass.localize, this.hass.locale )} - initialGroupColumn="category" + .initialGroupColumn=${this._activeGrouping || "category"} + .initialCollapsedGroups=${this._activeCollapsed} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} + @grouping-changed=${this._handleGroupingChanged} + @collapsed-changed=${this._handleCollapseChanged} .data=${automations} .empty=${!this.automations.length} @row-click=${this._handleRowClicked} @@ -1236,6 +1258,18 @@ ${rejected }); } + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + + private _handleGroupingChanged(ev: CustomEvent) { + this._activeGrouping = ev.detail.value; + } + + private _handleCollapseChanged(ev: CustomEvent) { + this._activeCollapsed = ev.detail.value; + } + static get styles(): CSSResultGroup { return [ haStyle, 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 1b94ff6138..fdd239e011 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 @@ -6,6 +6,7 @@ import { fireEvent } from "../../../../../common/dom/fire_event"; import "../../../../../components/device/ha-device-picker"; import "../../../../../components/device/ha-device-trigger-picker"; import "../../../../../components/ha-form/ha-form"; +import { computeInitialHaFormData } from "../../../../../components/ha-form/compute-initial-ha-form-data"; import { fullEntitiesContext } from "../../../../../data/context"; import { deviceAutomationsEqual, @@ -44,7 +45,9 @@ export class HaDeviceTrigger extends LitElement { private _extraFieldsData = memoizeOne( (trigger: DeviceTrigger, capabilities: DeviceCapabilities) => { - const extraFieldsData: Record = {}; + const extraFieldsData = computeInitialHaFormData( + capabilities.extra_fields + ); capabilities.extra_fields.forEach((item) => { if (trigger[item.name] !== undefined) { extraFieldsData![item.name] = trigger[item.name]; diff --git a/src/panels/config/blueprint/ha-blueprint-overview.ts b/src/panels/config/blueprint/ha-blueprint-overview.ts index 1133bf8fa4..45f02be911 100644 --- a/src/panels/config/blueprint/ha-blueprint-overview.ts +++ b/src/panels/config/blueprint/ha-blueprint-overview.ts @@ -24,6 +24,7 @@ import { extractSearchParam } from "../../../common/url/search-params"; import { DataTableColumnContainer, RowClickedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/entity/ha-entity-toggle"; import "../../../components/ha-button"; @@ -54,6 +55,7 @@ import { documentationUrl } from "../../../util/documentation-url"; import { showToast } from "../../../util/toast"; import { configSections } from "../ha-panel-config"; import { showAddBlueprintDialog } from "./show-dialog-import-blueprint"; +import { storage } from "../../../common/decorators/storage"; type BlueprintMetaDataPath = BlueprintMetaData & { path: string; @@ -92,8 +94,24 @@ class HaBlueprintOverview extends LitElement { Blueprints >; + @storage({ key: "blueprint-table-sort", state: false, subscribe: false }) + private _activeSorting?: SortingChangedEvent; + + @storage({ key: "blueprint-table-grouping", state: false, subscribe: false }) + private _activeGrouping?: string; + + @storage({ + key: "blueprint-table-collapsed", + state: false, + subscribe: false, + }) + private _activeCollapsed?: string; + private _processedBlueprints = memoizeOne( - (blueprints: Record): BlueprintMetaDataPath[] => { + ( + blueprints: Record, + localize: LocalizeFunc + ): BlueprintMetaDataPath[] => { const result: any[] = []; Object.entries(blueprints).forEach(([type, typeBlueprints]) => Object.entries(typeBlueprints).forEach(([path, blueprint]) => { @@ -101,6 +119,9 @@ class HaBlueprintOverview extends LitElement { result.push({ name: blueprint.error, type, + translated_type: localize( + `ui.panel.config.blueprint.overview.types.${type as "automation" | "script"}` + ), error: true, path, fullpath: `${type}/${path}`, @@ -109,6 +130,9 @@ class HaBlueprintOverview extends LitElement { result.push({ ...blueprint.metadata, type, + translated_type: localize( + `ui.panel.config.blueprint.overview.types.${type as "automation" | "script"}` + ), error: false, path, fullpath: `${type}/${path}`, @@ -140,14 +164,11 @@ class HaBlueprintOverview extends LitElement { ` : undefined, }, - type: { + translated_type: { title: localize("ui.panel.config.blueprint.overview.headers.type"), - template: (blueprint) => - html`${this.hass.localize( - `ui.panel.config.blueprint.overview.types.${blueprint.type}` - )}`, sortable: true, filterable: true, + groupable: true, hidden: narrow, direction: "asc", width: "10%", @@ -256,7 +277,7 @@ class HaBlueprintOverview extends LitElement { this.hass.language, this.hass.localize )} - .data=${this._processedBlueprints(this.blueprints)} + .data=${this._processedBlueprints(this.blueprints, this.hass.localize)} id="fullpath" .noDataText=${this.hass.localize( "ui.panel.config.blueprint.overview.no_blueprints" @@ -281,6 +302,12 @@ class HaBlueprintOverview extends LitElement { >
`} + .initialGroupColumn=${this._activeGrouping} + .initialCollapsedGroups=${this._activeCollapsed} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} + @grouping-changed=${this._handleGroupingChanged} + @collapsed-changed=${this._handleCollapseChanged} > ) { - const blueprint = this._processedBlueprints(this.blueprints).find( - (b) => b.fullpath === ev.detail.id - )!; + const blueprint = this._processedBlueprints( + this.blueprints, + this.hass.localize + ).find((b) => b.fullpath === ev.detail.id)!; if (blueprint.error) { showAlertDialog(this, { title: this.hass.localize("ui.panel.config.blueprint.overview.error", { @@ -502,6 +530,18 @@ class HaBlueprintOverview extends LitElement { fireEvent(this, "reload-blueprints"); }; + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + + private _handleGroupingChanged(ev: CustomEvent) { + this._activeGrouping = ev.detail.value; + } + + private _handleCollapseChanged(ev: CustomEvent) { + this._activeCollapsed = ev.detail.value; + } + static get styles(): CSSResultGroup { return haStyle; } diff --git a/src/panels/config/cloud/account/cloud-remote-pref.ts b/src/panels/config/cloud/account/cloud-remote-pref.ts index cd9d509f81..508ac04f22 100644 --- a/src/panels/config/cloud/account/cloud-remote-pref.ts +++ b/src/panels/config/cloud/account/cloud-remote-pref.ts @@ -21,6 +21,7 @@ import { import type { HomeAssistant } from "../../../../types"; import { showToast } from "../../../../util/toast"; import { showCloudCertificateDialog } from "../dialog-cloud-certificate/show-dialog-cloud-certificate"; +import { showAlertDialog } from "../../../lovelace/custom-card-helpers"; @customElement("cloud-remote-pref") export class CloudRemotePref extends LitElement { @@ -33,7 +34,7 @@ export class CloudRemotePref extends LitElement { return nothing; } - const { remote_enabled, remote_allow_remote_enable } = + const { remote_enabled, remote_allow_remote_enable, strict_connection } = this.cloudStatus.prefs; const { @@ -153,6 +154,61 @@ export class CloudRemotePref extends LitElement { @change=${this._toggleAllowRemoteEnabledChanged} > + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection" + )} + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_secondary" + )} + + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_modes.disabled" + )} + + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_modes.guard_page" + )} + + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_modes.drop_connection" + )} + + + + ${strict_connection !== "disabled" + ? html` + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_link" + )} + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_link_secondary" + )} + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_create_link" + )} + ` + : nothing} ${this.hass.localize( @@ -223,6 +279,18 @@ export class CloudRemotePref extends LitElement { } } + private async _setStrictConnectionMode(ev) { + const mode = ev.target.value; + try { + await updateCloudPref(this.hass, { + strict_connection: mode, + }); + fireEvent(this, "ha-refresh-cloud-status"); + } catch (err: any) { + alert(err.message); + } + } + private async _copyURL(ev): Promise { const url = ev.currentTarget.url; await copyToClipboard(url); @@ -231,6 +299,40 @@ export class CloudRemotePref extends LitElement { }); } + private async _createLoginUrl() { + try { + const result = await this.hass.callService( + "cloud", + "create_temporary_strict_connection_url", + undefined, + undefined, + false, + true + ); + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_link" + ), + text: html`${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_link_created_message" + )} +
${result.response.url}
+ + + ${this.hass.localize( + "ui.panel.config.cloud.account.remote.strict_connection_copy_link" + )} + `, + }); + } catch (err: any) { + showAlertDialog(this, { text: err.message }); + } + } + static get styles(): CSSResultGroup { return css` .preparing { diff --git a/src/panels/config/core/ha-config-section-general.ts b/src/panels/config/core/ha-config-section-general.ts index 1a8b4a7263..3ccadf595d 100644 --- a/src/panels/config/core/ha-config-section-general.ts +++ b/src/panels/config/core/ha-config-section-general.ts @@ -1,7 +1,6 @@ import "@material/mwc-list/mwc-list-item"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; -import memoizeOne from "memoize-one"; import { UNIT_C } from "../../../common/const"; import { stopPropagation } from "../../../common/dom/stop_propagation"; import { navigate } from "../../../common/navigate"; @@ -22,8 +21,6 @@ import "../../../components/ha-settings-row"; import "../../../components/ha-textfield"; import type { HaTextField } from "../../../components/ha-textfield"; import "../../../components/ha-timezone-picker"; -import "../../../components/map/ha-locations-editor"; -import type { MarkerLocation } from "../../../components/map/ha-locations-editor"; import { ConfigUpdateValues, saveCoreConfig } from "../../../data/core"; import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-subpage"; @@ -242,35 +239,22 @@ class HaConfigSectionGeneral extends LitElement { >
- ${this.narrow - ? html` - - ` - : html` - -
- ${this.hass.localize( - "ui.panel.config.core.section.core.core_config.edit_location" - )} -
-
- ${this.hass.localize( - "ui.panel.config.core.section.core.core_config.edit_location_description" - )} -
- ${this.hass.localize("ui.common.edit")} -
- `} + + +
+ ${this.hass.localize( + "ui.panel.config.core.section.core.core_config.edit_location" + )} +
+
+ ${this.hass.localize( + "ui.panel.config.core.section.core.core_config.edit_location_description" + )} +
+ ${this.hass.localize("ui.common.edit")} +
${this.hass!.localize("ui.panel.config.zone.detail.update")} @@ -319,10 +303,6 @@ class HaConfigSectionGeneral extends LitElement { this._updateUnits = (ev.target as HaCheckbox).checked; } - private _locationChanged(ev: CustomEvent) { - this._location = ev.detail.location; - } - private async _updateEntry(ev: CustomEvent) { const button = ev.target as HaProgressButton; if (button.progress) { @@ -381,21 +361,6 @@ class HaConfigSectionGeneral extends LitElement { } } - private _markerLocation = memoizeOne( - ( - lat: number, - lng: number, - location?: [number, number] - ): MarkerLocation[] => [ - { - id: "location", - latitude: location ? location[0] : lat, - longitude: location ? location[1] : lng, - location_editable: true, - }, - ] - ); - private _editLocation() { navigate("/config/zone/edit/zone.home"); } @@ -441,11 +406,6 @@ class HaConfigSectionGeneral extends LitElement { margin-top: 8px; display: inline-block; } - ha-locations-editor { - display: block; - height: 400px; - padding: 16px; - } `, ]; } diff --git a/src/panels/config/core/ha-config-section-updates.ts b/src/panels/config/core/ha-config-section-updates.ts index 6493cd1456..cdf7d896fa 100644 --- a/src/panels/config/core/ha-config-section-updates.ts +++ b/src/panels/config/core/ha-config-section-updates.ts @@ -82,11 +82,11 @@ class HaConfigSectionUpdates extends LitElement { > ${this.hass.localize("ui.panel.config.updates.show_skipped")} - ${this._supervisorInfo?.channel !== "dev" + ${this._supervisorInfo && this._supervisorInfo.channel !== "dev" ? html`
  • - ${this._supervisorInfo?.channel === "stable" + ${this._supervisorInfo.channel === "stable" ? this.hass.localize("ui.panel.config.updates.join_beta") : this.hass.localize( "ui.panel.config.updates.leave_beta" diff --git a/src/panels/config/dashboard/ha-config-dashboard.ts b/src/panels/config/dashboard/ha-config-dashboard.ts index 918b8c888e..9e4562f9a4 100644 --- a/src/panels/config/dashboard/ha-config-dashboard.ts +++ b/src/panels/config/dashboard/ha-config-dashboard.ts @@ -93,10 +93,19 @@ const randomTip = (hass: HomeAssistant, narrow: boolean) => { weight: 2, narrow: true, }, - { content: hass.localize("ui.tips.key_c_hint"), weight: 1, narrow: false }, - { content: hass.localize("ui.tips.key_m_hint"), weight: 1, narrow: false }, ]; + if (hass?.enableShortcuts) { + tips.push( + { + content: hass.localize("ui.tips.key_c_hint"), + weight: 1, + narrow: false, + }, + { content: hass.localize("ui.tips.key_m_hint"), weight: 1, narrow: false } + ); + } + if (narrow) { tips = tips.filter((tip) => tip.narrow); } @@ -310,7 +319,9 @@ class HaConfigDashboard extends SubscribeMixin(LitElement) { private _showQuickBar(): void { showQuickBar(this, { commandMode: true, - hint: this.hass.localize("ui.dialogs.quick-bar.key_c_hint"), + hint: this.hass.enableShortcuts + ? this.hass.localize("ui.dialogs.quick-bar.key_c_hint") + : undefined, }); } diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index e834e453fc..5d714d763b 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -1,6 +1,12 @@ import { consume } from "@lit-labs/context"; import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; -import { mdiChevronRight, mdiMenuDown, mdiPlus } from "@mdi/js"; +import { + mdiChevronRight, + mdiDotsVertical, + mdiMenuDown, + mdiPlus, + mdiTextureBox, +} from "@mdi/js"; import { CSSResultGroup, LitElement, @@ -10,10 +16,12 @@ import { nothing, } from "lit"; +import { ResizeController } from "@lit-labs/observers/resize-controller"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { computeCssColor } from "../../../common/color/compute-color"; +import { storage } from "../../../common/decorators/storage"; import { HASSDomEvent } from "../../../common/dom/fire_event"; import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { @@ -22,10 +30,15 @@ import { } from "../../../common/integrations/protocolIntegrationPicked"; import { navigate } from "../../../common/navigate"; import { LocalizeFunc } from "../../../common/translations/localize"; +import { + hasRejectedItems, + rejectedItems, +} from "../../../common/util/promise-all-settled-results"; import { DataTableColumnContainer, RowClickedEvent, SelectionChangedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/data-table/ha-data-table-labels"; import "../../../components/entity/ha-battery-icon"; @@ -41,6 +54,7 @@ import "../../../components/ha-filter-states"; import "../../../components/ha-icon-button"; import "../../../components/ha-menu-item"; import "../../../components/ha-sub-menu"; +import { createAreaRegistryEntry } from "../../../data/area_registry"; import { ConfigEntry, sortConfigEntries } from "../../../data/config_entries"; import { fullEntitiesContext } from "../../../data/context"; import { @@ -65,15 +79,12 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant, Route } from "../../../types"; import { brandsUrl } from "../../../util/brands-url"; +import { showAreaRegistryDetailDialog } from "../areas/show-dialog-area-registry-detail"; import { configSections } from "../ha-panel-config"; import "../integrations/ha-integration-overflow-menu"; import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; -import { - hasRejectedItems, - rejectedItems, -} from "../../../common/util/promise-all-settled-results"; -import { showAlertDialog } from "../../lovelace/custom-card-helpers"; +import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; interface DeviceRowData extends DeviceRegistryEntry { device?: DeviceRowData; @@ -117,6 +128,19 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) { @state() _labels!: LabelRegistryEntry[]; + @storage({ key: "devices-table-sort", state: false, subscribe: false }) + private _activeSorting?: SortingChangedEvent; + + @storage({ key: "devices-table-grouping", state: false, subscribe: false }) + private _activeGrouping?: string; + + @storage({ key: "devices-table-collapsed", state: false, subscribe: false }) + private _activeCollapsed?: string; + + private _sizeController = new ResizeController(this, { + callback: (entries) => entries[0]?.contentRect.width, + }); + private _ignoreLocationChange = false; public connectedCallback() { @@ -549,6 +573,41 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) { this._labels ); + const areasInOverflow = + (this._sizeController.value && this._sizeController.value < 700) || + (!this._sizeController.value && this.hass.dockedSidebar === "docked"); + + const areaItems = html`${Object.values(this.hass.areas).map( + (area) => + html` + ${area.icon + ? html`` + : html``} +
    ${area.name}
    +
    ` + )} + +
    + ${this.hass.localize( + "ui.panel.config.devices.picker.bulk_actions.no_area" + )} +
    +
    + + +
    + ${this.hass.localize( + "ui.panel.config.devices.picker.bulk_actions.add_area" + )} +
    +
    `; + const labelItems = html`${this._labels?.map((label) => { const color = label.color ? computeCssColor(label.color) : undefined; const selected = this._selected.every((deviceId) => @@ -614,8 +673,14 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) { Array.isArray(val) ? val.length : val ) ).length} + .initialGroupColumn=${this._activeGrouping} + .initialCollapsedGroups=${this._activeCollapsed} + .initialSorting=${this._activeSorting} @clear-filter=${this._clearFilter} @search-changed=${this._handleSearchChange} + @sorting-changed=${this._handleSortingChanged} + @grouping-changed=${this._handleGroupingChanged} + @collapsed-changed=${this._handleCollapseChanged} @row-click=${this._handleRowClicked} clickable hasFab @@ -684,36 +749,77 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) { ${!this.narrow ? html` - - - - ${labelItems} - ` - : html` - - + + + + ${labelItems} + + + ${areasInOverflow + ? nothing + : html` + + + + ${areaItems} + `}` + : nothing} + ${this.narrow || areasInOverflow + ? html` + ${this.narrow + ? html` + + ` + : html``} + ${this.narrow + ? html` + +
    + ${this.hass.localize( + "ui.panel.config.automation.picker.bulk_actions.add_label" + )} +
    + +
    + ${labelItems} +
    ` + : nothing}
    ${this.hass.localize( - "ui.panel.config.automation.picker.bulk_actions.add_label" + "ui.panel.config.devices.picker.bulk_actions.move_area" )}
    - ${labelItems} + ${areaItems}
    -
    `} + ` + : nothing} `; } @@ -809,6 +916,46 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) { this._selected = ev.detail.value; } + private async _handleBulkArea(ev) { + const area = ev.currentTarget.value; + this._bulkAddArea(area); + } + + private async _bulkAddArea(area: string) { + const promises: Promise[] = []; + this._selected.forEach((deviceId) => { + promises.push( + updateDeviceRegistryEntry(this.hass, deviceId, { + area_id: area, + }) + ); + }); + const result = await Promise.allSettled(promises); + if (hasRejectedItems(result)) { + const rejected = rejectedItems(result); + showAlertDialog(this, { + title: this.hass.localize("ui.panel.config.common.multiselect.failed", { + number: rejected.length, + }), + text: html`
    +${rejected
    +            .map((r) => r.reason.message || r.reason.code || r.reason)
    +            .join("\r\n")}
    `, + }); + } + } + + private async _bulkCreateArea() { + showAreaRegistryDetailDialog(this, { + createEntry: async (values) => { + const area = await createAreaRegistryEntry(this.hass, values); + this._bulkAddArea(area.area_id); + return area; + }, + }); + } + private async _handleBulkLabel(ev) { const label = ev.currentTarget.value; const action = ev.currentTarget.action; @@ -855,9 +1002,24 @@ ${rejected }); } + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + + private _handleGroupingChanged(ev: CustomEvent) { + this._activeGrouping = ev.detail.value; + } + + private _handleCollapseChanged(ev: CustomEvent) { + this._activeCollapsed = ev.detail.value; + } + static get styles(): CSSResultGroup { return [ css` + :host { + display: block; + } hass-tabs-subpage-data-table { --data-table-row-height: 60px; } diff --git a/src/panels/config/energy/components/ha-energy-device-settings.ts b/src/panels/config/energy/components/ha-energy-device-settings.ts index a9e3e41a77..8c6d3506e7 100644 --- a/src/panels/config/energy/components/ha-energy-device-settings.ts +++ b/src/panels/config/energy/components/ha-energy-device-settings.ts @@ -1,5 +1,5 @@ import "@material/mwc-button/mwc-button"; -import { mdiDelete, mdiDevices } from "@mdi/js"; +import { mdiDelete, mdiDevices, mdiPencil } from "@mdi/js"; import { CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; import { fireEvent } from "../../../../common/dom/fire_event"; @@ -83,18 +83,24 @@ export class EnergyDeviceSettings extends LitElement { ${this.preferences.device_consumption.map((device) => { const entityState = this.hass.states[device.stat_consumption]; return html` -
    +
    ${getStatisticLabel( + >${device.name || + getStatisticLabel( this.hass, device.stat_consumption, this.statsMetadata?.[device.stat_consumption] )} + { + await this._savePreferences({ + ...this.preferences, + device_consumption: this.preferences.device_consumption.map((d) => + d === origDevice ? newDevice : d + ), + }); + }, + }); + } + private _addDevice() { showEnergySettingsDeviceDialog(this, { device_consumptions: this.preferences diff --git a/src/panels/config/energy/dialogs/dialog-energy-device-settings.ts b/src/panels/config/energy/dialogs/dialog-energy-device-settings.ts index fba35d8334..1362dfbdb3 100644 --- a/src/panels/config/energy/dialogs/dialog-energy-device-settings.ts +++ b/src/panels/config/energy/dialogs/dialog-energy-device-settings.ts @@ -44,9 +44,10 @@ export class DialogEnergyDeviceSettings this._energy_units = ( await getSensorDeviceClassConvertibleUnits(this.hass, "energy") ).units; - this._excludeList = this._params.device_consumptions.map( - (entry) => entry.stat_consumption - ); + this._device = this._params.device; + this._excludeList = this._params.device_consumptions + .map((entry) => entry.stat_consumption) + .filter((id) => id !== this._device?.stat_consumption); } public closeDialog(): void { @@ -88,6 +89,7 @@ export class DialogEnergyDeviceSettings .hass=${this.hass} .helpMissingEntityUrl=${energyStatisticHelpUrl} .includeUnitClass=${energyUnitClasses} + .value=${this._device?.stat_consumption} .label=${this.hass.localize( "ui.panel.config.energy.device_consumption.dialog.device_consumption_energy" )} @@ -96,6 +98,17 @@ export class DialogEnergyDeviceSettings dialogInitialFocus > + + + ${this.hass.localize("ui.common.cancel")} @@ -118,6 +131,17 @@ export class DialogEnergyDeviceSettings this._device = { stat_consumption: ev.detail.value }; } + private _nameChanged(ev) { + const newDevice = { + ...this._device!, + name: ev.target!.value, + } as DeviceConsumptionEnergyPreference; + if (!newDevice.name) { + delete newDevice.name; + } + this._device = newDevice; + } + private async _save() { try { await this._params!.saveCallback(this._device!); @@ -134,6 +158,10 @@ export class DialogEnergyDeviceSettings ha-statistic-picker { width: 100%; } + ha-textfield { + margin-top: 16px; + width: 100%; + } `, ]; } diff --git a/src/panels/config/energy/dialogs/show-dialogs-energy.ts b/src/panels/config/energy/dialogs/show-dialogs-energy.ts index 997999a69c..246ac05c23 100644 --- a/src/panels/config/energy/dialogs/show-dialogs-energy.ts +++ b/src/panels/config/energy/dialogs/show-dialogs-energy.ts @@ -70,6 +70,7 @@ export interface EnergySettingsWaterDialogParams { } export interface EnergySettingsDeviceDialogParams { + device?: DeviceConsumptionEnergyPreference; device_consumptions: DeviceConsumptionEnergyPreference[]; saveCallback: (device: DeviceConsumptionEnergyPreference) => Promise; } diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index 50aa67a862..1e8d9a6db4 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -29,6 +29,7 @@ import { ifDefined } from "lit/directives/if-defined"; import { styleMap } from "lit/directives/style-map"; import memoize from "memoize-one"; import { computeCssColor } from "../../../common/color/compute-color"; +import { storage } from "../../../common/decorators/storage"; import type { HASSDomEvent } from "../../../common/dom/fire_event"; import { computeDomain } from "../../../common/entity/compute_domain"; import { computeStateName } from "../../../common/entity/compute_state_name"; @@ -37,10 +38,15 @@ import { protocolIntegrationPicked, } from "../../../common/integrations/protocolIntegrationPicked"; import { LocalizeFunc } from "../../../common/translations/localize"; +import { + hasRejectedItems, + rejectedItems, +} from "../../../common/util/promise-all-settled-results"; import type { DataTableColumnContainer, RowClickedEvent, SelectionChangedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/data-table/ha-data-table-labels"; import "../../../components/ha-alert"; @@ -66,6 +72,11 @@ import { removeEntityRegistryEntry, updateEntityRegistryEntry, } from "../../../data/entity_registry"; +import { + EntitySources, + fetchEntitySourcesWithCache, +} from "../../../data/entity_sources"; +import { domainToName } from "../../../data/integration"; import { LabelRegistryEntry, createLabelRegistryEntry, @@ -86,14 +97,6 @@ import { configSections } from "../ha-panel-config"; import "../integrations/ha-integration-overflow-menu"; import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; -import { - EntitySources, - fetchEntitySourcesWithCache, -} from "../../../data/entity_sources"; -import { - hasRejectedItems, - rejectedItems, -} from "../../../common/util/promise-all-settled-results"; export interface StateEntity extends Omit { @@ -110,6 +113,7 @@ export interface EntityRow extends StateEntity { status: string | undefined; area?: string; localized_platform: string; + domain: string; label_entries: LabelRegistryEntry[]; } @@ -149,6 +153,19 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { @state() private _entitySources?: EntitySources; + @storage({ key: "entities-table-sort", state: false, subscribe: false }) + private _activeSorting?: SortingChangedEvent; + + @storage({ key: "entities-table-grouping", state: false, subscribe: false }) + private _activeGrouping?: string; + + @storage({ + key: "entities-table-collapsed", + state: false, + subscribe: false, + }) + private _activeCollapsed?: string; + @query("hass-tabs-subpage-data-table", true) private _dataTable!: HaTabsSubpageDataTable; @@ -261,6 +278,13 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { filterable: true, width: "20%", }, + domain: { + title: localize("ui.panel.config.entities.picker.headers.domain"), + sortable: false, + hidden: true, + filterable: true, + groupable: true, + }, area: { title: localize("ui.panel.config.entities.picker.headers.area"), sortable: true, @@ -467,9 +491,9 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { ), unavailable, restored, - localized_platform: - localize(`component.${entry.platform}.title`) || entry.platform, + localized_platform: domainToName(localize, entry.platform), area: area ? area.name : "—", + domain: domainToName(localize, computeDomain(entry.entity_id)), status: restored ? localize("ui.panel.config.entities.picker.status.restored") : unavailable @@ -594,6 +618,12 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { .filter=${this._filter} selectable .selected=${this._selected.length} + .initialGroupColumn=${this._activeGrouping} + .initialCollapsedGroups=${this._activeCollapsed} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} + @grouping-changed=${this._handleGroupingChanged} + @collapsed-changed=${this._handleCollapseChanged} @selection-changed=${this._handleSelectionChanged} clickable @clear-filter=${this._clearFilter} @@ -1196,6 +1226,18 @@ ${rejected }); } + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + + private _handleGroupingChanged(ev: CustomEvent) { + this._activeGrouping = ev.detail.value; + } + + private _handleCollapseChanged(ev: CustomEvent) { + this._activeCollapsed = ev.detail.value; + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/helpers/dialog-helper-detail.ts b/src/panels/config/helpers/dialog-helper-detail.ts index 5e9a6e07d6..54488dccec 100644 --- a/src/panels/config/helpers/dialog-helper-detail.ts +++ b/src/panels/config/helpers/dialog-helper-detail.ts @@ -32,7 +32,7 @@ import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-c import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; import { brandsUrl } from "../../../util/brands-url"; -import { Helper, HelperDomain } from "./const"; +import { Helper, HelperDomain, isHelperDomain } from "./const"; import type { ShowDialogHelperDetailParams } from "./show-dialog-helper-detail"; type HelperCreators = { @@ -96,7 +96,7 @@ export class DialogHelperDetail extends LitElement { @state() private _opened = false; - @state() private _domain?: HelperDomain; + @state() private _domain?: string; @state() private _error?: string; @@ -114,8 +114,12 @@ export class DialogHelperDetail extends LitElement { this._params = params; this._domain = params.domain; this._item = undefined; + if (this._domain && this._domain in HELPERS) { + await HELPERS[this._domain].import(); + } this._opened = true; await this.updateComplete; + this.hass.loadFragmentTranslation("config"); Promise.all([ getConfigFlowHandlers(this.hass, ["helper"]), // Ensure the titles are loaded before we render the flows. @@ -141,7 +145,7 @@ export class DialogHelperDetail extends LitElement { if (this._domain) { content = html`
    - ${this._error ? html`
    ${this._error}
    ` : ""} + ${this._error ? html`
    ${this._error}
    ` : ""} ${dynamicElement(`ha-${this._domain}-form`, { hass: this.hass, item: this._item, @@ -155,13 +159,15 @@ export class DialogHelperDetail extends LitElement { > ${this.hass!.localize("ui.panel.config.helpers.dialog.create")} - - ${this.hass!.localize("ui.common.back")} - + ${this._params?.domain + ? nothing + : html` + ${this.hass!.localize("ui.common.back")} + `} `; } else if (this._loading || this._helperFlows === undefined) { content = html`; @@ -525,7 +540,12 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { ).length} .columns=${this._columns(this.narrow, this.hass.localize)} .data=${helpers} - initialGroupColumn="category" + .initialGroupColumn=${this._activeGrouping || "category"} + .initialCollapsedGroups=${this._activeCollapsed} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} + @grouping-changed=${this._handleGroupingChanged} + @collapsed-changed=${this._handleCollapseChanged} .activeFilters=${this._activeFilters} @clear-filter=${this._clearFilter} @row-click=${this._openEditDialog} @@ -1020,6 +1040,18 @@ ${rejected }); } + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + + private _handleGroupingChanged(ev: CustomEvent) { + this._activeGrouping = ev.detail.value; + } + + private _handleCollapseChanged(ev: CustomEvent) { + this._activeCollapsed = ev.detail.value; + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/helpers/show-dialog-helper-detail.ts b/src/panels/config/helpers/show-dialog-helper-detail.ts index da1942c108..ee5acaf8c8 100644 --- a/src/panels/config/helpers/show-dialog-helper-detail.ts +++ b/src/panels/config/helpers/show-dialog-helper-detail.ts @@ -1,13 +1,14 @@ import { fireEvent } from "../../../common/dom/fire_event"; -import { DataEntryFlowDialogParams } from "../../../dialogs/config-flow/show-dialog-data-entry-flow"; -import { HelperDomain } from "./const"; export const loadHelperDetailDialog = () => import("./dialog-helper-detail"); export interface ShowDialogHelperDetailParams { - domain?: HelperDomain; - // Only used for config entries - dialogClosedCallback?: DataEntryFlowDialogParams["dialogClosedCallback"]; + domain?: string; + dialogClosedCallback?: (params: { + flowFinished: boolean; + entryId?: string; + entityId?: string; + }) => void; } export const showHelperDetailDialog = ( diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index 5f0b01f2a0..674a720c05 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -37,6 +37,7 @@ import { } from "lit"; import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; +import { until } from "lit/directives/until"; import memoizeOne from "memoize-one"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isDevVersion } from "../../../common/config/version"; @@ -550,10 +551,24 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { `ui.panel.config.integrations.config_entry.state.${item.state}`, ]; if (item.reason) { - this.hass.loadBackendTranslation("config", item.domain); - stateTextExtra = html`${this.hass.localize( - `component.${item.domain}.config.error.${item.reason}` - ) || item.reason}`; + if (item.error_reason_translation_key) { + const lokalisePromExc = this.hass + .loadBackendTranslation("exceptions", item.domain) + .then((localize) => + localize( + `component.${item.domain}.exceptions.${item.error_reason_translation_key}.message`, + item.error_reason_translation_placeholders ?? undefined + ) + ); + stateTextExtra = html`${until(lokalisePromExc)}`; + } else { + const lokalisePromError = this.hass + .loadBackendTranslation("config", item.domain) + .then((localize) => + localize(`component.${item.domain}.config.error.${item.reason}`) + ); + stateTextExtra = html`${until(lokalisePromError, item.reason)}`; + } } else { stateTextExtra = html`
    diff --git a/src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts b/src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts index 575587aeaa..7520d95502 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts @@ -238,6 +238,9 @@ export class ZHANetworkVisualizationPage extends LitElement { label: this._buildLabel(device), shape: this._getShape(device), mass: this._getMass(device), + color: { + background: device.available ? "#66FF99" : "#FF9999", + }, }); if (device.neighbors && device.neighbors.length > 0) { device.neighbors.forEach((neighbor) => { @@ -249,13 +252,29 @@ export class ZHANetworkVisualizationPage extends LitElement { from: device.ieee, to: neighbor.ieee, label: neighbor.lqi + "", - color: this._getLQI(parseInt(neighbor.lqi)), + color: this._getLQI(parseInt(neighbor.lqi)).color, + width: this._getLQI(parseInt(neighbor.lqi)).width, + length: 2000 - 4 * parseInt(neighbor.lqi), + arrows: { + from: { + enabled: neighbor.relationship !== "Child", + }, + }, + dashes: neighbor.relationship !== "Child", }); } else { edges[idx].color = this._getLQI( (parseInt(edges[idx].label!) + parseInt(neighbor.lqi)) / 2 - ); + ).color; + edges[idx].width = this._getLQI( + (parseInt(edges[idx].label!) + parseInt(neighbor.lqi)) / 2 + ).width; + edges[idx].length = + 2000 - + 6 * ((parseInt(edges[idx].label!) + parseInt(neighbor.lqi)) / 2); edges[idx].label += "/" + neighbor.lqi; + delete edges[idx].arrows; + delete edges[idx].dashes; } }); } @@ -264,20 +283,23 @@ export class ZHANetworkVisualizationPage extends LitElement { this._network?.setData({ nodes: this._nodes, edges: edges }); } - private _getLQI(lqi: number): EdgeOptions["color"] { + private _getLQI(lqi: number): EdgeOptions { if (lqi > 192) { - return { color: "#17ab00", highlight: "#17ab00" }; + return { color: { color: "#17ab00", highlight: "#17ab00" }, width: 4 }; } if (lqi > 128) { - return { color: "#e6b402", highlight: "#e6b402" }; + return { color: { color: "#e6b402", highlight: "#e6b402" }, width: 3 }; } if (lqi > 80) { - return { color: "#fc4c4c", highlight: "#fc4c4c" }; + return { color: { color: "#fc4c4c", highlight: "#fc4c4c" }, width: 2 }; } - return { color: "#bfbfbf", highlight: "#bfbfbf" }; + return { color: { color: "#bfbfbf", highlight: "#bfbfbf" }, width: 1 }; } private _getMass(device: ZHADevice): number { + if (!device.available) { + return 6; + } if (device.device_type === "Coordinator") { return 2; } @@ -312,8 +334,8 @@ export class ZHANetworkVisualizationPage extends LitElement { } else { label += "\nDevice is not in 'zigbee.db'"; } - if (!device.available) { - label += "\nDevice is Offline"; + if (device.area_id) { + label += `\nArea ID: ${device.area_id}`; } return label; } @@ -402,7 +424,7 @@ export class ZHANetworkVisualizationPage extends LitElement { ? { physics: { barnesHut: { - springConstant: 0, + springConstant: 0.05, avoidOverlap: 10, damping: 0.09, }, diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts index a8a3d6cbd8..90b440dcff 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts @@ -235,7 +235,7 @@ class ZWaveJSNodeConfig extends SubscribeMixin(LitElement) { ${item.metadata.label} - ${item.metadata.description || item.metadata.label} + ${item.metadata.description} ${item.metadata.description !== null && !item.metadata.writeable ? html`
    ` : nothing} diff --git a/src/panels/config/labels/dialog-label-detail.ts b/src/panels/config/labels/dialog-label-detail.ts index b0e0638627..bffc5d79c0 100644 --- a/src/panels/config/labels/dialog-label-detail.ts +++ b/src/panels/config/labels/dialog-label-detail.ts @@ -7,6 +7,7 @@ import { createCloseHeading } from "../../../components/ha-dialog"; import "../../../components/ha-formfield"; import "../../../components/ha-switch"; import "../../../components/ha-textfield"; +import "../../../components/ha-textarea"; import "../../../components/ha-icon-picker"; import "../../../components/ha-color-picker"; import { HassDialog } from "../../../dialogs/make-dialog-manager"; @@ -31,6 +32,8 @@ class DialogLabelDetail @state() private _color!: string; + @state() private _description!: string; + @state() private _error?: string; @state() private _params?: LabelDetailDialogParams; @@ -44,10 +47,12 @@ class DialogLabelDetail this._name = this._params.entry.name || ""; this._icon = this._params.entry.icon || ""; this._color = this._params.entry.color || ""; + this._description = this._params.entry.description || ""; } else { this._name = this._params.suggestedName || ""; this._icon = ""; this._color = ""; + this._description = ""; } document.body.addEventListener("keydown", this._handleKeyPress); } @@ -118,6 +123,14 @@ class DialogLabelDetail "ui.panel.config.labels.detail.color" )} > +
    ${this._params.entry && this._params.removeEntry @@ -169,6 +182,7 @@ class DialogLabelDetail name: this._name.trim(), icon: this._icon.trim() || null, color: this._color.trim() || null, + description: this._description.trim() || null, }; if (this._params!.entry) { newValue = await this._params!.updateEntry!(values); @@ -202,12 +216,14 @@ class DialogLabelDetail a { color: var(--primary-color); } + ha-textarea, ha-textfield, ha-icon-picker, ha-color-picker { display: block; } - ha-color-picker { + ha-color-picker, + ha-textarea { margin-top: 16px; } `, diff --git a/src/panels/config/labels/ha-config-labels.ts b/src/panels/config/labels/ha-config-labels.ts index f8396ada5e..43f346ce6a 100644 --- a/src/panels/config/labels/ha-config-labels.ts +++ b/src/panels/config/labels/ha-config-labels.ts @@ -10,15 +10,17 @@ import { LitElement, PropertyValues, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { computeCssColor } from "../../../common/color/compute-color"; +import { navigate } from "../../../common/navigate"; import { LocalizeFunc } from "../../../common/translations/localize"; import { DataTableColumnContainer, RowClickedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/ha-fab"; import "../../../components/ha-icon-button"; -import "../../../components/ha-relative-time"; import "../../../components/ha-icon-overflow-menu"; +import "../../../components/ha-relative-time"; import { LabelRegistryEntry, LabelRegistryEntryMutableParams, @@ -35,7 +37,7 @@ import "../../../layouts/hass-tabs-subpage-data-table"; import { HomeAssistant, Route } from "../../../types"; import { configSections } from "../ha-panel-config"; import { showLabelDetailDialog } from "./show-dialog-label-detail"; -import { navigate } from "../../../common/navigate"; +import { storage } from "../../../common/decorators/storage"; @customElement("ha-config-labels") export class HaConfigLabels extends LitElement { @@ -49,6 +51,13 @@ export class HaConfigLabels extends LitElement { @state() private _labels: LabelRegistryEntry[] = []; + @storage({ + key: "labels-table-sort", + state: false, + subscribe: false, + }) + private _activeSorting?: SortingChangedEvent; + private _columns = memoizeOne((localize: LocalizeFunc) => { const columns: DataTableColumnContainer = { icon: { @@ -79,6 +88,12 @@ export class HaConfigLabels extends LitElement { sortable: true, filterable: true, grows: true, + template: (label) => html` +
    ${label.name}
    + ${label.description + ? html`
    ${label.description}
    ` + : nothing} + `, }, actions: { title: "", @@ -143,6 +158,8 @@ export class HaConfigLabels extends LitElement { .data=${this._data(this._labels)} .noDataText=${this.hass.localize("ui.panel.config.labels.no_labels")} hasFab + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} @row-click=${this._editLabel} clickable id="label_id" @@ -262,6 +279,10 @@ export class HaConfigLabels extends LitElement { `/config/automation/dashboard?historyBack=1&label=${label.label_id}` ); } + + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } } declare global { diff --git a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts index c393cd0ced..a089218c8c 100644 --- a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts +++ b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts @@ -16,6 +16,7 @@ import { stringCompare } from "../../../../common/string/compare"; import { DataTableColumnContainer, RowClickedEvent, + SortingChangedEvent, } from "../../../../components/data-table/ha-data-table"; import "../../../../components/ha-clickable-list-item"; import "../../../../components/ha-fab"; @@ -46,6 +47,7 @@ import { showNewDashboardDialog } from "../../dashboard/show-dialog-new-dashboar import { lovelaceTabs } from "../ha-config-lovelace"; import { showDashboardConfigureStrategyDialog } from "./show-dialog-lovelace-dashboard-configure-strategy"; import { showDashboardDetailDialog } from "./show-dialog-lovelace-dashboard-detail"; +import { storage } from "../../../../common/decorators/storage"; type DataTableItem = Pick< LovelaceDashboard, @@ -68,6 +70,13 @@ export class HaConfigLovelaceDashboards extends LitElement { @state() private _dashboards: LovelaceDashboard[] = []; + @storage({ + key: "lovelace-dashboards-table-sort", + state: false, + subscribe: false, + }) + private _activeSorting?: SortingChangedEvent; + public willUpdate() { if (!this.hasUpdated) { this.hass.loadFragmentTranslation("lovelace"); @@ -293,6 +302,8 @@ export class HaConfigLovelaceDashboards extends LitElement { this.hass.localize )} .data=${this._getItems(this._dashboards)} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} @row-click=${this._editDashboard} id="url_path" hasFab @@ -440,6 +451,10 @@ export class HaConfigLovelaceDashboards extends LitElement { }, }); } + + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } } declare global { diff --git a/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts b/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts index 273713b950..3131af913e 100644 --- a/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts +++ b/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts @@ -10,9 +10,11 @@ import { import { customElement, property, state } from "lit/decorators"; import memoize from "memoize-one"; import { stringCompare } from "../../../../common/string/compare"; +import { LocalizeFunc } from "../../../../common/translations/localize"; import { DataTableColumnContainer, RowClickedEvent, + SortingChangedEvent, } from "../../../../components/data-table/ha-data-table"; import "../../../../components/ha-card"; import "../../../../components/ha-fab"; @@ -33,10 +35,10 @@ import "../../../../layouts/hass-subpage"; import "../../../../layouts/hass-tabs-subpage-data-table"; import { haStyle } from "../../../../resources/styles"; import { HomeAssistant, Route } from "../../../../types"; -import { LocalizeFunc } from "../../../../common/translations/localize"; import { loadLovelaceResources } from "../../../lovelace/common/load-resources"; import { lovelaceResourcesTabs } from "../ha-config-lovelace"; import { showResourceDetailDialog } from "./show-dialog-lovelace-resource-detail"; +import { storage } from "../../../../common/decorators/storage"; @customElement("ha-config-lovelace-resources") export class HaConfigLovelaceRescources extends LitElement { @@ -50,6 +52,13 @@ export class HaConfigLovelaceRescources extends LitElement { @state() private _resources: LovelaceResource[] = []; + @storage({ + key: "lovelace-resources-table-sort", + state: false, + subscribe: false, + }) + private _activeSorting?: SortingChangedEvent; + private _columns = memoize( ( _language, @@ -127,6 +136,8 @@ export class HaConfigLovelaceRescources extends LitElement { .noDataText=${this.hass.localize( "ui.panel.config.lovelace.resources.picker.no_resources" )} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} @row-click=${this._editResource} hasFab clickable @@ -237,6 +248,10 @@ export class HaConfigLovelaceRescources extends LitElement { }); } + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/scene/ha-scene-dashboard.ts b/src/panels/config/scene/ha-scene-dashboard.ts index fbbe1cc334..c77bb1fb50 100644 --- a/src/panels/config/scene/ha-scene-dashboard.ts +++ b/src/panels/config/scene/ha-scene-dashboard.ts @@ -16,7 +16,7 @@ import { mdiPlus, mdiTag, } from "@mdi/js"; -import { differenceInDays } from "date-fns/esm"; +import { differenceInDays } from "date-fns"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { CSSResultGroup, @@ -32,14 +32,20 @@ import memoizeOne from "memoize-one"; import { computeCssColor } from "../../../common/color/compute-color"; import { formatShortDateTime } from "../../../common/datetime/format_date_time"; import { relativeTime } from "../../../common/datetime/relative_time"; +import { storage } from "../../../common/decorators/storage"; import { HASSDomEvent, fireEvent } from "../../../common/dom/fire_event"; import { computeStateName } from "../../../common/entity/compute_state_name"; import { navigate } from "../../../common/navigate"; import { LocalizeFunc } from "../../../common/translations/localize"; +import { + hasRejectedItems, + rejectedItems, +} from "../../../common/util/promise-all-settled-results"; import { DataTableColumnContainer, RowClickedEvent, SelectionChangedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/data-table/ha-data-table-labels"; import "../../../components/ha-button"; @@ -95,10 +101,6 @@ import { showAssignCategoryDialog } from "../category/show-dialog-assign-categor import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail"; import { configSections } from "../ha-panel-config"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; -import { - hasRejectedItems, - rejectedItems, -} from "../../../common/util/promise-all-settled-results"; type SceneItem = SceneEntity & { name: string; @@ -144,6 +146,19 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) { @consume({ context: fullEntitiesContext, subscribe: true }) _entityReg!: EntityRegistryEntry[]; + @storage({ key: "scene-table-sort", state: false, subscribe: false }) + private _activeSorting?: SortingChangedEvent; + + @storage({ key: "scene-table-grouping", state: false, subscribe: false }) + private _activeGrouping?: string; + + @storage({ + key: "scene-table-collapsed", + state: false, + subscribe: false, + }) + private _activeCollapsed?: string; + private _sizeController = new ResizeController(this, { callback: (entries) => entries[0]?.contentRect.width, }); @@ -463,7 +478,12 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) { ).length} .columns=${this._columns(this.narrow, this.hass.localize)} id="entity_id" - initialGroupColumn="category" + .initialGroupColumn=${this._activeGrouping || "category"} + .initialCollapsedGroups=${this._activeCollapsed} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} + @grouping-changed=${this._handleGroupingChanged} + @collapsed-changed=${this._handleCollapseChanged} .data=${scenes} .empty=${!this.scenes.length} .activeFilters=${this._activeFilters} @@ -975,6 +995,18 @@ ${rejected }); } + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + + private _handleGroupingChanged(ev: CustomEvent) { + this._activeGrouping = ev.detail.value; + } + + private _handleCollapseChanged(ev: CustomEvent) { + this._activeCollapsed = ev.detail.value; + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/script/ha-script-picker.ts b/src/panels/config/script/ha-script-picker.ts index b6ae00c012..2d8f5e70c1 100644 --- a/src/panels/config/script/ha-script-picker.ts +++ b/src/panels/config/script/ha-script-picker.ts @@ -15,7 +15,7 @@ import { mdiTag, mdiTransitConnection, } from "@mdi/js"; -import { differenceInDays } from "date-fns/esm"; +import { differenceInDays } from "date-fns"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { CSSResultGroup, @@ -33,14 +33,20 @@ import { computeCssColor } from "../../../common/color/compute-color"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { formatShortDateTime } from "../../../common/datetime/format_date_time"; import { relativeTime } from "../../../common/datetime/relative_time"; +import { storage } from "../../../common/decorators/storage"; import { HASSDomEvent, fireEvent } from "../../../common/dom/fire_event"; import { computeStateName } from "../../../common/entity/compute_state_name"; import { navigate } from "../../../common/navigate"; import { LocalizeFunc } from "../../../common/translations/localize"; +import { + hasRejectedItems, + rejectedItems, +} from "../../../common/util/promise-all-settled-results"; import { DataTableColumnContainer, RowClickedEvent, SelectionChangedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/data-table/ha-data-table-labels"; import "../../../components/ha-fab"; @@ -97,10 +103,6 @@ import { showAssignCategoryDialog } from "../category/show-dialog-assign-categor import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail"; import { configSections } from "../ha-panel-config"; import { showLabelDetailDialog } from "../labels/show-dialog-label-detail"; -import { - hasRejectedItems, - rejectedItems, -} from "../../../common/util/promise-all-settled-results"; type ScriptItem = ScriptEntity & { name: string; @@ -148,6 +150,19 @@ class HaScriptPicker extends SubscribeMixin(LitElement) { @consume({ context: fullEntitiesContext, subscribe: true }) _entityReg!: EntityRegistryEntry[]; + @storage({ key: "script-table-sort", state: false, subscribe: false }) + private _activeSorting?: SortingChangedEvent; + + @storage({ key: "script-table-grouping", state: false, subscribe: false }) + private _activeGrouping?: string; + + @storage({ + key: "script-table-collapsed", + state: false, + subscribe: false, + }) + private _activeCollapsed?: string; + private _sizeController = new ResizeController(this, { callback: (entries) => entries[0]?.contentRect.width, }); @@ -462,7 +477,12 @@ class HaScriptPicker extends SubscribeMixin(LitElement) { { number: scripts.length } )} hasFilters - initialGroupColumn="category" + .initialGroupColumn=${this._activeGrouping || "category"} + .initialCollapsedGroups=${this._activeCollapsed} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} + @grouping-changed=${this._handleGroupingChanged} + @collapsed-changed=${this._handleCollapseChanged} selectable .selected=${this._selected.length} @selection-changed=${this._handleSelectionChanged} @@ -1091,6 +1111,18 @@ ${rejected }); } + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + + private _handleGroupingChanged(ev: CustomEvent) { + this._activeGrouping = ev.detail.value; + } + + private _handleCollapseChanged(ev: CustomEvent) { + this._activeCollapsed = ev.detail.value; + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/users/ha-config-users.ts b/src/panels/config/users/ha-config-users.ts index 2512e0d3d1..a99d3ccf03 100644 --- a/src/panels/config/users/ha-config-users.ts +++ b/src/panels/config/users/ha-config-users.ts @@ -7,6 +7,7 @@ import { LocalizeFunc } from "../../../common/translations/localize"; import { DataTableColumnContainer, RowClickedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/data-table/ha-data-table-icon"; import "../../../components/ha-fab"; @@ -25,6 +26,7 @@ import { HomeAssistant, Route } from "../../../types"; import { configSections } from "../ha-panel-config"; import { showAddUserDialog } from "./show-dialog-add-user"; import { showUserDetailDialog } from "./show-dialog-user-detail"; +import { storage } from "../../../common/decorators/storage"; @customElement("ha-config-users") export class HaConfigUsers extends LitElement { @@ -38,6 +40,19 @@ export class HaConfigUsers extends LitElement { @state() private _users: User[] = []; + @storage({ key: "users-table-sort", state: false, subscribe: false }) + private _activeSorting?: SortingChangedEvent; + + @storage({ key: "users-table-grouping", state: false, subscribe: false }) + private _activeGrouping?: string; + + @storage({ + key: "users-table-collapsed", + state: false, + subscribe: false, + }) + private _activeCollapsed?: string; + private _columns = memoizeOne( (narrow: boolean, localize: LocalizeFunc): DataTableColumnContainer => { const columns: DataTableColumnContainer = { @@ -70,16 +85,14 @@ export class HaConfigUsers extends LitElement { hidden: narrow, template: (user) => html`${user.username || "—"}`, }, - group_ids: { + group: { title: localize("ui.panel.config.users.picker.headers.group"), sortable: true, filterable: true, + groupable: true, width: "20%", direction: "asc", hidden: narrow, - template: (user) => html` - ${localize(`groups.${user.group_ids[0]}`)} - `, }, is_active: { title: this.hass.localize( @@ -164,7 +177,13 @@ export class HaConfigUsers extends LitElement { backPath="/config" .tabs=${configSections.persons} .columns=${this._columns(this.narrow, this.hass.localize)} - .data=${this._users} + .data=${this._userData(this._users, this.hass.localize)} + .initialGroupColumn=${this._activeGrouping} + .initialCollapsedGroups=${this._activeCollapsed} + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} + @grouping-changed=${this._handleGroupingChanged} + @collapsed-changed=${this._handleCollapseChanged} @row-click=${this._editUser} hasFab clickable @@ -181,6 +200,13 @@ export class HaConfigUsers extends LitElement { `; } + private _userData = memoizeOne((users: User[], localize: LocalizeFunc) => + users.map((user) => ({ + ...user, + group: localize(`groups.${user.group_ids[0]}`), + })) + ); + private async _fetchUsers() { this._users = await fetchUsers(this.hass); @@ -245,6 +271,18 @@ export class HaConfigUsers extends LitElement { }, }); } + + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + + private _handleGroupingChanged(ev: CustomEvent) { + this._activeGrouping = ev.detail.value; + } + + private _handleCollapseChanged(ev: CustomEvent) { + this._activeCollapsed = ev.detail.value; + } } declare global { diff --git a/src/panels/config/voice-assistants/ha-config-voice-assistants-expose.ts b/src/panels/config/voice-assistants/ha-config-voice-assistants-expose.ts index c64ea12cef..68caa31338 100644 --- a/src/panels/config/voice-assistants/ha-config-voice-assistants-expose.ts +++ b/src/panels/config/voice-assistants/ha-config-voice-assistants-expose.ts @@ -23,6 +23,7 @@ import { DataTableRowData, RowClickedEvent, SelectionChangedEvent, + SortingChangedEvent, } from "../../../components/data-table/ha-data-table"; import "../../../components/ha-fab"; import { AlexaEntity, fetchCloudAlexaEntities } from "../../../data/alexa"; @@ -52,6 +53,7 @@ import "./expose/expose-assistant-icon"; import { voiceAssistantTabs } from "./ha-config-voice-assistants"; import { showExposeEntityDialog } from "./show-dialog-expose-entity"; import { showVoiceSettingsDialog } from "./show-dialog-voice-settings"; +import { storage } from "../../../common/decorators/storage"; @customElement("ha-config-voice-assistants-expose") export class VoiceAssistantsExpose extends LitElement { @@ -87,6 +89,13 @@ export class VoiceAssistantsExpose extends LitElement { string[] | undefined >; + @storage({ + key: "voice-expose-table-sort", + state: false, + subscribe: false, + }) + private _activeSorting?: SortingChangedEvent; + @query("hass-tabs-subpage-data-table", true) private _dataTable!: HaTabsSubpageDataTable; @@ -505,6 +514,8 @@ export class VoiceAssistantsExpose extends LitElement { selectable .selected=${this._selectedEntities.length} clickable + .initialSorting=${this._activeSorting} + @sorting-changed=${this._handleSortingChanged} @selection-changed=${this._handleSelectionChanged} @clear-filter=${this._clearFilter} @search-changed=${this._handleSearchChange} @@ -696,6 +707,10 @@ export class VoiceAssistantsExpose extends LitElement { navigate(window.location.pathname, { replace: true }); } + private _handleSortingChanged(ev: CustomEvent) { + this._activeSorting = ev.detail; + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/zone/dialog-home-zone-detail.ts b/src/panels/config/zone/dialog-home-zone-detail.ts new file mode 100644 index 0000000000..2786cca3cb --- /dev/null +++ b/src/panels/config/zone/dialog-home-zone-detail.ts @@ -0,0 +1,150 @@ +import "@material/mwc-button"; +import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../../../common/dom/fire_event"; +import { createCloseHeading } from "../../../components/ha-dialog"; +import "../../../components/ha-form/ha-form"; +import { HomeZoneMutableParams } from "../../../data/zone"; +import { haStyleDialog } from "../../../resources/styles"; +import { HomeAssistant } from "../../../types"; +import { HomeZoneDetailDialogParams } from "./show-dialog-home-zone-detail"; + +const SCHEMA = [ + { + name: "location", + required: true, + selector: { location: { radius: true, radius_readonly: true } }, + }, +]; + +class DialogHomeZoneDetail extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @state() private _error?: Record; + + @state() private _data?: HomeZoneMutableParams; + + @state() private _params?: HomeZoneDetailDialogParams; + + @state() private _submitting = false; + + public showDialog(params: HomeZoneDetailDialogParams): void { + this._params = params; + this._error = undefined; + this._data = { + latitude: this.hass.config.latitude, + longitude: this.hass.config.longitude, + }; + } + + public closeDialog(): void { + this._params = undefined; + this._data = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + protected render() { + if (!this._params || !this._data) { + return nothing; + } + const latInvalid = String(this._data.latitude) === ""; + const lngInvalid = String(this._data.longitude) === ""; + + const valid = !latInvalid && !lngInvalid; + + return html` + +
    + +

    + ${this.hass!.localize( + "ui.panel.config.zone.detail.no_edit_home_zone_radius" + )} +

    +
    + + ${this.hass!.localize("ui.panel.config.zone.detail.update")} + +
    + `; + } + + private _formData = memoizeOne((data: HomeZoneMutableParams) => ({ + ...data, + location: { + latitude: data.latitude, + longitude: data.longitude, + radius: this.hass.states["zone.home"]?.attributes?.radius || 100, + }, + })); + + private _valueChanged(ev: CustomEvent) { + this._error = undefined; + const value = { ...ev.detail.value }; + value.latitude = value.location.latitude; + value.longitude = value.location.longitude; + delete value.location; + this._data = value; + } + + private _computeLabel = (): string => ""; + + private async _updateEntry() { + this._submitting = true; + try { + await this._params!.updateEntry!(this._data!); + this.closeDialog(); + } catch (err: any) { + this._error = { base: err ? err.message : "Unknown error" }; + } finally { + this._submitting = false; + } + } + + static get styles(): CSSResultGroup { + return [ + haStyleDialog, + css` + ha-dialog { + --mdc-dialog-min-width: min(600px, 95vw); + } + @media all and (max-width: 450px), all and (max-height: 500px) { + ha-dialog { + --mdc-dialog-min-width: calc( + 100vw - env(safe-area-inset-right) - env(safe-area-inset-left) + ); + } + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-home-zone-detail": DialogHomeZoneDetail; + } +} + +customElements.define("dialog-home-zone-detail", DialogHomeZoneDetail); diff --git a/src/panels/config/zone/dialog-zone-detail.ts b/src/panels/config/zone/dialog-zone-detail.ts index 37432c6b8f..064bf61fa7 100644 --- a/src/panels/config/zone/dialog-zone-detail.ts +++ b/src/panels/config/zone/dialog-zone-detail.ts @@ -145,30 +145,8 @@ class DialogZoneDetail extends LitElement { required: true, selector: { location: { radius: true, icon } }, }, - { - name: "", - type: "grid", - schema: [ - { - name: "latitude", - required: true, - selector: { number: {} }, - }, - { - name: "longitude", - required: true, - - selector: { number: {} }, - }, - ], - }, { name: "passive_note", type: "constant" }, { name: "passive", selector: { boolean: {} } }, - { - name: "radius", - required: false, - selector: { number: { min: 0, max: 999999, mode: "box" } }, - }, ] as const ); @@ -184,15 +162,9 @@ class DialogZoneDetail extends LitElement { private _valueChanged(ev: CustomEvent) { this._error = undefined; const value = { ...ev.detail.value }; - if ( - value.location.latitude !== this._data!.latitude || - value.location.longitude !== this._data!.longitude || - value.location.radius !== this._data!.radius - ) { - value.latitude = value.location.latitude; - value.longitude = value.location.longitude; - value.radius = Math.round(value.location.radius); - } + value.latitude = value.location.latitude; + value.longitude = value.location.longitude; + value.radius = value.location.radius; delete value.location; if (!value.icon) { delete value.icon; diff --git a/src/panels/config/zone/ha-config-zone.ts b/src/panels/config/zone/ha-config-zone.ts index 2455bf2b48..8e8b4c2414 100644 --- a/src/panels/config/zone/ha-config-zone.ts +++ b/src/panels/config/zone/ha-config-zone.ts @@ -1,25 +1,26 @@ -import { mdiCog, mdiPencil, mdiPencilOff, mdiPlus } from "@mdi/js"; -import "@polymer/paper-item/paper-icon-item"; -import "@polymer/paper-item/paper-item-body"; -import "@polymer/paper-listbox/paper-listbox"; import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; +import "@material/mwc-list/mwc-list"; +import { mdiPencil, mdiPencilOff, mdiPlus } from "@mdi/js"; import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket"; import { - css, CSSResultGroup, - html, LitElement, PropertyValues, TemplateResult, + css, + html, + nothing, } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { computeStateDomain } from "../../../common/entity/compute_state_domain"; +import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { navigate } from "../../../common/navigate"; import { stringCompare } from "../../../common/string/compare"; import "../../../components/ha-card"; import "../../../components/ha-fab"; import "../../../components/ha-icon-button"; +import "../../../components/ha-list-item"; import "../../../components/ha-svg-icon"; import "../../../components/map/ha-locations-editor"; import type { @@ -29,12 +30,13 @@ import type { import { saveCoreConfig } from "../../../data/core"; import { subscribeEntityRegistry } from "../../../data/entity_registry"; import { + HomeZoneMutableParams, + Zone, + ZoneMutableParams, createZone, deleteZone, fetchZones, updateZone, - Zone, - ZoneMutableParams, } from "../../../data/zone"; import { showAlertDialog, @@ -46,6 +48,7 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import type { HomeAssistant, Route } from "../../../types"; import "../ha-config-section"; import { configSections } from "../ha-panel-config"; +import { showHomeZoneDetailDialog } from "./show-dialog-home-zone-detail"; import { showZoneDetailDialog } from "./show-dialog-zone-detail"; @customElement("ha-config-zone") @@ -143,77 +146,95 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
    ` : html` - + ${this._storageItems.map( (entry) => html` - - - ${entry.name} + + ${entry.name} ${!this.narrow ? html` - +
    + +
    ` : ""} -
    + ` )} ${this._stateItems.map( (stateObject) => html` - - - ${stateObject.attributes.friendly_name || - stateObject.entity_id} - -
    - - ${stateObject.entity_id !== "zone.home" - ? html` - - ${hass.localize( - "ui.panel.config.zone.configured_in_yaml" - )} - - ` - : ""} -
    -
    + + ${stateObject.attributes.friendly_name || + stateObject.entity_id} + ${this.narrow && + stateObject.entity_id === "zone.home" && + !this._canEditCore + ? nothing + : html`
    + + ${stateObject.entity_id !== "zone.home" + ? html` + + ${hass.localize( + "ui.panel.config.zone.configured_in_yaml" + )} + + ` + : ""} +
    `} + ` )} -
    + `; return html` @@ -286,7 +307,11 @@ export class HaConfigZone extends SubscribeMixin(LitElement) { return; } const id = this.route.path.slice(6); + this._editZone(id); navigate("/config/zone", { replace: true }); + if (this.narrow) { + return; + } this._zoomZone(id); } @@ -375,32 +400,52 @@ export class HaConfigZone extends SubscribeMixin(LitElement) { this._openDialog(); } - private _itemClicked(ev: Event) { + private _itemClicked(ev: CustomEvent) { + if (!shouldHandleRequestSelectedEvent(ev)) { + return; + } + if (this.narrow) { this._openEditEntry(ev); return; } - const entry: Zone = (ev.currentTarget! as any).entry; - this._zoomZone(entry.id); + const entryId: string = (ev.currentTarget! as any).value; + this._zoomZone(entryId); + this._activeEntry = entryId; } - private _stateItemClicked(ev: Event) { - const entityId = (ev.currentTarget! as HTMLElement).getAttribute( - "data-id" - )!; - this._zoomZone(entityId); + private _stateItemClicked(ev: CustomEvent) { + if (!shouldHandleRequestSelectedEvent(ev)) { + return; + } + + const entryId: string = (ev.currentTarget! as any).value; + + if (this.narrow && entryId === "zone.home") { + this._editHomeZone(ev); + return; + } + + this._zoomZone(entryId); + this._activeEntry = entryId; } private async _zoomZone(id: string) { this._map?.fitMarker(id); } + private async _editZone(id: string) { + await this.updateComplete; + (this.shadowRoot?.querySelector(`[id="${id}"]`) as HTMLElement)?.click(); + } + private _openEditEntry(ev: Event) { const entry: Zone = (ev.currentTarget! as any).entry; this._openDialog(entry); + ev.stopPropagation(); } - private async _openCoreConfig(ev) { + private async _editHomeZone(ev) { if (ev.currentTarget.noEdit) { showAlertDialog(this, { title: this.hass.localize("ui.panel.config.zone.can_not_edit"), @@ -409,7 +454,9 @@ export class HaConfigZone extends SubscribeMixin(LitElement) { }); return; } - navigate("/config/general"); + showHomeZoneDetailDialog(this, { + updateEntry: (values) => this._updateHomeZoneEntry(values), + }); } private async _createEntry(values: ZoneMutableParams) { @@ -427,6 +474,14 @@ export class HaConfigZone extends SubscribeMixin(LitElement) { this._map?.fitMarker(created.id); } + private async _updateHomeZoneEntry(values: HomeZoneMutableParams) { + await saveCoreConfig(this.hass, { + latitude: values.latitude, + longitude: values.longitude, + }); + this._zoomZone("zone.home"); + } + private async _updateEntry( entry: Zone, values: Partial, @@ -485,6 +540,9 @@ export class HaConfigZone extends SubscribeMixin(LitElement) { --app-header-background-color: var(--sidebar-background-color); --app-header-text-color: var(--sidebar-text-color); } + ha-list-item { + --mdc-list-item-meta-size: 48px; + } a { color: var(--primary-color); } @@ -515,40 +573,16 @@ export class HaConfigZone extends SubscribeMixin(LitElement) { flex-grow: 1; height: 100%; } - .flex paper-listbox, + .flex mwc-list, .flex .empty { border-left: 1px solid var(--divider-color); width: 250px; min-height: 100%; box-sizing: border-box; } - paper-icon-item { - padding-top: 4px; - padding-bottom: 4px; - cursor: pointer; - } - .overflow paper-icon-item:last-child { - margin-bottom: 80px; - } - paper-icon-item.iron-selected:before { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - pointer-events: none; - content: ""; - background-color: var(--sidebar-selected-icon-color); - opacity: 0.12; - transition: opacity 15ms linear; - will-change: opacity; - } ha-card { margin-bottom: 100px; } - ha-card paper-item { - cursor: pointer; - } `; } } diff --git a/src/panels/config/zone/show-dialog-home-zone-detail.ts b/src/panels/config/zone/show-dialog-home-zone-detail.ts new file mode 100644 index 0000000000..a4dc6c12c6 --- /dev/null +++ b/src/panels/config/zone/show-dialog-home-zone-detail.ts @@ -0,0 +1,20 @@ +import { fireEvent } from "../../../common/dom/fire_event"; +import { HomeZoneMutableParams } from "../../../data/zone"; + +export interface HomeZoneDetailDialogParams { + updateEntry?: (updates: HomeZoneMutableParams) => Promise; +} + +export const loadHomeZoneDetailDialog = () => + import("./dialog-home-zone-detail"); + +export const showHomeZoneDetailDialog = ( + element: HTMLElement, + params: HomeZoneDetailDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "dialog-home-zone-detail", + dialogImport: loadHomeZoneDetailDialog, + dialogParams: params, + }); +}; diff --git a/src/panels/developer-tools/assist/developer-tools-assist.ts b/src/panels/developer-tools/assist/developer-tools-assist.ts index 5d050d4ceb..ed99e6bb79 100644 --- a/src/panels/developer-tools/assist/developer-tools-assist.ts +++ b/src/panels/developer-tools/assist/developer-tools-assist.ts @@ -92,7 +92,9 @@ class HaPanelDevAssist extends SubscribeMixin(LitElement) { private async _fetchLanguages() { const { agents } = await listAgents(this.hass); - const assistAgent = agents.find((agent) => agent.id === "homeassistant"); + const assistAgent = agents.find( + (agent) => agent.id === "conversation.home_assistant" + ); this.supportedLanguages = assistAgent?.supported_languages === "*" ? undefined diff --git a/src/panels/developer-tools/ha-panel-developer-tools.ts b/src/panels/developer-tools/ha-panel-developer-tools.ts index 52e98b3770..667f016ea5 100644 --- a/src/panels/developer-tools/ha-panel-developer-tools.ts +++ b/src/panels/developer-tools/ha-panel-developer-tools.ts @@ -131,6 +131,8 @@ class PanelDeveloperTools extends LitElement { padding-top: env(safe-area-inset-top); color: var(--app-header-text-color, white); border-bottom: var(--app-header-border-bottom, none); + -webkit-backdrop-filter: var(--app-header-backdrop-filter, none); + backdrop-filter: var(--app-header-backdrop-filter, none); } .toolbar { height: var(--header-height); diff --git a/src/panels/developer-tools/state/developer-tools-state.ts b/src/panels/developer-tools/state/developer-tools-state.ts index dc7f04ed6a..ebeb324f2a 100644 --- a/src/panels/developer-tools/state/developer-tools-state.ts +++ b/src/panels/developer-tools/state/developer-tools-state.ts @@ -3,7 +3,7 @@ import { mdiInformationOutline, mdiRefresh, } from "@mdi/js"; -import { addHours } from "date-fns/esm"; +import { addHours } from "date-fns"; import { HassEntities, HassEntity, @@ -128,9 +128,11 @@ class HaPanelDevState extends LitElement { allow-custom-entity item-label-path="entity_id" > - ${this.hass.localize("ui.tips.key_e_hint")} + ${this.hass.enableShortcuts + ? html`${this.hass.localize("ui.tips.key_e_hint")}` + : nothing} { + const domain = computeDomain(stateObj.entity_id); + return domain === "lock"; +}; + +@customElement("hui-lock-commands-card-feature") +class HuiLockCommandsCardFeature + extends LitElement + implements LovelaceCardFeature +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public stateObj?: HassEntity; + + @state() private _config?: LockCommandsCardFeatureConfig; + + static getStubConfig(): LockCommandsCardFeatureConfig { + return { + type: "lock-commands", + }; + } + + public setConfig(config: LockCommandsCardFeatureConfig): void { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + } + + private _onTap(ev): void { + ev.stopPropagation(); + const service = ev.target.dataset.service; + if (!this.hass || !this.stateObj || !service) { + return; + } + forwardHaptic("light"); + callProtectedLockService(this, this.hass, this.stateObj, service); + } + + protected render() { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsLockCommandsCardFeature(this.stateObj) + ) { + return nothing; + } + + return html` + + + + + + + + + `; + } + + static get styles(): CSSResultGroup { + return css` + @keyframes pulse { + 0% { + opacity: 1; + } + 50% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + .pulse { + animation: pulse 1s infinite; + } + ha-control-button-group { + margin: 0 12px 12px 12px; + --control-button-group-spacing: 12px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-lock-commands-card-feature": HuiLockCommandsCardFeature; + } +} diff --git a/src/panels/lovelace/card-features/hui-lock-open-door-card-feature.ts b/src/panels/lovelace/card-features/hui-lock-open-door-card-feature.ts new file mode 100644 index 0000000000..4b13e44323 --- /dev/null +++ b/src/panels/lovelace/card-features/hui-lock-open-door-card-feature.ts @@ -0,0 +1,158 @@ +import { mdiCheck } from "@mdi/js"; +import { HassEntity } from "home-assistant-js-websocket"; +import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { computeDomain } from "../../../common/entity/compute_domain"; + +import { supportsFeature } from "../../../common/entity/supports-feature"; +import "../../../components/ha-control-button"; +import "../../../components/ha-control-button-group"; +import { + LockEntityFeature, + callProtectedLockService, + isAvailable, +} from "../../../data/lock"; +import { HomeAssistant } from "../../../types"; +import { LovelaceCardFeature } from "../types"; +import { LockOpenDoorCardFeatureConfig } from "./types"; + +export const supportsLockOpenDoorCardFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return domain === "lock" && supportsFeature(stateObj, LockEntityFeature.OPEN); +}; + +const CONFIRM_TIMEOUT_SECOND = 5; +const OPENED_TIMEOUT_SECOND = 3; + +type ButtonState = "normal" | "confirm" | "success"; + +@customElement("hui-lock-open-door-card-feature") +class HuiLockOpenDoorCardFeature + extends LitElement + implements LovelaceCardFeature +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public stateObj?: HassEntity; + + @state() public _buttonState: ButtonState = "normal"; + + @state() private _config?: LockOpenDoorCardFeatureConfig; + + private _buttonTimeout?: number; + + static getStubConfig(): LockOpenDoorCardFeatureConfig { + return { + type: "lock-open-door", + }; + } + + public setConfig(config: LockOpenDoorCardFeatureConfig): void { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + } + + private _setButtonState(buttonState: ButtonState, timeoutSecond?: number) { + clearTimeout(this._buttonTimeout); + this._buttonState = buttonState; + if (timeoutSecond) { + this._buttonTimeout = window.setTimeout(() => { + this._buttonState = "normal"; + }, timeoutSecond * 1000); + } + } + + private async _open() { + if (this._buttonState !== "confirm") { + this._setButtonState("confirm", CONFIRM_TIMEOUT_SECOND); + return; + } + if (!this.hass || !this.stateObj) { + return; + } + callProtectedLockService(this, this.hass, this.stateObj!, "open"); + + this._setButtonState("success", OPENED_TIMEOUT_SECOND); + } + + protected render() { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsLockOpenDoorCardFeature(this.stateObj) + ) { + return nothing; + } + + return html` + ${this._buttonState === "success" + ? html` +
    +

    + + ${this.hass.localize("ui.card.lock.open_door_success")} +

    +
    + ` + : html` + + + ${this._buttonState === "confirm" + ? this.hass.localize("ui.card.lock.open_door_confirm") + : this.hass.localize("ui.card.lock.open_door")} + + + `} + `; + } + + static get styles(): CSSResultGroup { + return css` + .buttons { + display: flex; + align-items: center; + justify-content: center; + margin-top: 0; + } + ha-control-button { + font-size: 14px; + } + ha-control-button-group { + margin: 0 12px 12px 12px; + --control-button-group-spacing: 12px; + } + .open-button { + width: 130px; + } + .open-button.confirm { + --control-button-background-color: var(--warning-color); + } + .open-success { + font-size: 14px; + line-height: 14px; + display: flex; + align-items: center; + flex-direction: row; + gap: 8px; + font-weight: 500; + color: var(--success-color); + } + ha-control-button-group + ha-attributes:not([empty]) { + margin-top: 16px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-lock-open-door-card-feature": HuiLockOpenDoorCardFeature; + } +} diff --git a/src/panels/lovelace/card-features/types.ts b/src/panels/lovelace/card-features/types.ts index 7b3771a2d8..82fa311876 100644 --- a/src/panels/lovelace/card-features/types.ts +++ b/src/panels/lovelace/card-features/types.ts @@ -26,6 +26,14 @@ export interface LightColorTempCardFeatureConfig { type: "light-color-temp"; } +export interface LockCommandsCardFeatureConfig { + type: "lock-commands"; +} + +export interface LockOpenDoorCardFeatureConfig { + type: "lock-open-door"; +} + export interface FanPresetModesCardFeatureConfig { type: "fan-preset-modes"; style?: "dropdown" | "icons"; @@ -143,6 +151,8 @@ export type LovelaceCardFeatureConfig = | LawnMowerCommandsCardFeatureConfig | LightBrightnessCardFeatureConfig | LightColorTempCardFeatureConfig + | LockCommandsCardFeatureConfig + | LockOpenDoorCardFeatureConfig | NumericInputCardFeatureConfig | SelectOptionsCardFeatureConfig | TargetHumidityCardFeatureConfig diff --git a/src/panels/lovelace/cards/energy/common/energy-chart-options.ts b/src/panels/lovelace/cards/energy/common/energy-chart-options.ts index ef6c04677e..5063de0215 100644 --- a/src/panels/lovelace/cards/energy/common/energy-chart-options.ts +++ b/src/panels/lovelace/cards/energy/common/energy-chart-options.ts @@ -5,7 +5,7 @@ import { subHours, differenceInDays, differenceInHours, -} from "date-fns/esm"; +} from "date-fns"; import { FrontendLocaleData } from "../../../../../data/translation"; import { formatNumber, diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts index c2565d7c97..95944eff0a 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-devices-detail-graph-card.ts @@ -4,7 +4,7 @@ import { ChartOptions, ScatterDataPoint, } from "chart.js"; -import { endOfToday, startOfToday } from "date-fns/esm"; +import { endOfToday, startOfToday } from "date-fns"; import { HassConfig, UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, @@ -333,11 +333,13 @@ export class HuiEnergyDevicesDetailGraphCard ); data.push({ - label: getStatisticLabel( - this.hass, - source.stat_consumption, - statisticsMetaData[source.stat_consumption] - ), + label: + source.name || + getStatisticLabel( + this.hass, + source.stat_consumption, + statisticsMetaData[source.stat_consumption] + ), hidden: this._hiddenStats.has(source.stat_consumption) || itemExceedsMax, borderColor: compare ? color + "7F" : color, diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts index 95604e45bb..83d287b8ea 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts @@ -127,11 +127,7 @@ export class HuiEnergyDevicesGraphCard const statisticId = ( this._chartData.datasets[0].data[index] as ScatterDataPoint ).y; - return getStatisticLabel( - this.hass, - statisticId as any, - this._data?.statsMetadata[statisticId] - ); + return this.getDeviceName(statisticId as any as string); }, }, }, @@ -149,11 +145,7 @@ export class HuiEnergyDevicesGraphCard callbacks: { title: (item) => { const statisticId = item[0].label; - return getStatisticLabel( - this.hass, - statisticId, - this._data?.statsMetadata[statisticId] - ); + return this.getDeviceName(statisticId); }, label: (context) => `${context.dataset.label}: ${formatNumber( @@ -181,6 +173,19 @@ export class HuiEnergyDevicesGraphCard }) ); + private getDeviceName(statisticId: string): string { + return ( + this._data?.prefs.device_consumption.find( + (d) => d.stat_consumption === statisticId + )?.name || + getStatisticLabel( + this.hass, + statisticId, + this._data?.statsMetadata[statisticId] + ) + ); + } + private async _getStatistics(energyData: EnergyData): Promise { const data = energyData.stats; const compareData = energyData.statsCompare; 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 40d91584dc..f6abc48b18 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 @@ -4,12 +4,7 @@ import { ChartOptions, ScatterDataPoint, } from "chart.js"; -import { - differenceInDays, - endOfToday, - isToday, - startOfToday, -} from "date-fns/esm"; +import { differenceInDays, endOfToday, isToday, startOfToday } from "date-fns"; import { HassConfig, UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, 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 4cdd7eb1b0..573afe4bde 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,7 +4,7 @@ import { ChartOptions, ScatterDataPoint, } from "chart.js"; -import { endOfToday, isToday, startOfToday } from "date-fns/esm"; +import { endOfToday, isToday, startOfToday } from "date-fns"; import { HassConfig, UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, diff --git a/src/panels/lovelace/cards/hui-iframe-card.ts b/src/panels/lovelace/cards/hui-iframe-card.ts index c64cb2bf24..7b48888191 100644 --- a/src/panels/lovelace/cards/hui-iframe-card.ts +++ b/src/panels/lovelace/cards/hui-iframe-card.ts @@ -98,7 +98,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard { title=${ifDefined(this._config.title)} src=${this._config.url} .sandbox=${`${sandbox_user_params} ${IFRAME_SANDBOX}`} - allow="fullscreen" + allow=${this._config.allow ?? "fullscreen"} >
    diff --git a/src/panels/lovelace/cards/hui-stack-card.ts b/src/panels/lovelace/cards/hui-stack-card.ts index b7b8e7758c..7a9940e635 100644 --- a/src/panels/lovelace/cards/hui-stack-card.ts +++ b/src/panels/lovelace/cards/hui-stack-card.ts @@ -7,6 +7,7 @@ import { nothing, } from "lit"; import { property, state } from "lit/decorators"; +import { fireEvent } from "../../../common/dom/fire_event"; import { LovelaceCardConfig } from "../../../data/lovelace/config/card"; import { HomeAssistant } from "../../../types"; import { createCardElement } from "../create-element/create-card-element"; @@ -119,6 +120,7 @@ export abstract class HuiStackCard (ev) => { ev.stopPropagation(); this._rebuildCard(element, cardConfig); + fireEvent(this, "ll-rebuild"); }, { once: true } ); diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index abb180dd35..2a08ce8f75 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -245,6 +245,14 @@ export class HuiTileCard extends LitElement implements LovelaceCard { > `; } + if (content === "last_triggered") { + return html` + + `; + } if (stateObj.attributes[content] == null) { return undefined; } diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index 8fcf28ab4e..0ae62e6aea 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -281,6 +281,7 @@ export interface IframeCardConfig extends LovelaceCardConfig { allow_open_top_navigation?: boolean; aspect_ratio?: string; title?: string; + allow?: string; url: string; } @@ -487,61 +488,6 @@ export interface WeatherForecastCardConfig extends LovelaceCardConfig { double_tap_action?: ActionConfig; } -export interface EnergyFlowCardConfig extends LovelaceCardConfig { - type: string; - name?: string; - show_header_toggle?: boolean; - - show_warning?: boolean; - show_error?: boolean; - test_gui?: boolean; - show_w_not_kw?: any; - hide_inactive_lines?: boolean; - threshold_in_k?: number; - energy_flow_diagramm?: boolean; - energy_flow_diagramm_lines_factor?: number; - change_house_bubble_color_with_flow?: boolean; - - grid_icon?: string; - generation_icon?: string; - house_icon?: string; - battery_icon?: string; - appliance1_icon?: string; - appliance2_icon?: string; - - icon_entities?: Map; - line_entities?: Map; - - house_entity?: string; - battery_entity?: string; - generation_entity?: string; - grid_entity?: string; - - grid_to_house_entity?: string; - grid_to_battery_entity?: string; - - generation_to_grid_entity?: string; - generation_to_battery_entity?: string; - generation_to_house_entity?: string; - - battery_to_house_entity?: string; - battery_to_grid_entity?: string; - - grid_extra_entity?: string; - generation_extra_entity?: string; - house_extra_entity?: string; - battery_extra_entity?: string; - - appliance1_consumption_entity?: string; - appliance1_extra_entity?: string; - appliance2_consumption_entity?: string; - appliance2_extra_entity?: string; - - tap_action?: ActionConfig; - hold_action?: ActionConfig; - double_tap_action?: ActionConfig; -} - export interface TileCardConfig extends LovelaceCardConfig { entity: string; name?: string; diff --git a/src/panels/lovelace/components/hui-energy-period-selector.ts b/src/panels/lovelace/components/hui-energy-period-selector.ts index 0da7b83907..11e8635607 100644 --- a/src/panels/lovelace/components/hui-energy-period-selector.ts +++ b/src/panels/lovelace/components/hui-energy-period-selector.ts @@ -20,7 +20,7 @@ import { startOfWeek, startOfYear, subDays, -} from "date-fns/esm"; +} from "date-fns"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { CSSResultGroup, 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 4054f4610e..2710c69ebf 100644 --- a/src/panels/lovelace/create-element/create-card-feature-element.ts +++ b/src/panels/lovelace/create-element/create-card-feature-element.ts @@ -14,6 +14,8 @@ import "../card-features/hui-humidifier-toggle-card-feature"; import "../card-features/hui-lawn-mower-commands-card-feature"; import "../card-features/hui-light-brightness-card-feature"; import "../card-features/hui-light-color-temp-card-feature"; +import "../card-features/hui-lock-commands-card-feature"; +import "../card-features/hui-lock-open-door-card-feature"; import "../card-features/hui-numeric-input-card-feature"; import "../card-features/hui-select-options-card-feature"; import "../card-features/hui-target-temperature-card-feature"; @@ -45,6 +47,8 @@ const TYPES: Set = new Set([ "lawn-mower-commands", "light-brightness", "light-color-temp", + "lock-commands", + "lock-open-door", "numeric-input", "select-options", "target-humidity", diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index 2577822756..e92aba044d 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -278,13 +278,21 @@ export class HuiCardPicker extends LitElement { if (customCards.length > 0) { cards = cards.concat( - customCards.map((ccard: CustomCardEntry) => ({ - type: ccard.type, - name: ccard.name, - description: ccard.description, - showElement: ccard.preview, - isCustom: true, - })) + customCards + .map((ccard: CustomCardEntry) => ({ + type: ccard.type, + name: ccard.name, + description: ccard.description, + showElement: ccard.preview, + isCustom: true, + })) + .sort((a, b) => + stringCompare( + a.name || a.type, + b.name || b.type, + this.hass?.language + ) + ) ); } this._cards = cards.map((card: Card) => ({ 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 444144925f..c4b938230a 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 @@ -35,6 +35,8 @@ import { supportsHumidifierToggleCardFeature } from "../../card-features/hui-hum 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"; +import { supportsLockCommandsCardFeature } from "../../card-features/hui-lock-commands-card-feature"; +import { supportsLockOpenDoorCardFeature } from "../../card-features/hui-lock-open-door-card-feature"; import { supportsNumericInputCardFeature } from "../../card-features/hui-numeric-input-card-feature"; import { supportsSelectOptionsCardFeature } from "../../card-features/hui-select-options-card-feature"; import { supportsTargetHumidityCardFeature } from "../../card-features/hui-target-humidity-card-feature"; @@ -56,8 +58,8 @@ const UI_FEATURE_TYPES = [ "climate-preset-modes", "cover-open-close", "cover-position", - "cover-tilt-position", "cover-tilt", + "cover-tilt-position", "fan-preset-modes", "fan-speed", "humidifier-modes", @@ -65,6 +67,8 @@ const UI_FEATURE_TYPES = [ "lawn-mower-commands", "light-brightness", "light-color-temp", + "lock-commands", + "lock-open-door", "numeric-input", "select-options", "target-humidity", @@ -111,6 +115,8 @@ const SUPPORTS_FEATURE_TYPES: Record< "lawn-mower-commands": supportsLawnMowerCommandCardFeature, "light-brightness": supportsLightBrightnessCardFeature, "light-color-temp": supportsLightColorTempCardFeature, + "lock-commands": supportsLockCommandsCardFeature, + "lock-open-door": supportsLockOpenDoorCardFeature, "numeric-input": supportsNumericInputCardFeature, "select-options": supportsSelectOptionsCardFeature, "target-humidity": supportsTargetHumidityCardFeature, diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts index b0115082bb..6226897809 100644 --- a/src/panels/lovelace/hui-root.ts +++ b/src/panels/lovelace/hui-root.ts @@ -640,7 +640,9 @@ class HUIRoot extends LitElement { private _showQuickBar(): void { showQuickBar(this, { commandMode: false, - hint: this.hass.localize("ui.tips.key_e_hint"), + hint: this.hass.enableShortcuts + ? this.hass.localize("ui.tips.key_e_hint") + : undefined, }); } @@ -908,6 +910,8 @@ class HUIRoot extends LitElement { position: fixed; top: 0; width: var(--mdc-top-app-bar-width, 100%); + -webkit-backdrop-filter: var(--app-header-backdrop-filter, none); + backdrop-filter: var(--app-header-backdrop-filter, none); padding-top: env(safe-area-inset-top); z-index: 4; transition: box-shadow 200ms linear; diff --git a/src/resources/styles-data.ts b/src/resources/styles-data.ts index ae04a4c4c4..77bde2fcb1 100644 --- a/src/resources/styles-data.ts +++ b/src/resources/styles-data.ts @@ -102,6 +102,7 @@ export const derivedStyles = { "mdc-theme-error": "var(--error-color)", "app-header-text-color": "var(--text-primary-color)", "app-header-background-color": "var(--primary-color)", + "app-theme-color": "var(--primary-color)", "mdc-checkbox-unchecked-color": "rgba(var(--rgb-primary-text-color), 0.54)", "mdc-checkbox-disabled-color": "var(--disabled-text-color)", "mdc-radio-unchecked-color": "rgba(var(--rgb-primary-text-color), 0.54)", diff --git a/src/state-control/cover/ha-state-control-cover-position.ts b/src/state-control/cover/ha-state-control-cover-position.ts index 0f5652004e..f0b0e7901e 100644 --- a/src/state-control/cover/ha-state-control-cover-position.ts +++ b/src/state-control/cover/ha-state-control-cover-position.ts @@ -41,6 +41,7 @@ export class HaStateControlCoverPosition extends LitElement { return html` >( service, serviceData, target, - notifyOnError = true + notifyOnError = true, + returnResponse = false ) => { if (__DEV__ || this.hass?.debugConnection) { // eslint-disable-next-line no-console @@ -101,7 +102,8 @@ export const connectionMixin = >( domain, service, serviceData ?? {}, - target + target, + returnResponse )) as ServiceCallResponse; } catch (err: any) { if ( diff --git a/src/state/themes-mixin.ts b/src/state/themes-mixin.ts index 034a3eb9ac..4dfb775d77 100644 --- a/src/state/themes-mixin.ts +++ b/src/state/themes-mixin.ts @@ -130,9 +130,8 @@ export default >(superClass: T) => const themeMeta = document.querySelector("meta[name=theme-color]"); const computedStyles = getComputedStyle(document.documentElement); - const headerColor = computedStyles.getPropertyValue( - "--app-header-background-color" - ); + const themeMetaColor = + computedStyles.getPropertyValue("--app-theme-color"); document.documentElement.style.backgroundColor = computedStyles.getPropertyValue("--primary-background-color"); @@ -145,7 +144,7 @@ export default >(superClass: T) => ); } const themeColor = - headerColor?.trim() || + themeMetaColor?.trim() || (themeMeta.getAttribute("default-content") as string); themeMeta.setAttribute("content", themeColor); } diff --git a/src/state/translations-mixin.ts b/src/state/translations-mixin.ts index db00f9c3c7..be3158da08 100644 --- a/src/state/translations-mixin.ts +++ b/src/state/translations-mixin.ts @@ -72,7 +72,7 @@ export default >(superClass: T) => // eslint-disable-next-line: variable-name private __coreProgress?: string; - private __loadedFragmetTranslations: Set = new Set(); + private __loadedFragmentTranslations: Set = new Set(); private __loadedTranslations: { // track what things have been loaded @@ -262,7 +262,7 @@ export default >(superClass: T) => document.querySelector("html")!.setAttribute("lang", hass.language); this._applyDirection(hass); this._loadCoreTranslations(hass.language); - this.__loadedFragmetTranslations = new Set(); + this.__loadedFragmentTranslations = new Set(); this._loadFragmentTranslations(hass.language, hass.panelUrl); } @@ -385,12 +385,12 @@ export default >(superClass: T) => return undefined; } - if (this.__loadedFragmetTranslations.has(fragment)) { + if (this.__loadedFragmentTranslations.has(fragment)) { return this.hass!.localize; } - this.__loadedFragmetTranslations.add(fragment); + this.__loadedFragmentTranslations.add(fragment); const result = await getTranslation(fragment, language); - return this._updateResources(result.language, result.data); + return this._updateResources(language, result.data); } private async _loadCoreTranslations(language: string) { @@ -402,7 +402,7 @@ export default >(superClass: T) => this.__coreProgress = language; try { const result = await getTranslation(null, language); - await this._updateResources(result.language, result.data); + await this._updateResources(language, result.data); } finally { this.__coreProgress = undefined; } diff --git a/src/translations/en.json b/src/translations/en.json index 21e30b9e0b..65b153f522 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -377,6 +377,11 @@ "upload_failed": "Upload failed", "unknown_file": "Unknown file" }, + "location": { + "latitude": "[%key:ui::panel::config::zone::detail::latitude%]", + "longitude": "[%key:ui::panel::config::zone::detail::longitude%]", + "radius": "[%key:ui::panel::config::zone::detail::radius%]" + }, "selector": { "options": "Selector Options", "types": { @@ -472,7 +477,9 @@ "clear": "Clear", "no_entities": "You don't have any entities", "no_match": "No matching entities found", - "show_entities": "Show entities" + "show_entities": "Show entities", + "new_entity": "Create a new entity", + "create_helper": "Create a new {domain, select, \n undefined {} \n other {{domain} }\n } helper." }, "entity-attribute-picker": { "attribute": "Attribute", @@ -776,7 +783,8 @@ "no-data": "No data", "filtering_by": "Filtering by", "hidden": "{number} hidden", - "clear": "Clear" + "clear": "Clear", + "ungrouped": "Ungrouped" }, "media-browser": { "tts": { @@ -2243,6 +2251,7 @@ "add_device": "Add device", "dialog": { "header": "Add a device", + "display_name": "Display name", "device_consumption_energy": "Device consumption energy", "selected_stat_intro": "Select the energy sensor that measures the device's energy usage in either of {unit}." } @@ -3828,6 +3837,19 @@ "advanced_options": "Advanced options", "external_activation": "Allow external activation of remote control", "external_activation_secondary": "Allows you to turn on remote control from your Nabu Casa account page, even if you're outside your local network", + "strict_connection": "Restrict access to logged in users", + "strict_connection_secondary": "When a user is not logged in to your Home Assistant instance, they will not be able to access your instance remotely", + "strict_connection_mode": "Mode", + "strict_connection_modes": { + "disabled": "Disabled", + "guard_page": "Guard page", + "drop_connection": "Drop connection" + }, + "strict_connection_link": "Create login link", + "strict_connection_link_secondary": "You can create a link that will give temporary access to the login page.", + "strict_connection_create_link": "Create link", + "strict_connection_link_created_message": "Give this link to the person you want to give remote access to the login page of your Home Assistant instance.", + "strict_connection_copy_link": "Copy link", "certificate_info": "Certificate info", "certificate_expire": "Will be renewed at {date}", "more_info": "More info" @@ -4017,7 +4039,12 @@ "confirm_delete_integration": "Are you sure you want to remove this device from {integration}?", "picker": { "search": "Search {number} devices", - "state": "State" + "state": "State", + "bulk_actions": { + "move_area": "Move to area", + "no_area": "No area", + "add_area": "Add area" + } } }, "entities": { @@ -4044,7 +4071,8 @@ "integration": "Integration", "area": "Area", "disabled_by": "Disabled by", - "status": "Status" + "status": "Status", + "domain": "Domain" }, "selected": "{number} selected", "enable_selected": { @@ -4119,10 +4147,6 @@ "confirm_delete": "Are you sure you want to delete this zone?", "can_not_edit": "Unable to edit zone", "configured_in_yaml": "Zones configured via configuration.yaml cannot be edited via the UI.", - "edit_home_zone": "The radius of the Home zone can't be edited from the frontend yet. Drag the marker on the map to move the home zone.", - "edit_home_zone_narrow": "The radius of the Home zone can't be edited from the frontend yet. The location can be changed from the general configuration.", - "go_to_core_config": "Go to general configuration?", - "home_zone_core_config": "The location of your home zone is editable from the general configuration page. The radius of the Home zone can't be edited from the frontend yet. Do you want to go to the general configuration?", "detail": { "new_zone": "New zone", "name": "Name", @@ -4137,7 +4161,8 @@ "required_error_msg": "This field is required", "delete": "Delete", "create": "Add", - "update": "Update" + "update": "Update", + "no_edit_home_zone_radius": "The radius of the home zone is not editable in the UI." }, "core_location_dialog": "Home Assistant location" }, @@ -5936,6 +5961,12 @@ "light-color-temp": { "label": "Light color temperature" }, + "lock-commands": { + "label": "Lock commands" + }, + "lock-open-door": { + "label": "Lock open door" + }, "vacuum-commands": { "label": "Vacuum commands", "commands": "Commands", diff --git a/src/types.ts b/src/types.ts index cb0e1931f9..c6b32be85d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -190,6 +190,7 @@ export interface Context { export interface ServiceCallResponse { context: Context; + response?: any; } export interface ServiceCallRequest { @@ -241,7 +242,8 @@ export interface HomeAssistant { service: ServiceCallRequest["service"], serviceData?: ServiceCallRequest["serviceData"], target?: ServiceCallRequest["target"], - notifyOnError?: boolean + notifyOnError?: boolean, + returnResponse?: boolean ): Promise; callApi( method: "GET" | "POST" | "PUT" | "DELETE", diff --git a/yarn.lock b/yarn.lock index f109503928..b546d2a82f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -55,24 +55,24 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.5, @babel/compat-data@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/compat-data@npm:7.24.1" - checksum: 10/d5460b99c07ff8487467c52f742a219c7e3bcdcaa2882456a13c0d0c8116405f0c85a651fb60511284dc64ed627a5e989f24c3cd6e71d07a9947e7c8954b433c +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.5, @babel/compat-data@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/compat-data@npm:7.24.4" + checksum: 10/e51faec0ac8259f03cc5029d2b4a944b4fee44cb5188c11530769d5beb81f384d031dba951febc3e33dbb48ceb8045b1184f5c1ac4c5f86ab1f5e951e9aaf7af languageName: node linkType: hard -"@babel/core@npm:7.24.3, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.0": - version: 7.24.3 - resolution: "@babel/core@npm:7.24.3" +"@babel/core@npm:7.24.4, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.0": + version: 7.24.4 + resolution: "@babel/core@npm:7.24.4" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.24.2" - "@babel/generator": "npm:^7.24.1" + "@babel/generator": "npm:^7.24.4" "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.24.1" - "@babel/parser": "npm:^7.24.1" + "@babel/helpers": "npm:^7.24.4" + "@babel/parser": "npm:^7.24.4" "@babel/template": "npm:^7.24.0" "@babel/traverse": "npm:^7.24.1" "@babel/types": "npm:^7.24.0" @@ -81,19 +81,19 @@ __metadata: gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10/3a7b9931fe0d93c500dcdb6b36f038b0f9d5090c048818e62aa8321c8f6e8ccc3d47373f0b40591c1fe3b13e5096bacabb1ade83f9f4d86f57878c39a9d1ade1 + checksum: 10/1e049f8df26be0fe5be36173fd7c33dfb004eeeec28152fea83c90e71784f9a6f2237296f43a2ee7d9041e2a33a05f43da48ce2d4e0cd473a682328ca07ce7e0 languageName: node linkType: hard -"@babel/generator@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/generator@npm:7.24.1" +"@babel/generator@npm:^7.24.1, @babel/generator@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/generator@npm:7.24.4" dependencies: "@babel/types": "npm:^7.24.0" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 10/c6160e9cd63d7ed7168dee27d827f9c46fab820c45861a5df56cd5c78047f7c3fc97c341e9ccfa1a6f97c87ec2563d9903380b5f92794e3540a6c5f99eb8f075 + checksum: 10/69e1772dcf8f95baec951f422cca091d59a3f29b5eedc989ad87f7262289b94625983f6fe654302ca17aae0a32f9232332b83fcc85533311d6267b09c58b1061 languageName: node linkType: hard @@ -128,9 +128,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/helper-create-class-features-plugin@npm:7.24.1" +"@babel/helper-create-class-features-plugin@npm:^7.24.1, @babel/helper-create-class-features-plugin@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/helper-create-class-features-plugin@npm:7.24.4" 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: 10/c48e9ce842cbd55099a6b9893df1b4fb08c88061d6c20c37a5279b95249879be478210b587295b55d3675428d2ce4306c790cf6332f478ab2af0061f940156f3 + checksum: 10/86153719d98e4402f92f24d6b1be94e6b59c0236a6cc36b173a570a64b5156dbc2f16ccfe3c8485dc795524ca88acca65b14863be63049586668c45567f2acd4 languageName: node linkType: hard @@ -304,9 +304,9 @@ __metadata: linkType: hard "@babel/helper-string-parser@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/helper-string-parser@npm:7.23.4" - checksum: 10/c352082474a2ee1d2b812bd116a56b2e8b38065df9678a32a535f151ec6f58e54633cc778778374f10544b930703cca6ddf998803888a636afa27e2658068a9c + version: 7.24.1 + resolution: "@babel/helper-string-parser@npm:7.24.1" + checksum: 10/04c0ede77b908b43e6124753b48bc485528112a9335f0a21a226bff1ace75bb6e64fab24c85cb4b1610ef3494dacd1cb807caeb6b79a7b36c43d48c289b35949 languageName: node linkType: hard @@ -335,14 +335,14 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/helpers@npm:7.24.1" +"@babel/helpers@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/helpers@npm:7.24.4" dependencies: "@babel/template": "npm:^7.24.0" "@babel/traverse": "npm:^7.24.1" "@babel/types": "npm:^7.24.0" - checksum: 10/82d3cdd3beafc4583f237515ef220bc205ced8b0540c6c6e191fc367a9589bd7304b8f9800d3d7574d4db9f079bd555979816b1874c86e53b3e7dd2032ad6c7c + checksum: 10/54a9d0f86f2803fcc216cfa23b66b871ea0fa0a892af1c9a79075872c2437de71afbb150ed8216f30e00b19a0b9c5c9d5845173d170e1ebfbbf8887839b89dde languageName: node linkType: hard @@ -358,12 +358,24 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.23.5, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/parser@npm:7.24.1" +"@babel/parser@npm:^7.23.5, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.1, @babel/parser@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/parser@npm:7.24.4" bin: parser: ./bin/babel-parser.js - checksum: 10/561d9454091e07ecfec3828ce79204c0fc9d24e17763f36181c6984392be4ca6b79c8225f2224fdb7b1b3b70940e243368c8f83ac77ec2dc20f46d3d06bd6795 + checksum: 10/3742cc5068036287e6395269dce5a2735e6349cdc8d4b53297c75f98c580d7e1c8cb43235623999d151f2ef975d677dbc2c2357573a1855caa71c271bf3046c9 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.24.4" + dependencies: + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-plugin-utils": "npm:^7.24.0" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/1439e2ceec512b72f05f036503bf2c31e807d1b75ae22cf2676145e9f20740960a1c9575ea3065c6fb9f44f6b46163aab76eac513694ffa10de674e3cdd6219e languageName: node linkType: hard @@ -706,14 +718,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-block-scoping@npm:7.24.1" +"@babel/plugin-transform-block-scoping@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.24.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.24.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/443069c6410079c007c40425254a5d0416e4fefe38c1cb354884694a3029dfa6ea8c196398726d2bd4ec3e5c4559ef85efc1ad0b068f1330df4aa03b414781e0 + checksum: 10/4093fa109cd256e8ad0b26e3ffa67ec6dac4078a1a24b7755bed63e650cf938b2a315e01696c35b221db1a37606f93cb82696c8d1bf563c2a9845620e551736e languageName: node linkType: hard @@ -729,16 +741,16 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-class-static-block@npm:7.24.1" +"@babel/plugin-transform-class-static-block@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/plugin-transform-class-static-block@npm:7.24.4" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.24.1" + "@babel/helper-create-class-features-plugin": "npm:^7.24.4" "@babel/helper-plugin-utils": "npm:^7.24.0" "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.12.0 - checksum: 10/253c627c11d9df79e3b32e78bfa1fe0dd1f91c3579da52bf73f76c83de53b140dcb1c9cc5f4c65ff1505754a01b59bc83987c35bcc8f89492b63dae46adef78f + checksum: 10/3b1db3308b57ba21d47772a9f183804234c23fd64c9ca40915d2d65c5dc7a48b49a6de16b8b90b7a354eacbb51232a862f0fca3dbd23e27d34641f511decddab languageName: node linkType: hard @@ -1133,7 +1145,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-runtime@npm:7.24.3": +"@babel/plugin-transform-runtime@npm:7.24.3, @babel/plugin-transform-runtime@npm:^7.13.0": version: 7.24.3 resolution: "@babel/plugin-transform-runtime@npm:7.24.3" dependencies: @@ -1206,16 +1218,16 @@ __metadata: linkType: hard "@babel/plugin-transform-typescript@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-typescript@npm:7.24.1" + version: 7.24.4 + resolution: "@babel/plugin-transform-typescript@npm:7.24.4" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-create-class-features-plugin": "npm:^7.24.1" + "@babel/helper-create-class-features-plugin": "npm:^7.24.4" "@babel/helper-plugin-utils": "npm:^7.24.0" "@babel/plugin-syntax-typescript": "npm:^7.24.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/9b7fee53ebea0e96d990d9bd4f37602366f9a0955fe65bb5671505ec2e0f3d14709f26c61383481ecacc8a418c545ea8a50d407f9e34e3265fe53a686fe2d826 + checksum: 10/e8d66fbafd6cbfeca2ebe77c4fc67537be9e01813f835ce097fa91329b0cd7ba587a9cf4c4a1df661cdde438741cb3c63d2ab95c97354eb89d7682a4d99bea5d languageName: node linkType: hard @@ -1266,14 +1278,15 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:7.24.3, @babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.13.0": - version: 7.24.3 - resolution: "@babel/preset-env@npm:7.24.3" +"@babel/preset-env@npm:7.24.4, @babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.13.0": + version: 7.24.4 + resolution: "@babel/preset-env@npm:7.24.4" dependencies: - "@babel/compat-data": "npm:^7.24.1" + "@babel/compat-data": "npm:^7.24.4" "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-plugin-utils": "npm:^7.24.0" "@babel/helper-validator-option": "npm:^7.23.5" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.24.4" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.24.1" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.24.1" "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.24.1" @@ -1300,9 +1313,9 @@ __metadata: "@babel/plugin-transform-async-generator-functions": "npm:^7.24.3" "@babel/plugin-transform-async-to-generator": "npm:^7.24.1" "@babel/plugin-transform-block-scoped-functions": "npm:^7.24.1" - "@babel/plugin-transform-block-scoping": "npm:^7.24.1" + "@babel/plugin-transform-block-scoping": "npm:^7.24.4" "@babel/plugin-transform-class-properties": "npm:^7.24.1" - "@babel/plugin-transform-class-static-block": "npm:^7.24.1" + "@babel/plugin-transform-class-static-block": "npm:^7.24.4" "@babel/plugin-transform-classes": "npm:^7.24.1" "@babel/plugin-transform-computed-properties": "npm:^7.24.1" "@babel/plugin-transform-destructuring": "npm:^7.24.1" @@ -1352,7 +1365,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/42de398cb7655f3748a03f9f5ca6132dd8e84315ccf286e47740455dfb5be6358df7cfcbecf84426c14176a4d02d0b0b3c97ddf6c5c4c8fb7f1f307692a103ee + checksum: 10/3d5cbdc2501bc1959fc76ed9d409d0ee5264bc475fa809958fd2e8e7db9b12f8eccdae750a0e05d25207373c42ca115b42bb3d5c743bc770cb12b6af05bf3bd8 languageName: node linkType: hard @@ -1391,12 +1404,12 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:7.24.1, @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.24.1 - resolution: "@babel/runtime@npm:7.24.1" +"@babel/runtime@npm:7.24.4, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4": + version: 7.24.4 + resolution: "@babel/runtime@npm:7.24.4" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 10/3a8d61400c636d1ce3a42895a106cd4dfb4e9b88832a8a754a724c68652f821d7a46dce394305d7623f9f0d3597bf0a98aeb5f9c150ef60e14bbbf66caab4654 + checksum: 10/8ec8ce2c145bc7e31dd39ab66df124f357f65c11489aefacb30f431bae913b9aaa66aa5efe5321ea2bf8878af3fcee338c87e7599519a952e3a6f83aa1b03308 languageName: node linkType: hard @@ -1456,9 +1469,9 @@ __metadata: languageName: node linkType: hard -"@codemirror/autocomplete@npm:6.15.0": - version: 6.15.0 - resolution: "@codemirror/autocomplete@npm:6.15.0" +"@codemirror/autocomplete@npm:6.16.0": + version: 6.16.0 + resolution: "@codemirror/autocomplete@npm:6.16.0" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.0.0" @@ -1469,19 +1482,19 @@ __metadata: "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 "@lezer/common": ^1.0.0 - checksum: 10/5ef009826113459532b836347afd73759588edb1cbe507834b2b06de665c8b36fdf6de0685bcae4b1204fbb0ba4294af732da57a44b57b350339228164ba49e1 + checksum: 10/a29e27f69d17bce014d1d34ab4cd7c607b139cb3cd529aad554f2b0badb9d2924412b0ab3f4eb44901ea4250cdb033e0c6b81134ee8991bdbcd128ecb3b94d75 languageName: node linkType: hard -"@codemirror/commands@npm:6.3.3": - version: 6.3.3 - resolution: "@codemirror/commands@npm:6.3.3" +"@codemirror/commands@npm:6.5.0": + version: 6.5.0 + resolution: "@codemirror/commands@npm:6.5.0" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.4.0" "@codemirror/view": "npm:^6.0.0" "@lezer/common": "npm:^1.1.0" - checksum: 10/4b398b102d6afcbf0e0018b426287a7458867497811c9155790a3cc679b880765cd756bdb96bf35abc28fecb85c0938e618d39469ce8bc0724d4dea5d88f6ac2 + checksum: 10/2fa3e42e02e50a02cbf55c48c3f3f7891453c841b6399834a2898f4f3a286074ef13646341a60a89b53bd8372ed5885740ced869b9482e115a73305f792971fe languageName: node linkType: hard @@ -1499,12 +1512,12 @@ __metadata: languageName: node linkType: hard -"@codemirror/legacy-modes@npm:6.3.3": - version: 6.3.3 - resolution: "@codemirror/legacy-modes@npm:6.3.3" +"@codemirror/legacy-modes@npm:6.4.0": + version: 6.4.0 + resolution: "@codemirror/legacy-modes@npm:6.4.0" dependencies: "@codemirror/language": "npm:^6.0.0" - checksum: 10/248a11a7fd43561ec85a8bd6dad26414f786bb9e46dcbd15394b3e5ed3b0f177eade39f1aad6f043af9a58396f68e092ee674d592ee434ebdc9f46de0bf4385c + checksum: 10/0f3f47cd867c95704ee7648eeb41b991f736ccd9ef4f6668210a82386333d3bc5e1beb6fa60391f6064327d6ac2037b17428decdee440c115a553f280a75bf61 languageName: node linkType: hard @@ -1526,14 +1539,14 @@ __metadata: languageName: node linkType: hard -"@codemirror/view@npm:6.26.1, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0": - version: 6.26.1 - resolution: "@codemirror/view@npm:6.26.1" +"@codemirror/view@npm:6.26.3, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0": + version: 6.26.3 + resolution: "@codemirror/view@npm:6.26.3" dependencies: "@codemirror/state": "npm:^6.4.0" style-mod: "npm:^4.1.0" w3c-keyname: "npm:^2.2.4" - checksum: 10/6d2b19b2439c36b2712d3560eeb0c198ad2ee442ad22641c2b4bce94077812cffbb52ca12328219d3b9663b2dd0ffc63481432a2550839e5c7a7a53704e82a9a + checksum: 10/fa7cb5aa37db2d252ffd7cdbfb858b23a525ce9835648070b3c99eaaa361f686fa1997576bb258b7c34b6d6bd7a251a2294158e952239616102f783da1025fe4 languageName: node linkType: hard @@ -1573,7 +1586,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": +"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" checksum: 10/8c36169c815fc5d726078e8c71a5b592957ee60d08c6470f9ce0187c8046af1a00afbda0a065cc40ff18d5d83f82aed9793c6818f7304a74a7488dc9f3ecbd42 @@ -1834,9 +1847,9 @@ __metadata: linkType: hard "@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.2 - resolution: "@humanwhocodes/object-schema@npm:2.0.2" - checksum: 10/ef915e3e2f34652f3d383b28a9a99cfea476fa991482370889ab14aac8ecd2b38d47cc21932526c6d949da0daf4a4a6bf629d30f41b0caca25e146819cbfa70e + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: 10/05bb99ed06c16408a45a833f03a732f59bf6184795d4efadd33238ff8699190a8c871ad1121241bb6501589a9598dc83bf25b99dcbcf41e155cdf36e35e937a3 languageName: node linkType: hard @@ -1854,6 +1867,15 @@ __metadata: languageName: node linkType: hard +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10/4412e9e6713c89c1e66d80bb0bb5a2a93192f10477623a27d08f228ba0316bb880affabc5bfe7f838f58a34d26c2c190da726e576cdfc18c49a72e89adabdcf5 + languageName: node + linkType: hard + "@jimp/bmp@npm:^0.16.13": version: 0.16.13 resolution: "@jimp/bmp@npm:0.16.13" @@ -2066,9 +2088,9 @@ __metadata: linkType: hard "@leichtgewicht/ip-codec@npm:^2.0.1": - version: 2.0.4 - resolution: "@leichtgewicht/ip-codec@npm:2.0.4" - checksum: 10/3c7ffb0afb86c731a02813aa4370da27eac037abf8a15fce211226c11b644610382c8eca7efadace9471ee1959afe72fc1d43a62227d974b9fca8eae8b8d2124 + version: 2.0.5 + resolution: "@leichtgewicht/ip-codec@npm:2.0.5" + checksum: 10/cb98c608392abe59457a14e00134e7dfa57c0c9b459871730cd4e907bb12b834cbd03e08ad8663fea9e486f260da7f1293ccd9af0376bf5524dd8536192f248c languageName: node linkType: hard @@ -2151,10 +2173,10 @@ __metadata: languageName: node linkType: hard -"@lokalise/node-api@npm:12.3.0": - version: 12.3.0 - resolution: "@lokalise/node-api@npm:12.3.0" - checksum: 10/934d868f606de63e97bc293ae1d9b80126949a3df9a184f24051b6b534db13d284ad8adf62bf761bb9cc935911921ef522f8a3f140ddf7f0608db864517ea0cb +"@lokalise/node-api@npm:12.4.0": + version: 12.4.0 + resolution: "@lokalise/node-api@npm:12.4.0" + checksum: 10/5e44b23e7139487961f291dcea4f7082fe86d8b017142890831f0ac83338d7f749565e7f96a628eb0f594d894abd905dfec1c31c140fd07bcf0c120db118ee15 languageName: node linkType: hard @@ -3165,13 +3187,13 @@ __metadata: languageName: node linkType: hard -"@material/web@npm:=1.3.0": - version: 1.3.0 - resolution: "@material/web@npm:1.3.0" +"@material/web@npm:1.4.1": + version: 1.4.1 + resolution: "@material/web@npm:1.4.1" dependencies: lit: "npm:^2.7.4 || ^3.0.0" tslib: "npm:^2.4.0" - checksum: 10/7c3427747eccb69628807bed115dca96bb4a8e360e5cb97170a42ab7d469d17f0c925defa417a212ef3237c252f0b06dac9499b56c42945214f9bdeb7f7e5a0b + checksum: 10/d712a885d131ce39b4fb44fe2219ada737e1874480db956eb675dfd8569c7f50f4f005b6cd79c18c54d728873de8b7861241ced3332f8cc6f252b4a4088e2b6a languageName: node linkType: hard @@ -3217,15 +3239,15 @@ __metadata: linkType: hard "@npmcli/agent@npm:^2.0.0": - version: 2.2.1 - resolution: "@npmcli/agent@npm:2.2.1" + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" 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: 10/d4a48128f61e47f2f5c89315a5350e265dc619987e635bd62b52b29c7ed93536e724e721418c0ce352ceece86c13043c67aba1b70c3f5cc72fce6bb746706162 + socks-proxy-agent: "npm:^8.0.3" + checksum: 10/96fc0036b101bae5032dc2a4cd832efb815ce9b33f9ee2f29909ee49d96a0026b3565f73c507a69eb8603f5cb32e0ae45a70cab1e2655990a4e06ae99f7f572a languageName: node linkType: hard @@ -3238,15 +3260,15 @@ __metadata: languageName: node linkType: hard -"@octokit/auth-oauth-device@npm:7.0.1": - version: 7.0.1 - resolution: "@octokit/auth-oauth-device@npm:7.0.1" +"@octokit/auth-oauth-device@npm:7.1.1": + version: 7.1.1 + resolution: "@octokit/auth-oauth-device@npm:7.1.1" dependencies: "@octokit/oauth-methods": "npm:^5.0.0" "@octokit/request": "npm:^9.0.0" - "@octokit/types": "npm:^12.0.0" + "@octokit/types": "npm:^13.0.0" universal-user-agent: "npm:^7.0.0" - checksum: 10/410051ec666bc9792a9080f9c15c035adda113539db6bd9783e30046bae0297b92b8faab83e04e8ae5c0d9f7260fd516de733b6a4f3ac0cce80fa7462e2b322b + checksum: 10/a7ff0c190a9318f790b20a40eb0a16fc86b962547fd40e724ad9da9f22967f6b0adca9b91956df45b039416a634ae7208da41f8cbee83fdee6be4610d0d1d059 languageName: node linkType: hard @@ -3257,68 +3279,68 @@ __metadata: languageName: node linkType: hard -"@octokit/core@npm:^5.0.0": - version: 5.1.0 - resolution: "@octokit/core@npm:5.1.0" +"@octokit/core@npm:^5.0.2": + version: 5.2.0 + resolution: "@octokit/core@npm:5.2.0" dependencies: "@octokit/auth-token": "npm:^4.0.0" - "@octokit/graphql": "npm:^7.0.0" - "@octokit/request": "npm:^8.0.2" - "@octokit/request-error": "npm:^5.0.0" - "@octokit/types": "npm:^12.0.0" + "@octokit/graphql": "npm:^7.1.0" + "@octokit/request": "npm:^8.3.1" + "@octokit/request-error": "npm:^5.1.0" + "@octokit/types": "npm:^13.0.0" before-after-hook: "npm:^2.2.0" universal-user-agent: "npm:^6.0.0" - checksum: 10/8062e86a3088f24a691b36d2c3e9f33e864cefcb5f544b0633650358bce280708b111551cbe855ecf6a5190d6fc4fec1220117c329a2c27525940dd97b868614 + checksum: 10/2e40baf0b5c6949922436a653c213be43befd9690c43dd89872f669f3ac23117ae8ae5e5d6c18094813756c71c3f4fbedd575a891f0b89e12f58b2c38b7f3c13 languageName: node linkType: hard "@octokit/endpoint@npm:^10.0.0": - version: 10.0.0 - resolution: "@octokit/endpoint@npm:10.0.0" + version: 10.1.1 + resolution: "@octokit/endpoint@npm:10.1.1" dependencies: - "@octokit/types": "npm:^12.0.0" + "@octokit/types": "npm:^13.0.0" universal-user-agent: "npm:^7.0.2" - checksum: 10/a73a3499206ffa47bc4060a296488886fb457e4526ea6c314d56a70b4c21c8c8cdc3b6db770cfd61d99789d9d4ea7ba73d31b40f5e7b99eea81f87491eabe914 + checksum: 10/6b8991b278ba7e63ddf95e7396f54e5f1347237f11fb845322ec25101764336ed0994ccb197c449b4fd4bc00ec5b78780ccbc3a0b48ba0620dcc115027a3add1 languageName: node linkType: hard -"@octokit/endpoint@npm:^9.0.0": - version: 9.0.4 - resolution: "@octokit/endpoint@npm:9.0.4" +"@octokit/endpoint@npm:^9.0.1": + version: 9.0.5 + resolution: "@octokit/endpoint@npm:9.0.5" dependencies: - "@octokit/types": "npm:^12.0.0" + "@octokit/types": "npm:^13.1.0" universal-user-agent: "npm:^6.0.0" - checksum: 10/7df35c96f2b5628fe5b3f44a72614be9b439779c06b4dd1bb72283b3cb2ea53e59e1f9a108798efe5404b6856f4380a4c5be12d93255d854f0683cd6e22f3a27 + checksum: 10/212122f653bf076ec37dd7de44bd54db74aa3cd16be4c395c91444488331becd83351e26b30248168e2cc28fc07b1a96e8f74adbbab02826f76de92e069f391f languageName: node linkType: hard -"@octokit/graphql@npm:^7.0.0": - version: 7.0.2 - resolution: "@octokit/graphql@npm:7.0.2" +"@octokit/graphql@npm:^7.1.0": + version: 7.1.0 + resolution: "@octokit/graphql@npm:7.1.0" dependencies: - "@octokit/request": "npm:^8.0.1" - "@octokit/types": "npm:^12.0.0" + "@octokit/request": "npm:^8.3.0" + "@octokit/types": "npm:^13.0.0" universal-user-agent: "npm:^6.0.0" - checksum: 10/f5dcc51fed5304f65dab83fcea4c2a569107d3b71e8d084199dc44f0d0cfc852c9e1f341b06ae66601f9da4af3aad416b0c62dcd0567ac7568f072d8d90d502e + checksum: 10/da6857a69dc93cd20a11d3a905db4214d269d246a6aaee1d8734f922024b08ffdef0b3cba2ac79917633043b4f50464242b0bd92a265c960083dfff5b833dbbe languageName: node linkType: hard "@octokit/oauth-authorization-url@npm:^7.0.0": - version: 7.0.1 - resolution: "@octokit/oauth-authorization-url@npm:7.0.1" - checksum: 10/028aa11cd976699eb8a26e26080be52f36757fa7f5213bc434f68a1fdf3886b41edc0c15a9008deade11672a11337650655cdfe3db20fcdcf27d23e7fc57bfe8 + version: 7.1.1 + resolution: "@octokit/oauth-authorization-url@npm:7.1.1" + checksum: 10/3ef5ef3fe943f9f82c6d0686120c7481078f46594c463f492e559cdd12d74043c9295f4323d7ac9f98d7a20692694cc7263657fabbcb275d3475686133d4f4a0 languageName: node linkType: hard "@octokit/oauth-methods@npm:^5.0.0": - version: 5.0.0 - resolution: "@octokit/oauth-methods@npm:5.0.0" + version: 5.1.2 + resolution: "@octokit/oauth-methods@npm:5.1.2" dependencies: "@octokit/oauth-authorization-url": "npm:^7.0.0" - "@octokit/request": "npm:^9.0.0" - "@octokit/request-error": "npm:^6.0.0" - "@octokit/types": "npm:^12.0.0" - checksum: 10/79e3cce0dac041ef1a117c9f7ef34abbf0076f58e2f86f445a4151c19479fa772fa6c0c7b01fedd63dfedcb8164c81fcccd3e8a98c96a8775af0f1663c1f0e6c + "@octokit/request": "npm:^9.1.0" + "@octokit/request-error": "npm:^6.1.0" + "@octokit/types": "npm:^13.0.0" + checksum: 10/8ed3a3d1abf3764aefdc0fa71ff4e8c8f1cf02e812a41cd8c9d7ebb15bb116f105380aef1aa14040dd37df3e33ef4bedf2ec1489525d5a1d63ff32e711c39b39 languageName: node linkType: hard @@ -3329,7 +3351,14 @@ __metadata: languageName: node linkType: hard -"@octokit/plugin-paginate-rest@npm:^9.0.0": +"@octokit/openapi-types@npm:^22.1.0": + version: 22.1.0 + resolution: "@octokit/openapi-types@npm:22.1.0" + checksum: 10/d80567182efe6cc2c36b96853e622f013a21362897c49fc35fadccfbc1c32b26e478a119385093ea95a5877c76a9327c54457ad22b1815c7a20a6912f2f7e0fb + languageName: node + linkType: hard + +"@octokit/plugin-paginate-rest@npm:^9.1.5": version: 9.2.1 resolution: "@octokit/plugin-paginate-rest@npm:9.2.1" dependencies: @@ -3349,7 +3378,7 @@ __metadata: languageName: node linkType: hard -"@octokit/plugin-rest-endpoint-methods@npm:^10.0.0": +"@octokit/plugin-rest-endpoint-methods@npm:^10.2.0": version: 10.4.1 resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.4.1" dependencies: @@ -3360,76 +3389,76 @@ __metadata: languageName: node linkType: hard -"@octokit/plugin-retry@npm:7.0.3": - version: 7.0.3 - resolution: "@octokit/plugin-retry@npm:7.0.3" +"@octokit/plugin-retry@npm:7.1.0": + version: 7.1.0 + resolution: "@octokit/plugin-retry@npm:7.1.0" dependencies: "@octokit/request-error": "npm:^6.0.0" - "@octokit/types": "npm:^12.0.0" + "@octokit/types": "npm:^13.0.0" bottleneck: "npm:^2.15.3" peerDependencies: "@octokit/core": ">=6" - checksum: 10/dd04be30d9b5814777b9c029ff94cc7962507e5a4708899498d98d78e79830e1746680734465af85c1fa83abe06e303831ab0afa4e54faaf4ddf5bed40779484 + checksum: 10/c445c76daa37c38fd095a280f28c6e9afbfdaab8290f0ca17253e3553b3fcf55f028ae72c923440e1a06b87e4e04f24d8a5a4976f6a7494d33d368ec4518a7de languageName: node linkType: hard -"@octokit/request-error@npm:^5.0.0": - version: 5.0.1 - resolution: "@octokit/request-error@npm:5.0.1" +"@octokit/request-error@npm:^5.1.0": + version: 5.1.0 + resolution: "@octokit/request-error@npm:5.1.0" dependencies: - "@octokit/types": "npm:^12.0.0" + "@octokit/types": "npm:^13.1.0" deprecation: "npm:^2.0.0" once: "npm:^1.4.0" - checksum: 10/a21a4614c46cb173e4ba73fa048576204f1ddc541dee3e7c938ef36088566e3b25e04ca1f96f375ec2e3cc29b7ba970b3b078a89a20bc50cdcdbed879db94573 + checksum: 10/d03f9f7a408af673cd991eeb450b6f4a5cee6c368f6349eb0211dfc0404fddfcff8b5225ef186020a2a1829adba0aa8c9174155b49ab2ed00a94fb9a886a1dd3 languageName: node linkType: hard -"@octokit/request-error@npm:^6.0.0, @octokit/request-error@npm:^6.0.1": - version: 6.0.2 - resolution: "@octokit/request-error@npm:6.0.2" +"@octokit/request-error@npm:^6.0.0, @octokit/request-error@npm:^6.0.1, @octokit/request-error@npm:^6.1.0": + version: 6.1.1 + resolution: "@octokit/request-error@npm:6.1.1" dependencies: - "@octokit/types": "npm:^12.0.0" - checksum: 10/ad2567500dccd14b42af02531812b63104e33fabd84de577005eed5104ca90b91d02456548b523c4b53b15bc12fb9e82e574f8fba993b93e7542dc80412f93eb + "@octokit/types": "npm:^13.0.0" + checksum: 10/cae7bc4078629a02edcf35977f496a4b943e730165f6d7828795073f99a1d884ac67343b02eff69e553a5057765e466d70ddd9d266787f505aa29018858ab06d languageName: node linkType: hard -"@octokit/request@npm:^8.0.1, @octokit/request@npm:^8.0.2": - version: 8.2.0 - resolution: "@octokit/request@npm:8.2.0" +"@octokit/request@npm:^8.3.0, @octokit/request@npm:^8.3.1": + version: 8.4.0 + resolution: "@octokit/request@npm:8.4.0" dependencies: - "@octokit/endpoint": "npm:^9.0.0" - "@octokit/request-error": "npm:^5.0.0" - "@octokit/types": "npm:^12.0.0" + "@octokit/endpoint": "npm:^9.0.1" + "@octokit/request-error": "npm:^5.1.0" + "@octokit/types": "npm:^13.1.0" universal-user-agent: "npm:^6.0.0" - checksum: 10/553ba8b99ea6fe2d3b66b2be6df06f7fe62a0b81e441d334ef25388cf0fcdab4a888fcfe2c1fb1ada262c233bcf7169da3ad5e03f024060ea5723f7753b0de3e + checksum: 10/176cd83c68bde87111a01d50e2d21cf12ec362c1a30b33649eb8771d37397f6d6dd0b0844aab8d59b16d74c825252e39cadd52e37a4b1669d6facd1cb2cdc995 languageName: node linkType: hard -"@octokit/request@npm:^9.0.0": - version: 9.0.1 - resolution: "@octokit/request@npm:9.0.1" +"@octokit/request@npm:^9.0.0, @octokit/request@npm:^9.1.0": + version: 9.1.1 + resolution: "@octokit/request@npm:9.1.1" dependencies: "@octokit/endpoint": "npm:^10.0.0" "@octokit/request-error": "npm:^6.0.1" - "@octokit/types": "npm:^12.0.0" + "@octokit/types": "npm:^13.1.0" universal-user-agent: "npm:^7.0.2" - checksum: 10/428e27ca11ebf02ffc4a7705f0b73cb5f7323a0a1e3a96ebce6a6da1c66c22ffdf7f0af536c67288cda4360525c47fc938c3b31258376ca3739be7c32c7b98d3 + checksum: 10/aef47d85751c387c6ef29e70b3b86c9033fc7940361092c80728f7e99cc0ba54ddd00bbecb4422e50df78744600cfb8a1a2bc6916c5b6440677aa8ebd6b9b291 languageName: node linkType: hard -"@octokit/rest@npm:20.0.2": - version: 20.0.2 - resolution: "@octokit/rest@npm:20.0.2" +"@octokit/rest@npm:20.1.0": + version: 20.1.0 + resolution: "@octokit/rest@npm:20.1.0" dependencies: - "@octokit/core": "npm:^5.0.0" - "@octokit/plugin-paginate-rest": "npm:^9.0.0" + "@octokit/core": "npm:^5.0.2" + "@octokit/plugin-paginate-rest": "npm:^9.1.5" "@octokit/plugin-request-log": "npm:^4.0.0" - "@octokit/plugin-rest-endpoint-methods": "npm:^10.0.0" - checksum: 10/527e1806ca274209a2a7daa485010dafb2ebb6c9b0b44c1d33a8f1f16f10e54a96386a4f642dc416160842a4b367d3953d27f8b827b9a94600709d2ac5e95d21 + "@octokit/plugin-rest-endpoint-methods": "npm:^10.2.0" + checksum: 10/a34ef12f066128dcac2680ba3a3fad8b2eb1ce0f278b613bf4497310701a752148c0a9703a6fb35326dcfb9a1958c541a6722d5c6eaf2e1612c8b935dfed8eb3 languageName: node linkType: hard -"@octokit/types@npm:^12.0.0, @octokit/types@npm:^12.6.0": +"@octokit/types@npm:^12.6.0": version: 12.6.0 resolution: "@octokit/types@npm:12.6.0" dependencies: @@ -3438,6 +3467,15 @@ __metadata: languageName: node linkType: hard +"@octokit/types@npm:^13.0.0, @octokit/types@npm:^13.1.0": + version: 13.4.1 + resolution: "@octokit/types@npm:13.4.1" + dependencies: + "@octokit/openapi-types": "npm:^22.1.0" + checksum: 10/ea2460da2e343edc2f4c9759d0846e40158b4023c9d802ee9edd0d15a18fa596cb151e0a21e8cad48c34c001942dc7813a4b15c399eb169e6fd5bd983d2f55dc + languageName: node + linkType: hard + "@open-wc/dedupe-mixin@npm:^1.3.0": version: 1.4.0 resolution: "@open-wc/dedupe-mixin@npm:1.4.0" @@ -3990,19 +4028,19 @@ __metadata: linkType: hard "@types/chrome@npm:*": - version: 0.0.263 - resolution: "@types/chrome@npm:0.0.263" + version: 0.0.266 + resolution: "@types/chrome@npm:0.0.266" dependencies: "@types/filesystem": "npm:*" "@types/har-format": "npm:*" - checksum: 10/ecffc799c2c8df057457fb79be0ac69d2d3327e53343d6727f1633a4782037613e7392ede6541284a9fa771d4d63352d61889882328c95e0ea9af4c65d8c98c5 + checksum: 10/3a6c0d3214da65947a9fcd4343ca86b0a4d3ebe1745038fd075a116b7d99d7ef331b84f7b595297faf31cfd4dd7c344ef366f403991635169d295807d3a75d78 languageName: node linkType: hard -"@types/chromecast-caf-receiver@npm:6.0.13": - version: 6.0.13 - resolution: "@types/chromecast-caf-receiver@npm:6.0.13" - checksum: 10/4e2fb8628985cd61f206de5dfe6f3bcbcb2527024f03e36c6cad844fe7672ecd1c2b14cd2b91987f3ab0f67a8b6430008e2a567cfa6b5df8cb09b204e7b72094 +"@types/chromecast-caf-receiver@npm:6.0.14": + version: 6.0.14 + resolution: "@types/chromecast-caf-receiver@npm:6.0.14" + checksum: 10/8d7388b280ef6db0d81098d68c77c1f256f0ccae480b3f4316ce3f86f68b585b38e3fbc4d2519bc55bbf41cc85fab2c968e6144ebfe671aabf6ccf0d4f26e203 languageName: node linkType: hard @@ -4015,10 +4053,10 @@ __metadata: languageName: node linkType: hard -"@types/color-name@npm:1.1.3": - version: 1.1.3 - resolution: "@types/color-name@npm:1.1.3" - checksum: 10/9060d16d0bce2cdf562d6da54e18c5f23e80308ccb58b725b9173a028818f27d8e01c8a5cd96952e76f11145a7388ed7d2f450fb4652f4760383834f2e698263 +"@types/color-name@npm:1.1.4": + version: 1.1.4 + resolution: "@types/color-name@npm:1.1.4" + checksum: 10/be275af06d32e6f09c8f1b8c15d35d2b8194736af980569b2fa572720339a19b3d5ccb63ce5950105d859d5c6226c98b8d8ecd613d626e757667037a90b9b47f languageName: node linkType: hard @@ -4078,12 +4116,12 @@ __metadata: linkType: hard "@types/eslint@npm:*": - version: 8.56.5 - resolution: "@types/eslint@npm:8.56.5" + version: 8.56.10 + resolution: "@types/eslint@npm:8.56.10" dependencies: "@types/estree": "npm:*" "@types/json-schema": "npm:*" - checksum: 10/548aab6ea34ca14452bf6e9212c76bb22cdf3b725d47e25591c20651af3f47fb62c59c4e80ed8ea3f7d1d7374d907cbba980af910e4c0f0cb29f73b9a6a9226f + checksum: 10/0cdd914b944ebba51c35827d3ef95bc3e16eb82b4c2741f6437fa57cdb00a4407c77f89c220afe9e4c9566982ec8a0fb9b97c956ac3bd4623a3b6af32eed8424 languageName: node linkType: hard @@ -4102,14 +4140,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": - version: 4.17.43 - resolution: "@types/express-serve-static-core@npm:4.17.43" + version: 4.19.0 + resolution: "@types/express-serve-static-core@npm:4.19.0" dependencies: "@types/node": "npm:*" "@types/qs": "npm:*" "@types/range-parser": "npm:*" "@types/send": "npm:*" - checksum: 10/9079e137470e0456bb8e77ae66df9505ee12591e94860bde574cfe52c5c60bbc5bf7dd44f5689c3cbb1baf0aa84442d9a21f53dcd921d18745727293cd5a5fd6 + checksum: 10/3e803822f90106158e2c7598d0a44e078e22fad67806eadb1e9f00261fa2be7ea65725d9d177157225d2b0ab22793a84039a433c2d97910586ae6f79e9d04c2f languageName: node linkType: hard @@ -4126,11 +4164,11 @@ __metadata: linkType: hard "@types/filesystem@npm:*": - version: 0.0.35 - resolution: "@types/filesystem@npm:0.0.35" + version: 0.0.36 + resolution: "@types/filesystem@npm:0.0.36" dependencies: "@types/filewriter": "npm:*" - checksum: 10/d8eb6c2b28601c5eacf8b48464bc48f060c2a7194e2c8e493e943f3a8543e35da9c706987665356ed67b11587cc94819fd8262037bf56945c6a38569a0e260f1 + checksum: 10/ec831040fe3aff066ffb7b7541e21a5dd59aa06e7175c61e592736e38b018b1d513551438254631e2a3fbc81ff671bf618401000f4c8ea79156934cbc7dcaeaa languageName: node linkType: hard @@ -4209,7 +4247,7 @@ __metadata: languageName: node 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": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 10/1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7 @@ -4264,12 +4302,12 @@ __metadata: languageName: node linkType: hard -"@types/leaflet@npm:*, @types/leaflet@npm:1.9.8": - version: 1.9.8 - resolution: "@types/leaflet@npm:1.9.8" +"@types/leaflet@npm:*, @types/leaflet@npm:1.9.11": + version: 1.9.11 + resolution: "@types/leaflet@npm:1.9.11" dependencies: "@types/geojson": "npm:*" - checksum: 10/c0c68ae0d1ccbed60e08ad82670df48f8bb6f19e3abaf84a9cd0a6cbc6d6efdd46852ee7be56744dfa7f3d8665adb56bb06ab02d09f979d3367c941a1fd90f2f + checksum: 10/a7f3936b83f1007fa74f65eee7a905e582966c3218d3a45ad1c713445038e69cdefeb668c8f0cb70bc293e77d3d801b299a90bc2fd33e52ff90fd93f342108a2 languageName: node linkType: hard @@ -4296,13 +4334,6 @@ __metadata: languageName: node linkType: hard -"@types/mime@npm:*": - version: 3.0.4 - resolution: "@types/mime@npm:3.0.4" - checksum: 10/a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843 - languageName: node - linkType: hard - "@types/mime@npm:^1": version: 1.3.5 resolution: "@types/mime@npm:1.3.5" @@ -4334,11 +4365,11 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 20.11.29 - resolution: "@types/node@npm:20.11.29" + version: 20.12.7 + resolution: "@types/node@npm:20.12.7" dependencies: undici-types: "npm:~5.26.4" - checksum: 10/eca2c87c1e583bcd4d73dc7a49643c6b793008d8aeefb93ba22c84d70b61388d6cacf8c44af0fcd35820a92121249437689afe48f42b228e281ecc64c22b0a67 + checksum: 10/b4a28a3b593a9bdca5650880b6a9acef46911d58cf7cfa57268f048e9a7157a7c3196421b96cea576850ddb732e3b54bc982c8eb5e1e5ef0635d4424c2fce801 languageName: node linkType: hard @@ -4396,9 +4427,9 @@ __metadata: linkType: hard "@types/qs@npm:*": - version: 6.9.13 - resolution: "@types/qs@npm:6.9.13" - checksum: 10/0a8c55694fee7027dda7e1451936a5a0f8f33a8a5ea24a2e5b0cf2dc221fc21afc6939ff74ea82c5107924e87192a403e60904c339abc3cbc19bd5e90e6e1ce0 + version: 6.9.15 + resolution: "@types/qs@npm:6.9.15" + checksum: 10/97d8208c2b82013b618e7a9fc14df6bd40a73e1385ac479b6896bafc7949a46201c15f42afd06e86a05e914f146f495f606b6fb65610cc60cf2e0ff743ec38a2 languageName: node linkType: hard @@ -4432,7 +4463,7 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.5.0": +"@types/semver@npm:^7.5.8": version: 7.5.8 resolution: "@types/semver@npm:7.5.8" checksum: 10/3496808818ddb36deabfe4974fd343a78101fa242c4690044ccdc3b95dcf8785b494f5d628f2f47f38a702f8db9c53c67f47d7818f2be1b79f2efb09692e1178 @@ -4468,13 +4499,13 @@ __metadata: linkType: hard "@types/serve-static@npm:*, @types/serve-static@npm:^1.15.5": - version: 1.15.5 - resolution: "@types/serve-static@npm:1.15.5" + version: 1.15.7 + resolution: "@types/serve-static@npm:1.15.7" dependencies: "@types/http-errors": "npm:*" - "@types/mime": "npm:*" "@types/node": "npm:*" - checksum: 10/49aa21c367fffe4588fc8c57ea48af0ea7cbadde7418bc53cde85d8bd57fd2a09a293970d9ea86e79f17a87f8adeb3e20da76aab38e1c4d1567931fa15c8af38 + "@types/send": "npm:*" + checksum: 10/c5a7171d5647f9fbd096ed1a26105759f3153ccf683824d99fee4c7eb9cde2953509621c56a070dd9fb1159e799e86d300cbe4e42245ebc5b0c1767e8ca94a67 languageName: node linkType: hard @@ -4494,13 +4525,13 @@ __metadata: languageName: node linkType: hard -"@types/tar@npm:6.1.11": - version: 6.1.11 - resolution: "@types/tar@npm:6.1.11" +"@types/tar@npm:6.1.13": + version: 6.1.13 + resolution: "@types/tar@npm:6.1.13" dependencies: "@types/node": "npm:*" minipass: "npm:^4.0.0" - checksum: 10/0d54b8acbd7d2fc43bd1097eef5058604a6b0e3a394cf485038303ca3ef39ecb42451c7dc5a2b9b18420e137ef5b2c76ec504e94c2f45010b2c8e8c3a49d9de7 + checksum: 10/d325223cf90399fd03f366d0eabe2383e75e550b3e40a006d5f062d006b894a475cd7c0968d258a8eb8eae5df30b6e7f4607d493a474f89134bbff65362b77ed languageName: node linkType: hard @@ -4543,126 +4574,126 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:7.4.0": - version: 7.4.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.4.0" +"@typescript-eslint/eslint-plugin@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.7.0" dependencies: - "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:7.4.0" - "@typescript-eslint/type-utils": "npm:7.4.0" - "@typescript-eslint/utils": "npm:7.4.0" - "@typescript-eslint/visitor-keys": "npm:7.4.0" + "@eslint-community/regexpp": "npm:^4.10.0" + "@typescript-eslint/scope-manager": "npm:7.7.0" + "@typescript-eslint/type-utils": "npm:7.7.0" + "@typescript-eslint/utils": "npm:7.7.0" + "@typescript-eslint/visitor-keys": "npm:7.7.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.4" + ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" peerDependencies: "@typescript-eslint/parser": ^7.0.0 eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/9bd8852c7e4e9608c3fded94f7c60506cc7d2b6d8a8c1cad6d48969a7363751b20282874e55ccdf180635cf204cb10b3e1e5c3d1cff34d4fcd07762be3fc138e + checksum: 10/9e6b6fbb9920581813c01daaa2f89419c3476e42823755c0627f4491640cfaffaebeb0592231ed4f318eefadfcdd4560b77b2903d66ab4e0c8df746a7037a603 languageName: node linkType: hard -"@typescript-eslint/parser@npm:7.4.0": - version: 7.4.0 - resolution: "@typescript-eslint/parser@npm:7.4.0" +"@typescript-eslint/parser@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/parser@npm:7.7.0" dependencies: - "@typescript-eslint/scope-manager": "npm:7.4.0" - "@typescript-eslint/types": "npm:7.4.0" - "@typescript-eslint/typescript-estree": "npm:7.4.0" - "@typescript-eslint/visitor-keys": "npm:7.4.0" + "@typescript-eslint/scope-manager": "npm:7.7.0" + "@typescript-eslint/types": "npm:7.7.0" + "@typescript-eslint/typescript-estree": "npm:7.7.0" + "@typescript-eslint/visitor-keys": "npm:7.7.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/142a9e1187d305ed43b4fef659c36fa4e28359467198c986f0955c70b4067c9799f4c85d9881fbf099c55dfb265e30666e28b3ef290520e242b45ca7cb8e4ca9 + checksum: 10/9f8c53ca29af09cd366e37420410319c8f69e9f4a676513ecd91f5e6d822b9935b6a8ad7ec931d604fc4a0ecd93d51063d0c93227f78f2380196c8a7fa6970d1 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.4.0": - version: 7.4.0 - resolution: "@typescript-eslint/scope-manager@npm:7.4.0" +"@typescript-eslint/scope-manager@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/scope-manager@npm:7.7.0" dependencies: - "@typescript-eslint/types": "npm:7.4.0" - "@typescript-eslint/visitor-keys": "npm:7.4.0" - checksum: 10/8cf9292444f9731017a707cac34bef5ae0eb33b5cd42ed07fcd046e981d97889d9201d48e02f470f2315123f53771435e10b1dc81642af28a11df5352a8e8be2 + "@typescript-eslint/types": "npm:7.7.0" + "@typescript-eslint/visitor-keys": "npm:7.7.0" + checksum: 10/c8890aaf99b57543774e50549c5b178c13695b21a6b30c65292268137fe5e6856cc0e050c118b47b5835dd8a48c96e042fc75891a7f6093a0b94b6b3b251afd9 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:7.4.0": - version: 7.4.0 - resolution: "@typescript-eslint/type-utils@npm:7.4.0" +"@typescript-eslint/type-utils@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/type-utils@npm:7.7.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:7.4.0" - "@typescript-eslint/utils": "npm:7.4.0" + "@typescript-eslint/typescript-estree": "npm:7.7.0" + "@typescript-eslint/utils": "npm:7.7.0" debug: "npm:^4.3.4" - ts-api-utils: "npm:^1.0.1" + ts-api-utils: "npm:^1.3.0" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/a8bd0929d8237679b2b8a7817f070a4b9658ee976882fba8ff37e4a70dd33f87793e1b157771104111fe8054eaa8ad437a010b6aa465072fbdb932647125db2d + checksum: 10/a3f5358b4b7046458ea573607f3d6ea7f48e16524390b24c9360bdf8b03cc89fc6eb5da31b3e541e7f1e5f6958194ecaad5b644ca9b0d90c9a7b182f345451aa languageName: node linkType: hard -"@typescript-eslint/types@npm:7.4.0": - version: 7.4.0 - resolution: "@typescript-eslint/types@npm:7.4.0" - checksum: 10/2782c5bf65cd3dfa9cd32bc3023676bbca22144987c3f6c6b67fd96c73d4a60b85a57458c49fd11b9971ac6531824bb3ae0664491e7a6de25d80c523c9be92b7 +"@typescript-eslint/types@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/types@npm:7.7.0" + checksum: 10/d54ff9eeea168188fcbf1c8efe42892d1646ead801ea0a0f1312c80cfb74ee5dd61a145bc982919fb396683fb4578f98f7ad90e5d466d7aa1ca593e4338e1a2e languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.4.0": - version: 7.4.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.4.0" +"@typescript-eslint/typescript-estree@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.7.0" dependencies: - "@typescript-eslint/types": "npm:7.4.0" - "@typescript-eslint/visitor-keys": "npm:7.4.0" + "@typescript-eslint/types": "npm:7.7.0" + "@typescript-eslint/visitor-keys": "npm:7.7.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" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10/162ec9d7582f45588342e1be36fdb60e41f50bbdfbc3035c91b517ff5d45244f776921c88d88e543e1c7d0f1e6ada5474a8316b78f1b0e6d2233b101bc45b166 + checksum: 10/40af26b3edb07af439f99728aa149bbc8668dae4a700a128abaf98d7f9bc0d5d31f8027aa1d13d6a55b22c20738d7cab84a3046a56417a2551de58671b39dbdf languageName: node linkType: hard -"@typescript-eslint/utils@npm:7.4.0": - version: 7.4.0 - resolution: "@typescript-eslint/utils@npm:7.4.0" +"@typescript-eslint/utils@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/utils@npm:7.7.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:7.4.0" - "@typescript-eslint/types": "npm:7.4.0" - "@typescript-eslint/typescript-estree": "npm:7.4.0" - semver: "npm:^7.5.4" + "@types/json-schema": "npm:^7.0.15" + "@types/semver": "npm:^7.5.8" + "@typescript-eslint/scope-manager": "npm:7.7.0" + "@typescript-eslint/types": "npm:7.7.0" + "@typescript-eslint/typescript-estree": "npm:7.7.0" + semver: "npm:^7.6.0" peerDependencies: eslint: ^8.56.0 - checksum: 10/ffed27e770c486cd000ff892d9049b0afe8b9d6318452a5355b78a37436cbb414bceacae413a2ac813f3e584684825d5e0baa2e6376b7ad6013a108ac91bc19d + checksum: 10/4223233ee022460a74f389302b50779537dfbb3bd414486dca356d2628a08d5b2c4c6002bae3bdffad92b368569024faf25faee9be739340d9459c23549a866f languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.4.0": - version: 7.4.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.4.0" +"@typescript-eslint/visitor-keys@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.7.0" dependencies: - "@typescript-eslint/types": "npm:7.4.0" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 10/70dc99f2ad116c6e2d9e55af249e4453e06bba2ceea515adef2d2e86e97e557865bb1b1d467667462443eb0d624baba36f7442fd1082f3874339bbc381c26e93 + "@typescript-eslint/types": "npm:7.7.0" + eslint-visitor-keys: "npm:^3.4.3" + checksum: 10/9f03591ab60b0b164f6bb222b5d5ae75f73fbe7f264be9318f770be9dc5dff8138d34701928940ffc18924058ae80754a738a1e623912a297d57a8a59cdfb41d languageName: node linkType: hard @@ -4673,128 +4704,128 @@ __metadata: languageName: node linkType: hard -"@vaadin/a11y-base@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/a11y-base@npm:24.3.10" +"@vaadin/a11y-base@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/a11y-base@npm:24.3.11" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.3.10" + "@vaadin/component-base": "npm:~24.3.11" lit: "npm:^3.0.0" - checksum: 10/8c1bb67fea2b6896ea9ec8e54e89432b3a2ced34dc05cd1d106beba80e584bdc4dd9669e013ee44162711c42aa98291378f1308ec4bc1bc9940e185a52149472 + checksum: 10/751dbf6469303a507d81af58725e6eaa858c1924fc5383b26aefadb92b872f2a877588362c5844773be6758cdb436036f1dab259c4dfa78d3d874cce704787c3 languageName: node linkType: hard -"@vaadin/combo-box@npm:24.3.10": - version: 24.3.10 - resolution: "@vaadin/combo-box@npm:24.3.10" +"@vaadin/combo-box@npm:24.3.11": + version: 24.3.11 + resolution: "@vaadin/combo-box@npm:24.3.11" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/a11y-base": "npm:~24.3.10" - "@vaadin/component-base": "npm:~24.3.10" - "@vaadin/field-base": "npm:~24.3.10" - "@vaadin/input-container": "npm:~24.3.10" - "@vaadin/item": "npm:~24.3.10" - "@vaadin/lit-renderer": "npm:~24.3.10" - "@vaadin/overlay": "npm:~24.3.10" - "@vaadin/vaadin-lumo-styles": "npm:~24.3.10" - "@vaadin/vaadin-material-styles": "npm:~24.3.10" - "@vaadin/vaadin-themable-mixin": "npm:~24.3.10" - checksum: 10/66b276a2a21e8a96080a73bb891b81026e6e0e28939b71543952d45d41f2eafc62b6f7240b48d1b46aaeffe96a1e8542ff04bde2fe0d70a231a88b485d12e8ac + "@vaadin/a11y-base": "npm:~24.3.11" + "@vaadin/component-base": "npm:~24.3.11" + "@vaadin/field-base": "npm:~24.3.11" + "@vaadin/input-container": "npm:~24.3.11" + "@vaadin/item": "npm:~24.3.11" + "@vaadin/lit-renderer": "npm:~24.3.11" + "@vaadin/overlay": "npm:~24.3.11" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.11" + "@vaadin/vaadin-material-styles": "npm:~24.3.11" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.11" + checksum: 10/0ea4ccef7ac038eea876a110839e98b6eb58401c4b7783b03c3d6e844828c0bad71529f67905b8bc153058a6d7bd93895333e1642b37aa7765e019d498ea4925 languageName: node linkType: hard -"@vaadin/component-base@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/component-base@npm:24.3.10" +"@vaadin/component-base@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/component-base@npm:24.3.11" 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:^3.0.0" - checksum: 10/20fae1c91f4c7ea2736840b5a241a955ec7c78e41f4219d41b90fc577e53a6cd8034183be63de3fef0a87fb4f2370075d0e20fc6ff13611231ae858f31f81581 + checksum: 10/b6ca4a2ce1ded0f81cab7f2ff18e456bed8c0e2927ca31adceedbb3dac9a9378b221a240ccc745a2c33f4f785a49d4916524e1bed36091059a77dd8f4798022f languageName: node linkType: hard -"@vaadin/field-base@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/field-base@npm:24.3.10" +"@vaadin/field-base@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/field-base@npm:24.3.11" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/a11y-base": "npm:~24.3.10" - "@vaadin/component-base": "npm:~24.3.10" + "@vaadin/a11y-base": "npm:~24.3.11" + "@vaadin/component-base": "npm:~24.3.11" lit: "npm:^3.0.0" - checksum: 10/a98c228201574cbb7d962e9c9b980c27d2c865474617913da71f628354df751e04c7a33c1c6ba0ea44c0082ff52aff682fd4187c3efa32f4c6a6762014cab7dd + checksum: 10/3ef6ad677eb2c0a473577eb5a08b620fa1bf961cdb0b3b61adb5f23be839d6fe4ef498b57ff5976b19b2b556c9f39d5ea479141eac0adaeb81e935132cd50481 languageName: node linkType: hard -"@vaadin/icon@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/icon@npm:24.3.10" +"@vaadin/icon@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/icon@npm:24.3.11" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.3.10" - "@vaadin/vaadin-lumo-styles": "npm:~24.3.10" - "@vaadin/vaadin-themable-mixin": "npm:~24.3.10" + "@vaadin/component-base": "npm:~24.3.11" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.11" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.11" lit: "npm:^3.0.0" - checksum: 10/acc722b27adb123e5456340e1ac70b3ac6976e5a56a814c483261216aa7ea700e3ba6609dc5a1013e49a5030bca83088832979e254de1b1682fb73731074091b + checksum: 10/73b7b4c2c400d430aad1d670b3d5b0f6ebabbd0115f318789cac38929d419f0e007b73c2f358aa72226153a865b7de410da0ddc22e93732ee17bb3b79810a64b languageName: node linkType: hard -"@vaadin/input-container@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/input-container@npm:24.3.10" +"@vaadin/input-container@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/input-container@npm:24.3.11" dependencies: "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.3.10" - "@vaadin/vaadin-lumo-styles": "npm:~24.3.10" - "@vaadin/vaadin-material-styles": "npm:~24.3.10" - "@vaadin/vaadin-themable-mixin": "npm:~24.3.10" + "@vaadin/component-base": "npm:~24.3.11" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.11" + "@vaadin/vaadin-material-styles": "npm:~24.3.11" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.11" lit: "npm:^3.0.0" - checksum: 10/0b62888095c36bb2201b7b91903d02a003ba13db3894ae32c78b863eda883bd799e34084600888b1e7091af2566f2d20c3c7908f1665e411da256a751174c0ef + checksum: 10/e2382dacd1221f8b0ee0996f3fe836370a2a99127514fd155fc671beb4f3f7240d1ce5f20394b6e450a7e73513bf4040b66f474e4caa7df30ed87beda6d39fa0 languageName: node linkType: hard -"@vaadin/item@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/item@npm:24.3.10" +"@vaadin/item@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/item@npm:24.3.11" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/a11y-base": "npm:~24.3.10" - "@vaadin/component-base": "npm:~24.3.10" - "@vaadin/vaadin-lumo-styles": "npm:~24.3.10" - "@vaadin/vaadin-material-styles": "npm:~24.3.10" - "@vaadin/vaadin-themable-mixin": "npm:~24.3.10" - checksum: 10/e2ec3916f20f6dcdc6d359b0a8affe937845e09f9ef3decb15f00a88bb372d485e376434d284fee739f7c8c7dbb6983c02a2ef406398cbc62088da060fe8663e + "@vaadin/a11y-base": "npm:~24.3.11" + "@vaadin/component-base": "npm:~24.3.11" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.11" + "@vaadin/vaadin-material-styles": "npm:~24.3.11" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.11" + checksum: 10/dc05b64399f9d943f90d9e6ad1feaf3783618d933a85f33ab7075431b8a8d12673f98f797856300887cf09cefdeebde8225f6a7509708da801be40f91f124c0f languageName: node linkType: hard -"@vaadin/lit-renderer@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/lit-renderer@npm:24.3.10" +"@vaadin/lit-renderer@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/lit-renderer@npm:24.3.11" dependencies: lit: "npm:^3.0.0" - checksum: 10/a1449affcb6df2ead9443e1be0f07a935388986496c7d6f2401ea72d4ecb6c6bcb7333e90a6699fb3b9b7e3a4736e29ab2a278da0681446d84ece36024a0964c + checksum: 10/14b3049c5a25a2540b68c7d4f6b2be0e3e397e460f246250bf5d0483c73ac4a375add01d1b8f987805ef89e0bfe6c658f4e8dcefd6951cb495be906044afa4d7 languageName: node linkType: hard -"@vaadin/overlay@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/overlay@npm:24.3.10" +"@vaadin/overlay@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/overlay@npm:24.3.11" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" "@polymer/polymer": "npm:^3.0.0" - "@vaadin/a11y-base": "npm:~24.3.10" - "@vaadin/component-base": "npm:~24.3.10" - "@vaadin/vaadin-lumo-styles": "npm:~24.3.10" - "@vaadin/vaadin-material-styles": "npm:~24.3.10" - "@vaadin/vaadin-themable-mixin": "npm:~24.3.10" - checksum: 10/fd55a60a81f34ff3d088360bf9014f99a804c14dfaea8436f1adf92bcc4a0080dd7e164775eb02c79dd2e109dd94b544de8af12e1696150b4d73df8826dfd7f1 + "@vaadin/a11y-base": "npm:~24.3.11" + "@vaadin/component-base": "npm:~24.3.11" + "@vaadin/vaadin-lumo-styles": "npm:~24.3.11" + "@vaadin/vaadin-material-styles": "npm:~24.3.11" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.11" + checksum: 10/2b79099e87e5cfa1500dbe4c48a8b30759dbe69bba28cc8e6991f121f93f8a959b3f62952f14ed14b9cedcc0a6fa7cddab19a5bfb51556c221483629574519ff languageName: node linkType: hard @@ -4805,36 +4836,36 @@ __metadata: languageName: node linkType: hard -"@vaadin/vaadin-lumo-styles@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/vaadin-lumo-styles@npm:24.3.10" +"@vaadin/vaadin-lumo-styles@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/vaadin-lumo-styles@npm:24.3.11" dependencies: "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.3.10" - "@vaadin/icon": "npm:~24.3.10" - "@vaadin/vaadin-themable-mixin": "npm:~24.3.10" - checksum: 10/962dbb77139931774d9cc190fc29a44294f72db0b6abc08bcbc37742f6d2e53b5cec4cf69653b58bc1e1cff657aaefa7fd3a63191c68101e9f59b29b02d7033a + "@vaadin/component-base": "npm:~24.3.11" + "@vaadin/icon": "npm:~24.3.11" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.11" + checksum: 10/b493736672291de9a7357faf99413191c905b8aa3efcb6fddbc3f7c83102fc1ef4ffaa6ebf1883effd2c41cf3ceba9ad51e54558bea42fb0c2e35aa154cd128b languageName: node linkType: hard -"@vaadin/vaadin-material-styles@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/vaadin-material-styles@npm:24.3.10" +"@vaadin/vaadin-material-styles@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/vaadin-material-styles@npm:24.3.11" dependencies: "@polymer/polymer": "npm:^3.0.0" - "@vaadin/component-base": "npm:~24.3.10" - "@vaadin/vaadin-themable-mixin": "npm:~24.3.10" - checksum: 10/f944723a5b569786febc496f47224fe06ce6b49b78a973a7e462ef64023a9f8870735c1e186e32299a589c2f9159335cbd636b9acbaad9ef1ce0580ded9f627d + "@vaadin/component-base": "npm:~24.3.11" + "@vaadin/vaadin-themable-mixin": "npm:~24.3.11" + checksum: 10/f3c718894e56f3705a05d978bde86bbe9ff6f70f317d96f94fb5d495a801ca23065fadf517569fad082d5e024570157c8c265497e3ef21e2d05ab752dedf1115 languageName: node linkType: hard -"@vaadin/vaadin-themable-mixin@npm:24.3.10, @vaadin/vaadin-themable-mixin@npm:~24.3.10": - version: 24.3.10 - resolution: "@vaadin/vaadin-themable-mixin@npm:24.3.10" +"@vaadin/vaadin-themable-mixin@npm:24.3.11, @vaadin/vaadin-themable-mixin@npm:~24.3.11": + version: 24.3.11 + resolution: "@vaadin/vaadin-themable-mixin@npm:24.3.11" dependencies: "@open-wc/dedupe-mixin": "npm:^1.3.0" lit: "npm:^3.0.0" - checksum: 10/28eaf3e9126180b188a7fc29d9c4f17474572fbdb5ff58ae653325e752bfc20f1304073ec1a5a9586f090bcf3b535ab5e5c003db9ef57548ced9e12799aa67e3 + checksum: 10/d18adde6a9c4fa5adf31a9366dc9d55170835b332150741d4e62eca71f0a6d16b7554a07ca788268508b654cf003567e0ff6f1a926b7c26bfba91f578fcd83fa languageName: node linkType: hard @@ -5342,12 +5373,12 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" dependencies: debug: "npm:^4.3.4" - checksum: 10/f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + checksum: 10/c478fec8f79953f118704d007a38f2a185458853f5c45579b9669372bd0e12602e88dc2ad0233077831504f7cd6fcc8251c383375bba5eaaf563b102938bda26 languageName: node linkType: hard @@ -5445,15 +5476,6 @@ __metadata: languageName: node linkType: hard -"ansi-cyan@npm:^0.1.1": - version: 0.1.1 - resolution: "ansi-cyan@npm:0.1.1" - dependencies: - ansi-wrap: "npm:0.1.0" - checksum: 10/5fb11d52bc4d7ab319913b56f876f8e7aff60edd1c119c3d754a33b14d126b7360df70b2d53c5967c29bae03e85149ebaa32f55c33e089e6d06330230983038e - languageName: node - linkType: hard - "ansi-escapes@npm:^4.3.2": version: 4.3.2 resolution: "ansi-escapes@npm:4.3.2" @@ -5464,11 +5486,9 @@ __metadata: linkType: hard "ansi-escapes@npm:^6.2.0": - version: 6.2.0 - resolution: "ansi-escapes@npm:6.2.0" - dependencies: - type-fest: "npm:^3.0.0" - checksum: 10/442f91b04650b35bc4815f47c20412d69ddbba5d4bf22f72ec03be352fca2de6819c7e3f4dfd17816ee4e0c6c965fe85e6f1b3f09683996a8d12fd366afd924e + version: 6.2.1 + resolution: "ansi-escapes@npm:6.2.1" + checksum: 10/3b064937dc8a0645ed8094bc8b09483ee718f3aa3139746280e6c2ea80e28c0a3ce66973d0f33e88e60021abbf67e5f877deabfc810e75edf8a19dfa128850be languageName: node linkType: hard @@ -5490,15 +5510,6 @@ __metadata: languageName: node linkType: hard -"ansi-red@npm:^0.1.1": - version: 0.1.1 - resolution: "ansi-red@npm:0.1.1" - dependencies: - ansi-wrap: "npm:0.1.0" - checksum: 10/84442078e6ae34c79ada32d43d40956e0f953204626be4c562431761407b4388a573cfff950c78a6c8fa20e9eed12441ac8d1c89864d6a35df53e9ef7fce2b98 - languageName: node - linkType: hard - "ansi-regex@npm:^2.0.0": version: 2.1.1 resolution: "ansi-regex@npm:2.1.1" @@ -5630,16 +5641,6 @@ __metadata: languageName: node linkType: hard -"arr-diff@npm:^1.0.1": - version: 1.1.0 - resolution: "arr-diff@npm:1.1.0" - dependencies: - arr-flatten: "npm:^1.0.1" - array-slice: "npm:^0.2.3" - checksum: 10/6fa5aade29ff80a8b704bcb6ae582ad718ea9dc31f213f616ba6185e2e033ce2082f9efead3ebc7d35a992852c74f052823c8a51248f15a535f84f346aa2f402 - languageName: node - linkType: hard - "arr-diff@npm:^4.0.0": version: 4.0.0 resolution: "arr-diff@npm:4.0.0" @@ -5672,13 +5673,6 @@ __metadata: languageName: node linkType: hard -"arr-union@npm:^2.0.1": - version: 2.1.0 - resolution: "arr-union@npm:2.1.0" - checksum: 10/19e21d0a8d184eb86c597541eaf90d9912470ce311b9e14b7b3f1be4fd18535ba3511db046565fb190f8be4f7a9ad3216b670cded3c765e03a0e3928a72085ea - languageName: node - linkType: hard - "arr-union@npm:^3.1.0": version: 3.1.0 resolution: "arr-union@npm:3.1.0" @@ -5725,15 +5719,16 @@ __metadata: linkType: hard "array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" is-string: "npm:^1.0.7" - checksum: 10/856a8be5d118967665936ad33ff3b07adfc50b06753e596e91fb80c3da9b8c022e92e3cc6781156d6ad95db7109b9f603682c7df2d6a529ed01f7f6b39a4a360 + checksum: 10/290b206c9451f181fb2b1f79a3bf1c0b66bb259791290ffbada760c79b284eef6f5ae2aeb4bcff450ebc9690edd25732c4c73a3c2b340fcc0f4563aed83bf488 languageName: node linkType: hard @@ -5756,13 +5751,6 @@ __metadata: languageName: node linkType: hard -"array-slice@npm:^0.2.3": - version: 0.2.3 - resolution: "array-slice@npm:0.2.3" - checksum: 10/9d35c15d05a160c9a85bbdfe79cb6c291d3c84bd46c4da632d235a4f5102e6f8b0b844a3082aeaf33cbb3ba54513b7732990788e7a6a62b55e800ca180180390 - languageName: node - linkType: hard - "array-slice@npm:^1.0.0": version: 1.1.0 resolution: "array-slice@npm:1.1.0" @@ -5796,27 +5784,29 @@ __metadata: linkType: hard "array.prototype.find@npm:^2.2.2": - version: 2.2.2 - resolution: "array.prototype.find@npm:2.2.2" + version: 2.2.3 + resolution: "array.prototype.find@npm:2.2.3" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - es-shim-unscopables: "npm:^1.0.0" - checksum: 10/d6b88bdbbc84851061e3689617748781c85228282ee923b556b70a3ac664bdb016803dc6aaf58666b47b5cdfc52cdb2395114fdc5bac08b69be25504c276840d + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/8ee81d37de9c8574a94f4773dffa40b4d200deca11b00f7176dcb328a9ddcf75fef117c97ccce1ab8345b7184c107553156908e7dcaf0d42f1a395a04bbe803e languageName: node linkType: hard "array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.4 - resolution: "array.prototype.findlastindex@npm:1.2.4" + version: 1.2.5 + resolution: "array.prototype.findlastindex@npm:1.2.5" dependencies: - call-bind: "npm:^1.0.5" + call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.22.3" + es-abstract: "npm:^1.23.2" es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" es-shim-unscopables: "npm:^1.0.2" - checksum: 10/12d7de8da619065b9d4c40550d11c13f2fbbc863c4270ef01d022f49ef16fbe9022441ee9d60b1e952853c661dd4b3e05c21e4348d4631c6d93ddf802a252296 + checksum: 10/7c5c821f357cd53ab6cc305de8086430dd8d7a2485db87b13f843e868055e9582b1fd338f02338f67fc3a1603ceaf9610dd2a470b0b506f9d18934780f95b246 languageName: node linkType: hard @@ -5944,9 +5934,9 @@ __metadata: linkType: hard "axe-core@npm:^4.3.3": - version: 4.8.4 - resolution: "axe-core@npm:4.8.4" - checksum: 10/c8b3972b17afac33b9e151556fa500b9218086ca763866942de30e7f51ac50582902ad03ec16381796c95afaacfa8c33efb2d02ab4f09b6c09d6be58b95da978 + version: 4.9.0 + resolution: "axe-core@npm:4.9.0" + checksum: 10/d337c4600e522bb85ed7b242e8eea322892025bc3c951fcda4845a664f9cfb065c509bc17428315c7f8571a4b5c55552d9011d752a6aae8be006bfa54d725a42 languageName: node linkType: hard @@ -6042,9 +6032,9 @@ __metadata: linkType: hard "bare-events@npm:^2.2.0": - version: 2.2.1 - resolution: "bare-events@npm:2.2.1" - checksum: 10/a2c96a638e5a049960e42660320bcd9e3c5e83da2072e4c05080661219eae744931751be86c814590dcce5107c30cbb60dc2d15097b1b14e2f42db1cd9b80898 + version: 2.2.2 + resolution: "bare-events@npm:2.2.2" + checksum: 10/79d50a739d9f2173e881e0957f9b0ee64befde3d7b6f955b1450de06a4c131f095415beaafa9772caa23c2ddfd70c56def0a3c5841b21488b7ff2c91d9f9898a languageName: node linkType: hard @@ -6107,16 +6097,6 @@ __metadata: languageName: node linkType: hard -"bl@npm:^1.2.1": - version: 1.2.3 - resolution: "bl@npm:1.2.3" - dependencies: - readable-stream: "npm:^2.3.5" - safe-buffer: "npm:^5.1.1" - checksum: 10/11d775b09ebd7d8c0df1ed7efd03cc8a2b1283c804a55153c81a0b586728a085fa24240647cac9a60163eb6f36a28cf8c45b80bf460a46336d4c84c40205faff - languageName: node - linkType: hard - "blocking-elements@npm:^0.1.0": version: 0.1.1 resolution: "blocking-elements@npm:0.1.1" @@ -6395,9 +6375,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001587": - version: 1.0.30001599 - resolution: "caniuse-lite@npm:1.0.30001599" - checksum: 10/c9a5ad806fc0d446e4f995d551b840d8fdcbe97958b7f83ff7a255a8ef5e40ca12ca1a508c66b3ab147e19eef932d28772d205c046500dd0740ea9dfb602e2e1 + version: 1.0.30001611 + resolution: "caniuse-lite@npm:1.0.30001611" + checksum: 10/24710a9cc026e564508fad6905d93d2be14ff38af6e08dce651521e7f4e87b2d2863dd8976da5349173e0c10b47377634238890dc34aa6d44a4d0ca3b1f6e236 languageName: node linkType: hard @@ -6535,6 +6515,13 @@ __metadata: languageName: node linkType: hard +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10/b63cb1f73d171d140a2ed8154ee6566c8ab775d3196b0e03a2a94b5f6a0ce7777ee5685ca56849403c8d17bd457a6540672f9a60696a6137c7a409097495b82c + languageName: node + linkType: hard + "chrome-trace-event@npm:^1.0.2": version: 1.0.3 resolution: "chrome-trace-event@npm:1.0.3" @@ -7012,18 +6999,18 @@ __metadata: linkType: hard "core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.36.1": - version: 3.36.1 - resolution: "core-js-compat@npm:3.36.1" + version: 3.37.0 + resolution: "core-js-compat@npm:3.37.0" dependencies: browserslist: "npm:^4.23.0" - checksum: 10/d86b46805de7f5ba3675ed21532ecc64b6c1f123be7286b9efa7941ec087cd8d2446cb555f03a407dbbbeb6e881d1baf92eaffb7f051b11d9103f39c8731fa62 + checksum: 10/5f33d7ba45acc9ceb45544d844090edfd14e46a64c2424df24084347405182c1156588cc3a877fc580c005a0b13b8a1af26bb6c73fe73f22eede89b5483b482d languageName: node linkType: hard -"core-js@npm:3.36.1": - version: 3.36.1 - resolution: "core-js@npm:3.36.1" - checksum: 10/ce1e1bfc1034b6f2ff7c91077319e8abdd650ee606ffe6e80073e64ab9d8aad2d6a6d953461b01f331a6f796ad2fd766a3386b88aa371b45d44fa7c0b9913ce6 +"core-js@npm:3.37.0": + version: 3.37.0 + resolution: "core-js@npm:3.37.0" + checksum: 10/97feac0b54b95d928bda6a6e611cf34963a265a5fe8ab46ed35bbc9d32a14221bf6bede5d6cd4b0c0f30e8440cf1eff0c4f0c242d719c561e5dd73d3b005d63c languageName: node linkType: hard @@ -7123,21 +7110,19 @@ __metadata: languageName: node linkType: hard -"date-fns-tz@npm:2.0.1": - version: 2.0.1 - resolution: "date-fns-tz@npm:2.0.1" +"date-fns-tz@npm:3.1.3": + version: 3.1.3 + resolution: "date-fns-tz@npm:3.1.3" peerDependencies: - date-fns: 2.x - checksum: 10/f12e684bc13c9fe7ef7910c5b25437e15290a655d45102b7420f046cecdf9fa5715bf333d6dfb6bab6c382c7abc6b58241a50c216e9ab0b60d6fdb388f473d6b + date-fns: ^3.0.0 + checksum: 10/eb5cb3b2cd152340004efda9f7905e571cf5140b8e85267b1eaa36c2f1eaa54a0f2e3b26e19794f2aca4d3b15aa3d52a5b2dadb540fcec74b239049c7792a981 languageName: node linkType: hard -"date-fns@npm:2.30.0": - version: 2.30.0 - resolution: "date-fns@npm:2.30.0" - dependencies: - "@babel/runtime": "npm:^7.21.0" - checksum: 10/70b3e8ea7aaaaeaa2cd80bd889622a4bcb5d8028b4de9162cbcda359db06e16ff6e9309e54eead5341e71031818497f19aaf9839c87d1aba1e27bb4796e758a9 +"date-fns@npm:3.6.0": + version: 3.6.0 + resolution: "date-fns@npm:3.6.0" + checksum: 10/cac35c58926a3b5d577082ff2b253612ec1c79eb6754fddef46b6a8e826501ea2cb346ecbd211205f1ba382ddd1f9d8c3f00bf433ad63cc3063454d294e3a6b8 languageName: node linkType: hard @@ -7561,27 +7546,27 @@ __metadata: linkType: hard "ejs@npm:^3.1.6": - version: 3.1.9 - resolution: "ejs@npm:3.1.9" + version: 3.1.10 + resolution: "ejs@npm:3.1.10" dependencies: jake: "npm:^10.8.5" bin: ejs: bin/cli.js - checksum: 10/71f56d37540d2c2d71701f0116710c676f75314a3e997ef8b83515d5d4d2b111c5a72725377caeecb928671bacb84a0d38135f345904812e989847057d59f21a + checksum: 10/a9cb7d7cd13b7b1cd0be5c4788e44dd10d92f7285d2f65b942f33e127230c054f99a42db4d99f766d8dbc6c57e94799593ee66a14efd7c8dd70c4812bf6aa384 languageName: node linkType: hard "electron-to-chromium@npm:^1.4.668": - version: 1.4.710 - resolution: "electron-to-chromium@npm:1.4.710" - checksum: 10/9f20e58d35350141e3c8d8ea577249cacf91e91ac57be2ad631606c4fb2ee627c6054e4dff152800c438faa1dc1cd14ae244a9e270eaec11821e0de263ff5de5 + version: 1.4.743 + resolution: "electron-to-chromium@npm:1.4.743" + checksum: 10/e8c2db1f6bc55c9edf20819afaa93682309bc91078e01918aff8c9b4f7ac109fb43223f09468ea0559216e608e9a3c24a73adab4cc872ebdc3ad41f7b2d692e9 languageName: node linkType: hard -"element-internals-polyfill@npm:1.3.10": - version: 1.3.10 - resolution: "element-internals-polyfill@npm:1.3.10" - checksum: 10/156fed2c83b309714d7241d73d741798bfd4177e73cef0f105735b87a5fd0791d8e09d44eddfda5bc4b6ba411777d43994894e2f2ec352d4b144454cb7c2e07f +"element-internals-polyfill@npm:1.3.11": + version: 1.3.11 + resolution: "element-internals-polyfill@npm:1.3.11" + checksum: 10/8e86562c84cac451801c8d1593e8d8d7224a91e85037f0b651072a628f7e3b23155c3d520d369be9a733e9675f7fc0763a6ca61f54f5485f6840eb5709bf269e languageName: node linkType: hard @@ -7674,11 +7659,11 @@ __metadata: linkType: hard "envinfo@npm:^7.7.3": - version: 7.11.1 - resolution: "envinfo@npm:7.11.1" + version: 7.12.0 + resolution: "envinfo@npm:7.12.0" bin: envinfo: dist/cli.js - checksum: 10/5a18ead05954ac1643350170fefce2436a9cb758dc402e36fe4616553ee46469f766fcb6df72379d1741a2e5b55918949b343ff6174502c31c524a5cf75f05cd + checksum: 10/981fbc80d484e42aa2c86d637ab0db773b67c285116561e50f49b5d2cb95cfd7c381d323196c487a1fa95d461ae787857559f08cf68c01be114449527f757df8 languageName: node linkType: hard @@ -7708,8 +7693,8 @@ __metadata: linkType: hard "es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2": - version: 1.23.2 - resolution: "es-abstract@npm:1.23.2" + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" dependencies: array-buffer-byte-length: "npm:^1.0.1" arraybuffer.prototype.slice: "npm:^1.0.3" @@ -7750,14 +7735,14 @@ __metadata: safe-regex-test: "npm:^1.0.3" string.prototype.trim: "npm:^1.2.9" string.prototype.trimend: "npm:^1.0.8" - string.prototype.trimstart: "npm:^1.0.7" + string.prototype.trimstart: "npm:^1.0.8" typed-array-buffer: "npm:^1.0.2" typed-array-byte-length: "npm:^1.0.1" typed-array-byte-offset: "npm:^1.0.2" - typed-array-length: "npm:^1.0.5" + typed-array-length: "npm:^1.0.6" unbox-primitive: "npm:^1.0.2" which-typed-array: "npm:^1.1.15" - checksum: 10/f8fa0ef674b176f177f637f1af13fb895d10306e1eb1f57dc48a5aa64a643da307f96b222054ff76f3fd9029983295192c55fc54169f464ad2fcee992c5b7310 + checksum: 10/2da795a6a1ac5fc2c452799a409acc2e3692e06dc6440440b076908617188899caa562154d77263e3053bcd9389a07baa978ab10ac3b46acc399bd0c77be04cb languageName: node linkType: hard @@ -7778,9 +7763,9 @@ __metadata: linkType: hard "es-module-lexer@npm:^1.0.0, es-module-lexer@npm:^1.2.1": - version: 1.4.1 - resolution: "es-module-lexer@npm:1.4.1" - checksum: 10/cf453613468c417af6e189b03d9521804033fdd5a229a36fedec28d37ea929fccf6822d42abff1126eb01ba1d2aa2845a48d5d1772c0724f8204464d9d3855f6 + version: 1.5.0 + resolution: "es-module-lexer@npm:1.5.0" + checksum: 10/d0e198d8642cb42aa82d86f2c6830cb6786916171a3e693046c11500c0cb62e77703940e58757db8aafa8a86fa2a9cc1c493dcd22c0b03c4a72dede3ce5c7dd1 languageName: node linkType: hard @@ -8075,15 +8060,15 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-wc@npm:2.0.4": - version: 2.0.4 - resolution: "eslint-plugin-wc@npm:2.0.4" +"eslint-plugin-wc@npm:2.1.0": + version: 2.1.0 + resolution: "eslint-plugin-wc@npm:2.1.0" dependencies: is-valid-element-name: "npm:^1.0.0" js-levenshtein-esm: "npm:^1.2.0" peerDependencies: eslint: ">=5" - checksum: 10/fcdbf34946009ee58cd43a520ed53a16a4eb208cca26449e48d3ce32fcecb75fea31887cca1986ce9d71c011ecd3b8785c6bed464e0902e5f59bb093bc01a511 + checksum: 10/d0d7e8377103282dc8836a347dde923b24075e910d85dc32767bb118d82b31a2597ad57b4eb2359ac4322e5239e6ca064c3be7ab8e82eeb6aff4684a472625a0 languageName: node linkType: hard @@ -8417,15 +8402,6 @@ __metadata: languageName: node linkType: hard -"extend-shallow@npm:^1.1.2": - version: 1.1.4 - resolution: "extend-shallow@npm:1.1.4" - dependencies: - kind-of: "npm:^1.1.0" - checksum: 10/437ebb676d031cf98b9952220ef026593bde81f8f100b9f3793b4872a8cc6905d1ef9301c8f8958aed6bc0c5472872f96f43cf417b43446a84a28e67d984a0a6 - languageName: node - linkType: hard - "extend-shallow@npm:^2.0.1": version: 2.0.1 resolution: "extend-shallow@npm:2.0.1" @@ -9177,18 +9153,18 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.3.10, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.3.10 - resolution: "glob@npm:10.3.10" +"glob@npm:10.3.12, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": + version: 10.3.12 + resolution: "glob@npm:10.3.12" dependencies: foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.5" + jackspeak: "npm:^2.3.6" minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" + minipass: "npm:^7.0.4" + path-scurry: "npm:^1.10.2" bin: glob: dist/esm/bin.mjs - checksum: 10/38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 + checksum: 10/9e8186abc22dc824b5dd86cefd8e6b5621a72d1be7f68bacc0fd681e8c162ec5546660a6ec0553d6a74757a585e655956c7f8f1a6d24570e8d865c307323d178 languageName: node linkType: hard @@ -9372,16 +9348,6 @@ __metadata: languageName: node linkType: hard -"gulp-flatmap@npm:1.0.2": - version: 1.0.2 - resolution: "gulp-flatmap@npm:1.0.2" - dependencies: - plugin-error: "npm:0.1.2" - through2: "npm:2.0.3" - checksum: 10/31db36c97d74ee0572e269b029e5968e99b820ed39a8d5624147ecba94db1e297258895ecd3f3187dac394b585796f6cf66cd2a120b734a6953bb4020defd1b2 - languageName: node - linkType: hard - "gulp-json-transform@npm:0.5.0": version: 0.5.0 resolution: "gulp-json-transform@npm:0.5.0" @@ -9589,22 +9555,22 @@ __metadata: version: 0.0.0-use.local resolution: "home-assistant-frontend@workspace:." dependencies: - "@babel/core": "npm:7.24.3" + "@babel/core": "npm:7.24.4" "@babel/helper-define-polyfill-provider": "npm:0.6.1" "@babel/plugin-proposal-decorators": "npm:7.24.1" "@babel/plugin-transform-runtime": "npm:7.24.3" - "@babel/preset-env": "npm:7.24.3" + "@babel/preset-env": "npm:7.24.4" "@babel/preset-typescript": "npm:7.24.1" - "@babel/runtime": "npm:7.24.1" + "@babel/runtime": "npm:7.24.4" "@braintree/sanitize-url": "npm:7.0.1" "@bundle-stats/plugin-webpack-filter": "npm:4.12.2" - "@codemirror/autocomplete": "npm:6.15.0" - "@codemirror/commands": "npm:6.3.3" + "@codemirror/autocomplete": "npm:6.16.0" + "@codemirror/commands": "npm:6.5.0" "@codemirror/language": "npm:6.10.1" - "@codemirror/legacy-modes": "npm:6.3.3" + "@codemirror/legacy-modes": "npm:6.4.0" "@codemirror/search": "npm:6.5.6" "@codemirror/state": "npm:6.4.1" - "@codemirror/view": "npm:6.26.1" + "@codemirror/view": "npm:6.26.3" "@egjs/hammerjs": "npm:2.0.17" "@formatjs/intl-datetimeformat": "npm:6.12.3" "@formatjs/intl-displaynames": "npm:6.6.6" @@ -9626,7 +9592,7 @@ __metadata: "@lit-labs/motion": "npm:1.0.7" "@lit-labs/observers": "npm:2.0.2" "@lit-labs/virtualizer": "npm:2.0.12" - "@lokalise/node-api": "npm:12.3.0" + "@lokalise/node-api": "npm:12.4.0" "@lrnwebcomponents/simple-tooltip": "npm:8.0.2" "@material/chips": "npm:=14.0.0-canary.53b3cad2f.0" "@material/data-table": "npm:=14.0.0-canary.53b3cad2f.0" @@ -9654,12 +9620,12 @@ __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.3.0" + "@material/web": "npm:1.4.1" "@mdi/js": "npm:7.4.47" "@mdi/svg": "npm:7.4.47" - "@octokit/auth-oauth-device": "npm:7.0.1" - "@octokit/plugin-retry": "npm:7.0.3" - "@octokit/rest": "npm:20.0.2" + "@octokit/auth-oauth-device": "npm:7.1.1" + "@octokit/plugin-retry": "npm:7.1.0" + "@octokit/rest": "npm:20.1.0" "@open-wc/dev-server-hmr": "npm:0.1.4" "@polymer/paper-item": "npm:3.0.1" "@polymer/paper-listbox": "npm:3.0.1" @@ -9672,26 +9638,26 @@ __metadata: "@rollup/plugin-replace": "npm:5.0.5" "@thomasloven/round-slider": "npm:0.6.0" "@types/babel__plugin-transform-runtime": "npm:7.9.5" - "@types/chromecast-caf-receiver": "npm:6.0.13" + "@types/chromecast-caf-receiver": "npm:6.0.14" "@types/chromecast-caf-sender": "npm:1.0.9" - "@types/color-name": "npm:1.1.3" + "@types/color-name": "npm:1.1.4" "@types/glob": "npm:8.1.0" "@types/html-minifier-terser": "npm:7.0.2" "@types/js-yaml": "npm:4.0.9" - "@types/leaflet": "npm:1.9.8" + "@types/leaflet": "npm:1.9.11" "@types/leaflet-draw": "npm:1.0.11" "@types/luxon": "npm:3.4.2" "@types/mocha": "npm:10.0.6" "@types/qrcode": "npm:1.5.5" "@types/serve-handler": "npm:6.1.4" "@types/sortablejs": "npm:1.15.8" - "@types/tar": "npm:6.1.11" + "@types/tar": "npm:6.1.13" "@types/ua-parser-js": "npm:0.7.39" "@types/webspeechapi": "npm:0.0.29" - "@typescript-eslint/eslint-plugin": "npm:7.4.0" - "@typescript-eslint/parser": "npm:7.4.0" - "@vaadin/combo-box": "npm:24.3.10" - "@vaadin/vaadin-themable-mixin": "npm:24.3.10" + "@typescript-eslint/eslint-plugin": "npm:7.7.0" + "@typescript-eslint/parser": "npm:7.7.0" + "@vaadin/combo-box": "npm:24.3.11" + "@vaadin/vaadin-themable-mixin": "npm:24.3.11" "@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" @@ -9707,14 +9673,14 @@ __metadata: chart.js: "npm:4.4.2" color-name: "npm:2.0.0" comlink: "npm:4.4.1" - core-js: "npm:3.36.1" + core-js: "npm:3.37.0" cropperjs: "npm:1.6.1" - date-fns: "npm:2.30.0" - date-fns-tz: "npm:2.0.1" + date-fns: "npm:3.6.0" + date-fns-tz: "npm:3.1.3" deep-clone-simple: "npm:1.1.1" deep-freeze: "npm:0.0.1" del: "npm:7.1.0" - element-internals-polyfill: "npm:1.3.10" + element-internals-polyfill: "npm:1.3.11" eslint: "npm:8.57.0" eslint-config-airbnb-base: "npm:15.0.0" eslint-config-airbnb-typescript: "npm:18.0.0" @@ -9725,20 +9691,19 @@ __metadata: eslint-plugin-lit: "npm:1.11.0" eslint-plugin-lit-a11y: "npm:4.1.2" eslint-plugin-unused-imports: "npm:3.1.0" - eslint-plugin-wc: "npm:2.0.4" + eslint-plugin-wc: "npm:2.1.0" fancy-log: "npm:2.0.0" fs-extra: "npm:11.2.0" fuse.js: "npm:7.0.0" - glob: "npm:10.3.10" + glob: "npm:10.3.12" google-timezones-json: "npm:1.2.0" gulp: "npm:4.0.2" - gulp-flatmap: "npm:1.0.2" gulp-json-transform: "npm:0.5.0" gulp-merge-json: "npm:2.2.1" gulp-rename: "npm:2.0.0" gulp-zopfli-green: "npm:6.0.1" hls.js: "patch:hls.js@npm%3A1.5.7#~/.yarn/patches/hls.js-npm-1.5.7-f5bbd3d060.patch" - home-assistant-js-websocket: "npm:9.2.1" + home-assistant-js-websocket: "npm:9.3.0" html-minifier-terser: "npm:7.2.0" husky: "npm:9.0.11" idb-keyval: "npm:6.2.1" @@ -9753,11 +9718,11 @@ __metadata: lit-analyzer: "npm:2.0.3" lodash.template: "npm:4.5.0" luxon: "npm:3.4.4" - magic-string: "npm:0.30.8" + magic-string: "npm:0.30.10" map-stream: "npm:0.0.7" - marked: "npm:12.0.1" + marked: "npm:12.0.2" memoize-one: "npm:6.0.0" - mocha: "npm:10.3.0" + mocha: "npm:10.4.0" node-vibrant: "npm:3.2.1-alpha.1" object-hash: "npm:3.0.0" open: "npm:10.1.0" @@ -9780,18 +9745,16 @@ __metadata: stacktrace-js: "npm:2.0.2" superstruct: "npm:1.0.4" systemjs: "npm:6.14.3" - tar: "npm:6.2.1" + tar: "npm:7.0.1" terser-webpack-plugin: "npm:5.3.10" tinykeys: "npm:2.1.0" - transform-async-modules-webpack-plugin: "npm:1.0.4" + transform-async-modules-webpack-plugin: "npm:1.1.0" ts-lit-plugin: "npm:2.0.2" tsparticles-engine: "npm:2.12.0" tsparticles-preset-links: "npm:2.12.0" - typescript: "npm:5.4.3" + typescript: "npm:5.4.5" ua-parser-js: "npm:1.0.37" unfetch: "npm:5.0.0" - vinyl-buffer: "npm:1.0.1" - vinyl-source-stream: "npm:2.0.0" vis-data: "npm:7.1.9" vis-network: "npm:9.1.9" vue: "npm:2.7.16" @@ -9814,10 +9777,10 @@ __metadata: languageName: unknown linkType: soft -"home-assistant-js-websocket@npm:9.2.1": - version: 9.2.1 - resolution: "home-assistant-js-websocket@npm:9.2.1" - checksum: 10/0508aacb4285c805953e620968ef7ca7fc9c3cdac18fa723dd9af128dff74ef2ec65fad4079353b80363cd1daec6d2798b46d2d40a7e4ff5c0807ac71080bf58 +"home-assistant-js-websocket@npm:9.3.0": + version: 9.3.0 + resolution: "home-assistant-js-websocket@npm:9.3.0" + checksum: 10/0afbe9f327c3f917187422db1b800383530846724ed8985bb076f6312a10580baeff706d45fba3d840348b76e261eab3f3f7c0b4597340d7575b9b09fc41b0c7 languageName: node linkType: hard @@ -10070,7 +10033,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.0, ignore@npm:^5.2.4": +"ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.1": version: 5.3.1 resolution: "ignore@npm:5.3.1" checksum: 10/0a884c2fbc8c316f0b9f92beaf84464253b73230a4d4d286697be45fca081199191ca33e1c2e82d9e5f851f5e9a48a78e25a35c951e7eb41e59f150db3530065 @@ -10184,7 +10147,7 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.5, internal-slot@npm:^1.0.7": +"internal-slot@npm:^1.0.7": version: 1.0.7 resolution: "internal-slot@npm:1.0.7" dependencies: @@ -10558,9 +10521,9 @@ __metadata: linkType: hard "is-network-error@npm:^1.0.0": - version: 1.0.1 - resolution: "is-network-error@npm:1.0.1" - checksum: 10/165d61500c4186c62db5a3a693d6bfa14ca40fe9b471ef4cd4f27b20ef6760880faf5386dc01ca9867531631782941fedaa94521d09959edf71f046e393c7b91 + version: 1.1.0 + resolution: "is-network-error@npm:1.1.0" + checksum: 10/b2fe6aac07f814a9de275efd05934c832c129e7ba292d27614e9e8eec9e043b7a0bbeaeca5d0916b0f462edbec2aa2eaee974ee0a12ac095040e9515c222c251 languageName: node linkType: hard @@ -10870,7 +10833,7 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.3.5": +"jackspeak@npm:^2.3.6": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" dependencies: @@ -11102,13 +11065,6 @@ __metadata: languageName: node linkType: hard -"kind-of@npm:^1.1.0": - version: 1.1.0 - resolution: "kind-of@npm:1.1.0" - checksum: 10/29a95ed9d72d2bc8e3cc86dc461b5a61bde9e931f39158c183d76c5c9b83a0659766520f202473f45b06bce517eece7af061e04ba5fcdfbffe7eb80aedf4743a - languageName: node - linkType: hard - "kind-of@npm:^3.0.2, kind-of@npm:^3.0.3, kind-of@npm:^3.2.0": version: 3.2.2 resolution: "kind-of@npm:3.2.2" @@ -11189,8 +11145,8 @@ __metadata: linkType: hard "koa@npm:^2.13.0": - version: 2.15.1 - resolution: "koa@npm:2.15.1" + version: 2.15.3 + resolution: "koa@npm:2.15.3" dependencies: accepts: "npm:^1.3.5" cache-content-type: "npm:^1.0.0" @@ -11215,7 +11171,7 @@ __metadata: statuses: "npm:^1.5.0" type-is: "npm:^1.6.16" vary: "npm:^1.1.2" - checksum: 10/494e3deaa26879744a0f145cbd12ad1020a54dea327b50e2074e336697dfba3c45cb63f76a8bcc546183347286b254b8aa49b63a32eebad6de0a046edd58db48 + checksum: 10/b2c2771a4ee5268f9d039ce025b9c3798a0baba8c3cf3895a6fc2d286363e0cd2c98c02a5b87f14100baa2bc17d854eed6ed80f9bd41afda1d056f803b206514 languageName: node linkType: hard @@ -11647,7 +11603,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": version: 10.2.0 resolution: "lru-cache@npm:10.2.0" checksum: 10/502ec42c3309c0eae1ce41afca471f831c278566d45a5273a0c51102dee31e0e250a62fa9029c3370988df33a14188a38e682c16143b794de78668de3643e302 @@ -11679,12 +11635,12 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:0.30.8, magic-string@npm:^0.30.3": - version: 0.30.8 - resolution: "magic-string@npm:0.30.8" +"magic-string@npm:0.30.10, magic-string@npm:^0.30.3": + version: 0.30.10 + resolution: "magic-string@npm:0.30.10" dependencies: "@jridgewell/sourcemap-codec": "npm:^1.4.15" - checksum: 10/72ab63817af600e92c19dc8489c1aa4a9599da00cfd59b2319709bd48fb0cf533fdf354bf140ac86e598dbd63e6b2cc83647fe8448f864a3eb6061c62c94e784 + checksum: 10/9f8bf6363a14c98a9d9f32ef833b194702a5c98fb931b05ac511b76f0b06fd30ed92beda6ca3261d2d52d21e39e891ef1136fbd032023f6cbb02d0b7d5767201 languageName: node linkType: hard @@ -11757,12 +11713,12 @@ __metadata: languageName: node linkType: hard -"marked@npm:12.0.1": - version: 12.0.1 - resolution: "marked@npm:12.0.1" +"marked@npm:12.0.2": + version: 12.0.2 + resolution: "marked@npm:12.0.2" bin: marked: bin/marked.js - checksum: 10/34fd0044ebeda28b3f3f94f340e2388666408315557f125d561b59b49baec4c6e6777f54b6fb12aa5c2bf3b75a4aa9f1809679bfb6502da73053d0461c1a232d + checksum: 10/24d4fc58d37c1779197fa7f93c504d8c71d4df54eb69cbbc14a55ba2a8e2ad83d723801fc25452c21ce74b38a483c5863c53449f130253a597be9e9c1d3e7e2b languageName: node linkType: hard @@ -11795,11 +11751,11 @@ __metadata: linkType: hard "memfs@npm:^4.6.0": - version: 4.7.7 - resolution: "memfs@npm:4.7.7" + version: 4.8.2 + resolution: "memfs@npm:4.8.2" dependencies: tslib: "npm:^2.0.0" - checksum: 10/311633e5857c91f41021b43f00eda8d540fed2c2d9e02c780fe78de720cfb55d15ab2d5b5ce9f2576637589b82e84488f1b9ff503563e817ed65200ad24617fb + checksum: 10/9cc1d1ce0ecb7cf91b1c0a29cb661ff0bde7471e8d902bbd465da6e0c49b4b3917309042a0ce7af82fa130b130e8b55688f7ac306c03e51639eb44eea6ffd75a languageName: node linkType: hard @@ -11965,15 +11921,6 @@ __metadata: languageName: node linkType: hard -"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: 10/c81b47d28153e77521877649f4bab48348d10938df9e8147a58111fe00ef89559a2938de9f6632910c4f7bf7bb5cd81191a546167e58d357f0cfb1e18cecc1c5 - languageName: node - linkType: hard - "minimatch@npm:^5.0.1": version: 5.1.6 resolution: "minimatch@npm:5.1.6" @@ -11983,6 +11930,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.1, minimatch@npm:^9.0.4": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10/4cdc18d112b164084513e890d6323370db14c22249d536ad1854539577a895e690a27513dc346392f61a4a50afbbd8abc88f3f25558bfbbbb862cd56508b20f5 + languageName: node + linkType: hard + "minimist@npm:^1.2.0, minimist@npm:^1.2.6": version: 1.2.8 resolution: "minimist@npm:1.2.8" @@ -12064,7 +12020,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, 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, minipass@npm:^7.0.4": version: 7.0.4 resolution: "minipass@npm:7.0.4" checksum: 10/e864bd02ceb5e0707696d58f7ce3a0b89233f0d686ef0d447a66db705c0846a8dc6f34865cd85256c1472ff623665f616b90b8ff58058b2ad996c5de747d2d18 @@ -12081,6 +12037,16 @@ __metadata: languageName: node linkType: hard +"minizlib@npm:^3.0.1": + version: 3.0.1 + resolution: "minizlib@npm:3.0.1" + dependencies: + minipass: "npm:^7.0.4" + rimraf: "npm:^5.0.5" + checksum: 10/622cb85f51e5c206a080a62d20db0d7b4066f308cb6ce82a9644da112367c3416ae7062017e631eb7ac8588191cfa4a9a279b8651c399265202b298e98c4acef + languageName: node + linkType: hard + "mixin-deep@npm:^1.2.0": version: 1.3.2 resolution: "mixin-deep@npm:1.3.2" @@ -12111,9 +12077,18 @@ __metadata: languageName: node linkType: hard -"mocha@npm:10.3.0": - version: 10.3.0 - resolution: "mocha@npm:10.3.0" +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10/16fd79c28645759505914561e249b9a1f5fe3362279ad95487a4501e4467abeb714fd35b95307326b8fd03f3c7719065ef11a6f97b7285d7888306d1bd2232ba + languageName: node + linkType: hard + +"mocha@npm:10.4.0": + version: 10.4.0 + resolution: "mocha@npm:10.4.0" dependencies: ansi-colors: "npm:4.1.1" browser-stdout: "npm:1.3.1" @@ -12138,7 +12113,7 @@ __metadata: bin: _mocha: bin/_mocha mocha: bin/mocha.js - checksum: 10/8b30b3fdb3f365fca7e069fce732e13db4192e1bf8f49e63ec67a3b7857c41cbcd162289ad22178db6ef405fb251b8a0dbb54e942d08c72abf45e1ec3fcdd052 + checksum: 10/0147b2a86c8a3b134b3bda949006aa5f2b08db606b9394e38eb3fa0d97dd2f54f06eb4afb270d4ae08aa6fb7674282737ed556b9a8bc407f9b8488380852eca4 languageName: node linkType: hard @@ -12285,8 +12260,8 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 10.0.1 - resolution: "node-gyp@npm:10.0.1" + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" @@ -12300,7 +12275,7 @@ __metadata: which: "npm:^4.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 10/578cf0c821f258ce4b6ebce4461eca4c991a4df2dee163c0624f2fe09c7d6d37240be4942285a0048d307230248ee0b18382d6623b9a0136ce9533486deddfa8 + checksum: 10/89e105e495e66cd4568af3cf79cdeb67d670eb069e33163c7781d3366470a30367c9bd8dea59e46db16370020139e5bf78b1fbc03284cb571754dfaa59744db5 languageName: node linkType: hard @@ -13005,13 +12980,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" +"path-scurry@npm:^1.10.2": + version: 1.10.2 + resolution: "path-scurry@npm:1.10.2" dependencies: - lru-cache: "npm:^9.1.1 || ^10.0.0" + lru-cache: "npm:^10.2.0" minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10/eebfb8304fef1d4f7e1486df987e4fd77413de4fce16508dea69fcf8eb318c09a6b15a7a2f4c22877cec1cb7ecbd3071d18ca9de79eeece0df874a00f1f0bdc8 + checksum: 10/a2bbbe8dc284c49dd9be78ca25f3a8b89300e0acc24a77e6c74824d353ef50efbf163e64a69f4330b301afca42d0e2229be0560d6d616ac4e99d48b4062016b1 languageName: node linkType: hard @@ -13030,9 +13005,9 @@ __metadata: linkType: hard "path-to-regexp@npm:^6.2.1": - version: 6.2.1 - resolution: "path-to-regexp@npm:6.2.1" - checksum: 10/1e266be712d1a08086ee77beab12a1804842ec635dfed44f9ee1ba960a0e01cec8063fb8c92561115cdc0ce73158cdc7766e353ffa039340b4a85b370084c4d4 + version: 6.2.2 + resolution: "path-to-regexp@npm:6.2.2" + checksum: 10/f7d11c1a9e02576ce0294f4efdc523c11b73894947afdf7b23a0d0f7c6465d7a7772166e770ddf1495a8017cc0ee99e3e8a15ed7302b6b948b89a6dd4eea895e languageName: node linkType: hard @@ -13159,19 +13134,6 @@ __metadata: languageName: node linkType: hard -"plugin-error@npm:0.1.2": - version: 0.1.2 - resolution: "plugin-error@npm:0.1.2" - dependencies: - ansi-cyan: "npm:^0.1.1" - ansi-red: "npm:^0.1.1" - arr-diff: "npm:^1.0.1" - arr-union: "npm:^2.0.1" - extend-shallow: "npm:^1.1.2" - checksum: 10/e363d3b644753ef468fc069fd8a76a67a077ece85320e434386e0889e10bbbc507d9733f8f6d6ef1cfda272a6c7f0d03cd70340a0a1f8014fe41a4d0d1ce59d0 - languageName: node - linkType: hard - "plugin-error@npm:^1.0.1": version: 1.0.1 resolution: "plugin-error@npm:1.0.1" @@ -13233,13 +13195,13 @@ __metadata: linkType: hard "postcss@npm:^8.4.14": - version: 8.4.36 - resolution: "postcss@npm:8.4.36" + version: 8.4.38 + resolution: "postcss@npm:8.4.38" dependencies: nanoid: "npm:^3.3.7" picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.1.0" - checksum: 10/8b8bb8e6b67ed8bd3c6773b9b7e9f5fabcf3c6bce35f08dcbea099ce971e81ed5e0639dd08edcdd7078aa78523cdd195f985dde2e070013897f8a7aa4e95adf3 + source-map-js: "npm:^1.2.0" + checksum: 10/6e44a7ed835ffa9a2b096e8d3e5dfc6bcf331a25c48aeb862dd54e3aaecadf814fa22be224fd308f87d08adf2299164f88c5fd5ab1c4ef6cbd693ceb295377f4 languageName: node linkType: hard @@ -13412,11 +13374,11 @@ __metadata: linkType: hard "qs@npm:^6.11.2": - version: 6.12.0 - resolution: "qs@npm:6.12.0" + version: 6.12.1 + resolution: "qs@npm:6.12.1" dependencies: side-channel: "npm:^1.0.6" - checksum: 10/6156d3f0d74278b7e93a3a6b56e6b87b513ebd45ae65c7330c96d70270d0844fb0af9454a194124cd56b9ebf47b456dd01e28b223cde93c8ab01d1cb53a0e491 + checksum: 10/035bcad2a1ab0175bac7a74c904c15913bdac252834149ccff988c93a51de02642fe7be10e43058ba4dc4094bb28ce9b59d12b9e91d40997f445cfde3ecc1c29 languageName: node linkType: hard @@ -13612,7 +13574,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.2": +"regexp.prototype.flags@npm:^1.5.2": version: 1.5.2 resolution: "regexp.prototype.flags@npm:1.5.2" dependencies: @@ -14059,7 +14021,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10/32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 @@ -14167,7 +14129,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.4": +"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.6.0": version: 7.6.0 resolution: "semver@npm:7.6.0" dependencies: @@ -14290,7 +14252,7 @@ __metadata: languageName: node linkType: hard -"set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": +"set-function-name@npm:^2.0.1, set-function-name@npm:^2.0.2": version: 2.0.2 resolution: "set-function-name@npm:2.0.2" dependencies: @@ -14495,24 +14457,24 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.1": - version: 8.0.2 - resolution: "socks-proxy-agent@npm:8.0.2" +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" dependencies: - agent-base: "npm:^7.0.2" + agent-base: "npm:^7.1.1" debug: "npm:^4.3.4" socks: "npm:^2.7.1" - checksum: 10/ea727734bd5b2567597aa0eda14149b3b9674bb44df5937bbb9815280c1586994de734d965e61f1dd45661183d7b41f115fb9e432d631287c9063864cfcc2ecc + checksum: 10/c2112c66d6322e497d68e913c3780f3683237fd394bfd480b9283486a86e36095d0020db96145d88f8ccd9cc73261b98165b461f9c1bf5dc17abfe75c18029ce languageName: node linkType: hard "socks@npm:^2.7.1": - version: 2.8.1 - resolution: "socks@npm:2.8.1" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: 10/a3cc38e0716ab53a2db3fa00c703ca682ad54dbbc9ed4c7461624a999be6fa7cdc79fc904c411618e698d5eff55a55aa6d9329169a7db11636d0200814a2b5aa + checksum: 10/ffcb622c22481dfcd7589aae71fbfd71ca34334064d181df64bf8b7feaeee19706aba4cffd1de35cc7bbaeeaa0af96be2d7f40fcbc7bc0ab69533a7ae9ffc4fb languageName: node linkType: hard @@ -14537,10 +14499,10 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.1.0": - version: 1.1.0 - resolution: "source-map-js@npm:1.1.0" - checksum: 10/6319690f50f8da9445433d7edfb8cc4ffd42b9deb69739c73bb65992c61dfdf6f5979f49d4a25e85e51ebf235fde65e061291e8ee2a68da2b87a38c62cb4aef4 +"source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 10/74f331cfd2d121c50790c8dd6d3c9de6be21926de80583b23b37029b0f37aefc3e019fa91f9a10a5e120c08135297e1ecf312d561459c45908cb1e0e365f49e5 languageName: node linkType: hard @@ -14882,19 +14844,22 @@ __metadata: linkType: hard "string.prototype.matchall@npm:^4.0.6": - version: 4.0.10 - resolution: "string.prototype.matchall@npm:4.0.10" + version: 4.0.11 + resolution: "string.prototype.matchall@npm:4.0.11" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" + gopd: "npm:^1.0.1" has-symbols: "npm:^1.0.3" - internal-slot: "npm:^1.0.5" - regexp.prototype.flags: "npm:^1.5.0" - set-function-name: "npm:^2.0.0" - side-channel: "npm:^1.0.4" - checksum: 10/0f7a1a7f91790cd45f804039a16bc6389c8f4f25903e648caa3eea080b019a5c7b0cac2ca83976646140c2332b159042140bf389f23675609d869dd52450cddc + internal-slot: "npm:^1.0.7" + regexp.prototype.flags: "npm:^1.5.2" + set-function-name: "npm:^2.0.2" + side-channel: "npm:^1.0.6" + checksum: 10/a902ff4500f909f2a08e55cc5ab1ffbbc905f603b36837674370ee3921058edd0392147e15891910db62a2f31ace2adaf065eaa3bc6e9810bdbc8ca48e05a7b5 languageName: node linkType: hard @@ -14921,14 +14886,14 @@ __metadata: languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - checksum: 10/6e594d3a61b127d243b8be1312e9f78683abe452cfe0bcafa3e0dc62ad6f030ccfb64d87ed3086fb7cb540fda62442c164d237cc5cc4d53c6e3eb659c29a0aeb + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/160167dfbd68e6f7cb9f51a16074eebfce1571656fc31d40c3738ca9e30e35496f2c046fe57b6ad49f65f238a152be8c86fd9a2dd58682b5eba39dad995b3674 languageName: node linkType: hard @@ -15138,7 +15103,21 @@ __metadata: languageName: node linkType: hard -"tar@npm:6.2.1, tar@npm:^6.1.11, tar@npm:^6.1.2": +"tar@npm:7.0.1": + version: 7.0.1 + resolution: "tar@npm:7.0.1" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^5.0.0" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" + yallist: "npm:^5.0.0" + checksum: 10/6fd89ef8051d12975f66a2f3932a80479bdc6c9f3bcdf04b8b57784e942ed860708ccecf79bcbb30659b14ab52eef2095d2c3af377545ff9df30de28036671dc + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.1.2": version: 6.2.1 resolution: "tar@npm:6.2.1" dependencies: @@ -15216,8 +15195,8 @@ __metadata: linkType: hard "terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.26.0": - version: 5.29.2 - resolution: "terser@npm:5.29.2" + version: 5.30.3 + resolution: "terser@npm:5.30.3" dependencies: "@jridgewell/source-map": "npm:^0.3.3" acorn: "npm:^8.8.2" @@ -15225,7 +15204,7 @@ __metadata: source-map-support: "npm:~0.5.20" bin: terser: bin/terser - checksum: 10/062df6a8f99ea2635d1b3ce41cfd4180dea6e1c83db9b2cf4b525170b2446d10e069d2877d8dcb59fbf6045870efa17b56462b67045ef2d2b420870f9d144690 + checksum: 10/f4ee378065a327c85472f351ac232fa47ec84d4f15df7ec58c044b41e3c063cf11aaedd90dcfe9c7f2a6ef01d4aab23deb61622301170dc77d0a8b6a6a83cf5e languageName: node linkType: hard @@ -15246,16 +15225,6 @@ __metadata: languageName: node linkType: hard -"through2@npm:2.0.3": - version: 2.0.3 - resolution: "through2@npm:2.0.3" - dependencies: - readable-stream: "npm:^2.1.5" - xtend: "npm:~4.0.1" - checksum: 10/d0783560d7b346a1ac595000409a6a3161ad42a3e84309c070da4ee8ecf0a40a7c9c976a5c9a5262cdeae88ead3641dc8ffc14d4a8f64e1c0f06939632c8b96a - languageName: node - linkType: hard - "through2@npm:^2.0.0, through2@npm:^2.0.3, through2@npm:~2.0.0": version: 2.0.5 resolution: "through2@npm:2.0.5" @@ -15418,21 +15387,24 @@ __metadata: languageName: node linkType: hard -"transform-async-modules-webpack-plugin@npm:1.0.4": - version: 1.0.4 - resolution: "transform-async-modules-webpack-plugin@npm:1.0.4" +"transform-async-modules-webpack-plugin@npm:1.1.0": + version: 1.1.0 + resolution: "transform-async-modules-webpack-plugin@npm:1.1.0" dependencies: "@babel/core": "npm:^7.13.0" + "@babel/plugin-transform-runtime": "npm:^7.13.0" "@babel/preset-env": "npm:^7.13.0" peerDependencies: "@babel/core": ^7.13.0 + "@babel/plugin-transform-runtime": ^7.13.0 "@babel/preset-env": ^7.13.0 + "@babel/runtime": ^7.13.0 webpack: ^5.0.0 - checksum: 10/dfb4c1a693897b0b35bf435130fd48fac8175fe60d681ef884bbdc0f1cd15017747f18b3d966bdcd96781ed85b284facbf007c6f358a6b495d46aa4358081909 + checksum: 10/35e729c8ed44bf7cf5b6ae6e4ea5eb82eef44038ec13fba0a53eec551095be5553e3c99c6c7dec37d6b1fd3c9e04f35e94a246f735c81fb2d247dfad21678322 languageName: node linkType: hard -"ts-api-utils@npm:^1.0.1": +"ts-api-utils@npm:^1.3.0": version: 1.3.0 resolution: "ts-api-utils@npm:1.3.0" peerDependencies: @@ -15617,13 +15589,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^3.0.0": - version: 3.13.1 - resolution: "type-fest@npm:3.13.1" - checksum: 10/9a8a2359ada34c9b3affcaf3a8f73ee14c52779e89950db337ce66fb74c3399776c697c99f2532e9b16e10e61cfdba3b1c19daffb93b338b742f0acd0117ce12 - languageName: node - linkType: hard - "type-is@npm:^1.6.16, type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -15679,9 +15644,9 @@ __metadata: languageName: node linkType: hard -"typed-array-length@npm:^1.0.5": - version: 1.0.5 - resolution: "typed-array-length@npm:1.0.5" +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" dependencies: call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" @@ -15689,7 +15654,7 @@ __metadata: has-proto: "npm:^1.0.3" is-typed-array: "npm:^1.1.13" possible-typed-array-names: "npm:^1.0.0" - checksum: 10/f9a0da99c41880b44e2c5e5d0d01515c2a6e0f54b10c594151804f013272d837df3b67ea84d7304ecfbab2c10d99c3372168bf3a4bd295abf13ac5a72f93054a + checksum: 10/05e96cf4ff836743ebfc593d86133b8c30e83172cb5d16c56814d7bacfed57ce97e87ada9c4b2156d9aaa59f75cdef01c25bd9081c7826e0b869afbefc3e8c39 languageName: node linkType: hard @@ -15700,13 +15665,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:5.4.3": - version: 5.4.3 - resolution: "typescript@npm:5.4.3" +"typescript@npm:5.4.5": + version: 5.4.5 + resolution: "typescript@npm:5.4.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10/de4c69f49a7ad4b1ea66a6dcc8b055ac34eb56af059a069d8988dd811c5e649be07e042e5bf573e8d0ac3ec2f30e6c999aa651cd09f6e9cbc6113749e8b6be20 + checksum: 10/d04a9e27e6d83861f2126665aa8d84847e8ebabcea9125b9ebc30370b98cb38b5dff2508d74e2326a744938191a83a69aa9fddab41f193ffa43eabfdf3f190a5 languageName: node linkType: hard @@ -15720,13 +15685,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A5.4.3#optional!builtin": - version: 5.4.3 - resolution: "typescript@patch:typescript@npm%3A5.4.3#optional!builtin::version=5.4.3&hash=5adc0c" +"typescript@patch:typescript@npm%3A5.4.5#optional!builtin": + version: 5.4.5 + resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10/5aedd97595582b08aadb8a70e8e3ddebaf5a9c1e5ad4d6503c2fcfc15329b5cf8d01145b09913e9555683ac16c5123a96be32b6d72614098ebd42df520eed9b1 + checksum: 10/760f7d92fb383dbf7dee2443bf902f4365db2117f96f875cf809167f6103d55064de973db9f78fe8f31ec08fff52b2c969aee0d310939c0a3798ec75d0bca2e1 languageName: node linkType: hard @@ -16056,16 +16021,6 @@ __metadata: languageName: node linkType: hard -"vinyl-buffer@npm:1.0.1": - version: 1.0.1 - resolution: "vinyl-buffer@npm:1.0.1" - dependencies: - bl: "npm:^1.2.1" - through2: "npm:^2.0.3" - checksum: 10/07c7775e0157b79553ffd901d14821e50bc30bc5d65b77abad648f469f19eee896b60bad12923f3ddf2964a965461c8f59498083fc09752ac3036e212f945581 - languageName: node - linkType: hard - "vinyl-fs@npm:^3.0.0": version: 3.0.3 resolution: "vinyl-fs@npm:3.0.3" @@ -16091,16 +16046,6 @@ __metadata: languageName: node linkType: hard -"vinyl-source-stream@npm:2.0.0": - version: 2.0.0 - resolution: "vinyl-source-stream@npm:2.0.0" - dependencies: - through2: "npm:^2.0.3" - vinyl: "npm:^2.1.0" - checksum: 10/7d88f30fb98237fb0187b13ed6cc9124f1728168ede7812f8bc10f47a78273c87eb207d21fb3290f4c98572e305ad4d577c4afdbff503a439e9fff7048b4fa45 - languageName: node - linkType: hard - "vinyl-sourcemap@npm:^1.1.0": version: 1.1.0 resolution: "vinyl-sourcemap@npm:1.1.0" @@ -16326,8 +16271,8 @@ __metadata: linkType: hard "webpack-dev-middleware@npm:^7.1.0": - version: 7.1.1 - resolution: "webpack-dev-middleware@npm:7.1.1" + version: 7.2.1 + resolution: "webpack-dev-middleware@npm:7.2.1" dependencies: colorette: "npm:^2.0.10" memfs: "npm:^4.6.0" @@ -16340,7 +16285,7 @@ __metadata: peerDependenciesMeta: webpack: optional: true - checksum: 10/c6076d4c89431ab50c16170bc34be5aaf35a7e28e9f97a621a2ed62c453e89bfacbbebfcc135c669c73a7044b386875f5c0c8e9121159e74d8745cb3c3664e20 + checksum: 10/e1fa9b40cba7b954f901b085cdded62df6f3c10d1d4e24d4850bd35ebe3dcfb18e7159e6579d6ac854e8e3611e5895aaf45ea1f3e29da2287659d36f0cb614d1 languageName: node linkType: hard @@ -17011,6 +16956,13 @@ __metadata: languageName: node linkType: hard +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10/1884d272d485845ad04759a255c71775db0fac56308764b4c77ea56a20d56679fad340213054c8c9c9c26fcfd4c4b2a90df993b7e0aaf3cdb73c618d1d1a802a + languageName: node + linkType: hard + "yaml@npm:2.3.4": version: 2.3.4 resolution: "yaml@npm:2.3.4" @@ -17142,9 +17094,9 @@ __metadata: linkType: hard "ylru@npm:^1.2.0": - version: 1.3.2 - resolution: "ylru@npm:1.3.2" - checksum: 10/56ea73b6fd01170de8bf7f28347a832bfb87b0bf02deb8e43b1bbe11bdc14532b0fba2364d550ed20fd0ec2ec73a3e14b1b9324636718336accd325135643ae8 + version: 1.4.0 + resolution: "ylru@npm:1.4.0" + checksum: 10/5437f8eb2fb5dd515845c657dde3cecaa9f6bd4c6386d2a5212d3fafe02189c7d8ebfdfc84940a7811607cb3524eb362ce95d3180d355cd5deb610aa8c82c9bc languageName: node linkType: hard