From 93445ced7487c6a6d6fd8ede46019045986a2f47 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:30:05 -0400 Subject: [PATCH 01/14] Update dependency eslint-plugin-lit-a11y to v4.1.3 (#21227) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 28 +++++++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 2f1c2b10a773..1937552669a6 100644 --- a/package.json +++ b/package.json @@ -200,7 +200,7 @@ "eslint-import-resolver-webpack": "0.13.8", "eslint-plugin-import": "2.29.1", "eslint-plugin-lit": "1.14.0", - "eslint-plugin-lit-a11y": "4.1.2", + "eslint-plugin-lit-a11y": "4.1.3", "eslint-plugin-unused-imports": "4.0.0", "eslint-plugin-wc": "2.1.0", "fancy-log": "2.0.0", diff --git a/yarn.lock b/yarn.lock index f26b8a6153bc..405534461284 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3974,6 +3974,15 @@ __metadata: languageName: node linkType: hard +"@thepassle/axobject-query@npm:^4.0.0": + version: 4.0.0 + resolution: "@thepassle/axobject-query@npm:4.0.0" + dependencies: + dequal: "npm:^2.0.3" + checksum: 10/919cb6ed90259cd0398b7e485dfbacae42423ff4202d5753c6545d3dfa9dc3d63e7f34941d6b94608c2730ec1539d30805411d9501c86951966e0d4aa0c4ae44 + languageName: node + linkType: hard + "@thomasloven/round-slider@npm:0.6.0": version: 0.6.0 resolution: "@thomasloven/round-slider@npm:0.6.0" @@ -5825,13 +5834,6 @@ __metadata: languageName: node linkType: hard -"axobject-query@npm:^2.2.0": - version: 2.2.0 - resolution: "axobject-query@npm:2.2.0" - checksum: 10/25de4b5ba6b28f5856fab60d86ea20fea941586bc38f33c81b78d66cd7e9c5792a9b9a9e60a38407aa634e01fee6a34133fbbd1d1d3d24cc686de83c6bb1e634 - languageName: node - linkType: hard - "b4a@npm:^1.6.4": version: 1.6.6 resolution: "b4a@npm:1.6.6" @@ -7579,13 +7581,13 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-lit-a11y@npm:4.1.2": - version: 4.1.2 - resolution: "eslint-plugin-lit-a11y@npm:4.1.2" +"eslint-plugin-lit-a11y@npm:4.1.3": + version: 4.1.3 + resolution: "eslint-plugin-lit-a11y@npm:4.1.3" dependencies: + "@thepassle/axobject-query": "npm:^4.0.0" aria-query: "npm:^5.1.3" axe-core: "npm:^4.3.3" - axobject-query: "npm:^2.2.0" dom5: "npm:^3.0.1" emoji-regex: "npm:^10.2.1" eslint-plugin-lit: "npm:^1.10.1" @@ -7596,7 +7598,7 @@ __metadata: requireindex: "npm:~1.2.0" peerDependencies: eslint: ">= 5" - checksum: 10/2d70f0b9fa6afc7f259877acd7e69c14f0104a69a019efb594d5de603e12b982e4a96fec5b169005fab244655951f85bff77f469d9aeadb885974f963a7d9996 + checksum: 10/730a82cfefbeba87e604172db8c29fc18d3361b5c913531c05e83af26edbe612df955d5f124daf6066c3703b0e25f2352a8ea9cae8b2f8a3e6121937c297d3a9 languageName: node linkType: hard @@ -9018,7 +9020,7 @@ __metadata: eslint-import-resolver-webpack: "npm:0.13.8" eslint-plugin-import: "npm:2.29.1" eslint-plugin-lit: "npm:1.14.0" - eslint-plugin-lit-a11y: "npm:4.1.2" + eslint-plugin-lit-a11y: "npm:4.1.3" eslint-plugin-unused-imports: "npm:4.0.0" eslint-plugin-wc: "npm:2.1.0" fancy-log: "npm:2.0.0" From bda61da6660495ba8ad65240baa022911bd74de5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 30 Jun 2024 09:34:43 +0200 Subject: [PATCH 02/14] Update dependency @material/web to v1.5.1 (#21224) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 1937552669a6..292983f4ad45 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,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.5.0", + "@material/web": "1.5.1", "@mdi/js": "7.4.47", "@mdi/svg": "7.4.47", "@polymer/paper-item": "3.0.1", diff --git a/yarn.lock b/yarn.lock index 405534461284..255077cb166b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3235,13 +3235,13 @@ __metadata: languageName: node linkType: hard -"@material/web@npm:1.5.0": - version: 1.5.0 - resolution: "@material/web@npm:1.5.0" +"@material/web@npm:1.5.1": + version: 1.5.1 + resolution: "@material/web@npm:1.5.1" dependencies: lit: "npm:^2.7.4 || ^3.0.0" tslib: "npm:^2.4.0" - checksum: 10/6bf651e8eaf33332b7f83aa04d473f6844a1f8280d5a2025a30583fbe03aa718de348260c5b9466d587f166772759aba0d100137e3e13d4d7c6fba6ffb79efa4 + checksum: 10/9be6019068fbc4ed6873837ad549fd672c24beaacd9123bc9f3d72b7dfd67a1acdafab43bd484b50d40300e27e3742314915f4d6e6723b38be223b4547ae206f languageName: node linkType: hard @@ -8951,7 +8951,7 @@ __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.5.0" + "@material/web": "npm:1.5.1" "@mdi/js": "npm:7.4.47" "@mdi/svg": "npm:7.4.47" "@octokit/auth-oauth-device": "npm:7.1.1" From f41fab69680f4bbe20aaadf7042ea7159fa0c197 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 1 Jul 2024 11:12:15 +0200 Subject: [PATCH 03/14] Improve take control of automation/script wording (#21241) --- src/translations/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/translations/en.json b/src/translations/en.json index 4ee62dc063c6..75271fe1a472 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2773,7 +2773,7 @@ "take_control": "Take control", "take_control_confirmation": { "title": "Take control of automation?", - "text": "This automation is using a blueprint. By taking control, your automation will be converted into a regular automation using triggers, conditions and actions. You will be able to edit it directly and you won't be able to convert it back to a blueprint.", + "text": "This automation is based on a blueprint. You are about to take control, which will separate it from the blueprint and give you the ability to fully edit the automation. Would you like to proceed?", "action": "Take control" }, "run": "[%key:ui::panel::config::automation::editor::actions::run%]", @@ -3650,7 +3650,7 @@ "take_control": "[%key:ui::panel::config::automation::editor::take_control%]", "take_control_confirmation": { "title": "Take control of script?", - "text": "This script is using a blueprint. By taking control, your script will be converted into a regular automation using actions. You will be able to edit it directly and you won't be able to convert it back to a blueprint.", + "text": "This script is based on a blueprint. You are about to take control, which will separate it from the blueprint and give you the ability to fully edit the script. Would you like to proceed?", "action": "[%key:ui::panel::config::automation::editor::take_control_confirmation::action%]" }, "read_only": "This script cannot be edited from the UI, because it is not stored in the ''scripts.yaml'' file.", From c71a051b6dedb2ff273a58a45331b713d9933090 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 1 Jul 2024 12:11:26 +0200 Subject: [PATCH 04/14] Remove ga.js (#21242) --- cast/src/html/faq.html.template | 12 ------------ cast/src/html/media.html.template | 6 ------ cast/src/html/receiver.html.template | 6 ------ demo/src/html/index.html.template | 11 ----------- 4 files changed, 35 deletions(-) diff --git a/cast/src/html/faq.html.template b/cast/src/html/faq.html.template index c67a5b477a95..80fc487bef21 100644 --- a/cast/src/html/faq.html.template +++ b/cast/src/html/faq.html.template @@ -232,17 +232,5 @@ http:

- - diff --git a/cast/src/html/media.html.template b/cast/src/html/media.html.template index e91fbb881cbe..49633e084021 100644 --- a/cast/src/html/media.html.template +++ b/cast/src/html/media.html.template @@ -14,12 +14,6 @@ --background-color: #41bdf5; } - <%= renderTemplate("../../../src/html/_js_base.html.template") %> diff --git a/cast/src/html/receiver.html.template b/cast/src/html/receiver.html.template index 582e9ca865d4..d326ce55ff13 100644 --- a/cast/src/html/receiver.html.template +++ b/cast/src/html/receiver.html.template @@ -11,10 +11,4 @@ font-size: initial; } - diff --git a/demo/src/html/index.html.template b/demo/src/html/index.html.template index c2be4e7cc39c..6b044e44a355 100644 --- a/demo/src/html/index.html.template +++ b/demo/src/html/index.html.template @@ -93,16 +93,5 @@ } <%= renderTemplate("../../../src/html/_script_load_es5.html.template") %> - From e97be57e3b8ca22daf096294b0c2d46d97bfe6bb Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Mon, 1 Jul 2024 13:11:52 +0200 Subject: [PATCH 05/14] Application credentials: small improvements (#21233) * small improvements * Update ha-config-application-credentials.ts * Update ha-config-application-credentials.ts --------- Co-authored-by: Bram Kragten --- .../ha-config-application-credentials.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/panels/config/application_credentials/ha-config-application-credentials.ts b/src/panels/config/application_credentials/ha-config-application-credentials.ts index e11f0515f431..d31c8b274d18 100644 --- a/src/panels/config/application_credentials/ha-config-application-credentials.ts +++ b/src/panels/config/application_credentials/ha-config-application-credentials.ts @@ -77,12 +77,13 @@ export class HaConfigApplicationCredentials extends LitElement { private _filter = ""; private _columns = memoizeOne( - (narrow: boolean, localize: LocalizeFunc): DataTableColumnContainer => { + (localize: LocalizeFunc): DataTableColumnContainer => { const columns: DataTableColumnContainer = { name: { title: localize( "ui.panel.config.application_credentials.picker.headers.name" ), + main: true, sortable: true, filterable: true, direction: "asc", @@ -94,7 +95,6 @@ export class HaConfigApplicationCredentials extends LitElement { ), filterable: true, width: "30%", - hidden: narrow, }, localizedDomain: { title: localize( @@ -109,6 +109,9 @@ export class HaConfigApplicationCredentials extends LitElement { title: "", width: "64px", type: "overflow-menu", + showNarrow: true, + hideable: false, + moveable: false, template: (credential) => html` Date: Mon, 1 Jul 2024 10:31:22 -0400 Subject: [PATCH 06/14] Fix Webpack bundling of recorder worklet (#21239) * Fix Webpack bundling of recorder worklet --- build-scripts/webpack.cjs | 17 ++++++++++++----- src/util/audio-recorder.ts | 17 +++++++++-------- ...{recorder.worklet.js => recorder-worklet.js} | 2 +- 3 files changed, 22 insertions(+), 14 deletions(-) rename src/util/{recorder.worklet.js => recorder-worklet.js} (89%) diff --git a/build-scripts/webpack.cjs b/build-scripts/webpack.cjs index 0679e3e2baec..5ba0f35d2383 100644 --- a/build-scripts/webpack.cjs +++ b/build-scripts/webpack.cjs @@ -74,6 +74,9 @@ const createWebpackConfig = ({ resolve: { fullySpecified: false, }, + parser: { + worker: ["*context.audioWorklet.addModule()", "..."], + }, }, { test: /\.css$/, @@ -92,11 +95,15 @@ const createWebpackConfig = ({ moduleIds: isProdBuild && !isStatsBuild ? "deterministic" : "named", chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named", splitChunks: { - // Disable splitting for web workers with ESM output - // Imports of external chunks are broken - chunks: latestBuild - ? (chunk) => !chunk.canBeInitial() && !/^.+-worker$/.test(chunk.name) - : undefined, + // Disable splitting for web workers and worklets because imports of + // external chunks are broken for: + // - ESM output: https://github.com/webpack/webpack/issues/17014 + // - Worklets use `importScripts`: https://github.com/webpack/webpack/issues/11543 + chunks: (chunk) => + !chunk.canBeInitial() && + !new RegExp(`^.+-work${latestBuild ? "(?:let|er)" : "let"}$`).test( + chunk.name + ), }, }, plugins: [ diff --git a/src/util/audio-recorder.ts b/src/util/audio-recorder.ts index b26f0f49229c..30bf78793709 100644 --- a/src/util/audio-recorder.ts +++ b/src/util/audio-recorder.ts @@ -70,17 +70,18 @@ export class AudioRecorder { } private async _createContext() { - // @ts-ignore-next-line - this._context = new (window.AudioContext || window.webkitAudioContext)(); + // @ts-expect-error webkitAudioContext is not recognized + const context = new (AudioContext || webkitAudioContext)(); this._stream = await navigator.mediaDevices.getUserMedia({ audio: true }); - - await this._context.audioWorklet.addModule( - new URL("./recorder.worklet.js", import.meta.url) + // Syntax here must match an item of `parser.worker` in Webpack config in + // order for module to be parsed and a chunk to be properly created. + await context.audioWorklet.addModule( + /* webpackChunkName: "recorder-worklet" */ + new URL("./recorder-worklet.js", import.meta.url) ); - + this._context = context; this._source = this._context.createMediaStreamSource(this._stream); - this._recorder = new AudioWorkletNode(this._context, "recorder.worklet"); - + this._recorder = new AudioWorkletNode(this._context, "recorder-worklet"); this._recorder.port.onmessage = (e) => { if (!this._active) { return; diff --git a/src/util/recorder.worklet.js b/src/util/recorder-worklet.js similarity index 89% rename from src/util/recorder.worklet.js rename to src/util/recorder-worklet.js index b8fef662e727..0d54b3a607c9 100644 --- a/src/util/recorder.worklet.js +++ b/src/util/recorder-worklet.js @@ -18,4 +18,4 @@ class RecorderProcessor extends AudioWorkletProcessor { } } -registerProcessor("recorder.worklet", RecorderProcessor); +registerProcessor("recorder-worklet", RecorderProcessor); From 76abfea6edc41fb4ed22f543b177db099914d5c8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 2 Jul 2024 14:59:52 +0200 Subject: [PATCH 07/14] Hide demo card when showing demo from frontpage (#21243) * Hide demo card when showing demo from frontpage * Store in constant on load * reverse * Remove filter * move constnat * Make Home Assistant title --- demo/src/configs/sections/lovelace.ts | 15 ++++++++++----- demo/src/entrypoint.ts | 1 + demo/src/util/is_frontpage.ts | 1 + 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 demo/src/util/is_frontpage.ts diff --git a/demo/src/configs/sections/lovelace.ts b/demo/src/configs/sections/lovelace.ts index 70146c0bdb39..ccea806c61ee 100644 --- a/demo/src/configs/sections/lovelace.ts +++ b/demo/src/configs/sections/lovelace.ts @@ -1,3 +1,4 @@ +import { isFrontpageEmbed } from "../../util/is_frontpage"; import { DemoConfig } from "../types"; export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({ @@ -5,14 +6,18 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({ views: [ { type: "sections", - title: "Demo", + title: isFrontpageEmbed ? "Home Assistant" : "Demo", path: "home", icon: "mdi:home-assistant", sections: [ - { - title: "Welcome 👋", - cards: [{ type: "custom:ha-demo-card" }], - }, + ...(isFrontpageEmbed + ? [] + : [ + { + title: "Welcome 👋", + cards: [{ type: "custom:ha-demo-card" }], + }, + ]), { cards: [ { diff --git a/demo/src/entrypoint.ts b/demo/src/entrypoint.ts index ca58e546e357..e02049326436 100644 --- a/demo/src/entrypoint.ts +++ b/demo/src/entrypoint.ts @@ -1,4 +1,5 @@ import "../../src/resources/safari-14-attachshadow-patch"; +import "./util/is_frontpage"; import "./ha-demo"; import("../../src/resources/ha-style"); diff --git a/demo/src/util/is_frontpage.ts b/demo/src/util/is_frontpage.ts new file mode 100644 index 000000000000..4de52935ba6a --- /dev/null +++ b/demo/src/util/is_frontpage.ts @@ -0,0 +1 @@ +export const isFrontpageEmbed = document.location.search === "?frontpage"; From 5707ca0016e832d99dd0b9a1a2242eb3abd7da6f Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Tue, 2 Jul 2024 09:13:04 -0400 Subject: [PATCH 08/14] Fix English only translations build (#21245) --- build-scripts/gulp/translations.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build-scripts/gulp/translations.js b/build-scripts/gulp/translations.js index dde4dd89f4c8..1127a5d3f5eb 100755 --- a/build-scripts/gulp/translations.js +++ b/build-scripts/gulp/translations.js @@ -244,11 +244,11 @@ const createTranslations = async () => { // 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 + const masterStream = gulp .src(`${workDir}/en.json`) - .pipe(new PassThrough({ objectMode: true })) - .pipe(hashStream, { end: false }); - const mergesFinished = []; + .pipe(new PassThrough({ objectMode: true })); + masterStream.pipe(hashStream, { end: false }); + const mergesFinished = [finished(masterStream)]; for (const translationFile of translationFiles) { const locale = basename(translationFile, ".json"); const subtags = locale.split("-"); From 7258e31348d6fa8fc98271990d99e1c252210062 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 2 Jul 2024 17:11:16 +0200 Subject: [PATCH 09/14] Tweak first section in section demo (#21249) * Tweak first section in section demo * Allow automation entities be toggled --- demo/src/configs/sections/lovelace.ts | 25 +++++-------------------- src/fake_data/entity.ts | 1 + 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/demo/src/configs/sections/lovelace.ts b/demo/src/configs/sections/lovelace.ts index ccea806c61ee..36b4abb2fe9c 100644 --- a/demo/src/configs/sections/lovelace.ts +++ b/demo/src/configs/sections/lovelace.ts @@ -20,26 +20,6 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({ ]), { cards: [ - { - type: "tile", - entity: "cover.living_room_garden_shutter", - name: "Garden", - }, - { - type: "tile", - entity: "cover.living_room_graveyard_shutter", - name: "Rear", - }, - { - type: "tile", - entity: "cover.living_room_left_shutter", - name: "Left", - }, - { - type: "tile", - entity: "cover.living_room_right_shutter", - name: "Right", - }, { type: "tile", entity: "light.floor_lamp", @@ -65,6 +45,11 @@ export const demoLovelaceSections: DemoConfig["lovelace"] = () => ({ detail: 1, name: "Temperature", }, + { + type: "tile", + entity: "cover.living_room_garden_shutter", + name: "Blinds", + }, { type: "tile", entity: "media_player.living_room_nest_mini", diff --git a/src/fake_data/entity.ts b/src/fake_data/entity.ts index b001b4b7fcd0..2ea81b3feacf 100644 --- a/src/fake_data/entity.ts +++ b/src/fake_data/entity.ts @@ -394,6 +394,7 @@ class GroupEntity extends Entity { } const TYPES = { + automation: ToggleEntity, alarm_control_panel: AlarmControlPanelEntity, climate: ClimateEntity, cover: CoverEntity, From 7d432cd11ab6504595667e6bf53b754addc09417 Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Tue, 2 Jul 2024 18:44:36 +0200 Subject: [PATCH 10/14] Fix logbook card display/reloading issues (#21253) remove await logic --- src/panels/logbook/ha-logbook.ts | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/panels/logbook/ha-logbook.ts b/src/panels/logbook/ha-logbook.ts index ea25e307b3d4..38ef5ee2a62f 100644 --- a/src/panels/logbook/ha-logbook.ts +++ b/src/panels/logbook/ha-logbook.ts @@ -139,7 +139,7 @@ export class HaLogbook extends LitElement { this._throttleGetLogbookEntries.cancel(); this._updateTraceContexts.cancel(); this._updateUsers.cancel(); - await this._unsubscribeSetLoading(); + this._unsubscribeSetLoading(); if (force) { this._getLogBookData(); @@ -206,18 +206,9 @@ export class HaLogbook extends LitElement { ); } - private async _unsubscribe(): Promise { + private _unsubscribe() { if (this._subscribed) { - const unsub = await this._subscribed; - if (unsub) { - try { - await unsub(); - } catch (e) { - // The backend will cancel the subscription if - // we subscribe to entities that will all be - // filtered away - } - } + this._subscribed.then((unsub) => unsub?.()); this._subscribed = undefined; } } @@ -239,8 +230,8 @@ export class HaLogbook extends LitElement { * Setting this._logbookEntries to undefined * will put the page in a loading state. */ - private async _unsubscribeSetLoading() { - await this._unsubscribe(); + private _unsubscribeSetLoading() { + this._unsubscribe(); this._logbookEntries = undefined; this._pendingStreamMessages = []; } @@ -249,8 +240,8 @@ export class HaLogbook extends LitElement { * Setting this._logbookEntries to an empty * list will show a no results message. */ - private async _unsubscribeNoResults() { - await this._unsubscribe(); + private _unsubscribeNoResults() { + this._unsubscribe(); this._logbookEntries = []; this._pendingStreamMessages = []; } From 09accb3071eefb62e28bbf688d054aee9e05ec8c Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 2 Jul 2024 18:50:42 +0200 Subject: [PATCH 11/14] Ignore aspect ratio in grid section (#21248) * Ignore aspect ratio in grid section * Feedback --- src/panels/lovelace/cards/hui-area-card.ts | 23 +++++++++- src/panels/lovelace/cards/hui-card.ts | 10 ++++- src/panels/lovelace/cards/hui-iframe-card.ts | 43 ++++++++++++------- src/panels/lovelace/cards/hui-map-card.ts | 16 ++++++- .../lovelace/sections/hui-grid-section.ts | 1 + src/panels/lovelace/types.ts | 1 + 6 files changed, 72 insertions(+), 22 deletions(-) diff --git a/src/panels/lovelace/cards/hui-area-card.ts b/src/panels/lovelace/cards/hui-area-card.ts index 5bd7e44e317b..5ebf4b4eae05 100644 --- a/src/panels/lovelace/cards/hui-area-card.ts +++ b/src/panels/lovelace/cards/hui-area-card.ts @@ -55,7 +55,11 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { HomeAssistant } from "../../../types"; import "../components/hui-image"; import "../components/hui-warning"; -import { LovelaceCard, LovelaceCardEditor } from "../types"; +import { + LovelaceCard, + LovelaceCardEditor, + LovelaceLayoutOptions, +} from "../types"; import { AreaCardConfig } from "./types"; export const DEFAULT_ASPECT_RATIO = "16:9"; @@ -102,6 +106,9 @@ export class HuiAreaCard @property({ attribute: false }) public hass!: HomeAssistant; + @property({ attribute: false }) + public layout?: string; + @state() private _config?: AreaCardConfig; @state() private _entities?: EntityRegistryEntry[]; @@ -405,13 +412,17 @@ export class HuiAreaCard if (this._config.show_camera && "camera" in entitiesByDomain) { cameraEntityId = entitiesByDomain.camera[0].entity_id; } + cameraEntityId = "camera.demo_camera"; const imageClass = area.picture || cameraEntityId; + + const ignoreAspectRatio = imageClass || this.layout === "grid"; + return html` 0 && ratio.h > 0) { - padding = `${((100 * ratio.h) / ratio.w).toFixed(2)}%`; + const ignoreAspectRatio = this.isPanel || this.layout === "grid"; + if (!ignoreAspectRatio) { + if (this._config.aspect_ratio) { + const ratio = parseAspectRatio(this._config.aspect_ratio); + if (ratio && ratio.w > 0 && ratio.h > 0) { + padding = `${((100 * ratio.h) / ratio.w).toFixed(2)}%`; + } + } else { + padding = "50%"; } - } else if (!this.isPanel) { - padding = "50%"; } const target_protocol = new URL(this._config.url, location.toString()) @@ -105,24 +115,25 @@ export class HuiIframeCard extends LitElement implements LovelaceCard { `; } + public getLayoutOptions(): LovelaceLayoutOptions { + return { + grid_columns: 4, + grid_rows: 4, + }; + } + static get styles(): CSSResultGroup { return css` - :host([ispanel]) ha-card { - width: 100%; - height: 100%; - } - ha-card { overflow: hidden; + width: 100%; + height: 100%; } #root { width: 100%; - position: relative; - } - - :host([ispanel]) #root { height: 100%; + position: relative; } iframe { diff --git a/src/panels/lovelace/cards/hui-map-card.ts b/src/panels/lovelace/cards/hui-map-card.ts index 65189e351360..ef0d25be529e 100644 --- a/src/panels/lovelace/cards/hui-map-card.ts +++ b/src/panels/lovelace/cards/hui-map-card.ts @@ -39,7 +39,7 @@ import { HomeAssistant } from "../../../types"; import { findEntities } from "../common/find-entities"; import { processConfigEntities } from "../common/process-config-entities"; import { EntityConfig } from "../entity-rows/types"; -import { LovelaceCard } from "../types"; +import { LovelaceCard, LovelaceLayoutOptions } from "../types"; import { MapCardConfig } from "./types"; export const DEFAULT_HOURS_TO_SHOW = 0; @@ -57,6 +57,9 @@ class HuiMapCard extends LitElement implements LovelaceCard { @property({ type: Boolean, reflect: true }) public isPanel = false; + @property({ attribute: false }) + public layout?: string; + @state() private _stateHistory?: HistoryStates; @state() @@ -297,7 +300,9 @@ class HuiMapCard extends LitElement implements LovelaceCard { private _computePadding(): void { const root = this.shadowRoot!.getElementById("root"); - if (!this._config || this.isPanel || !root) { + + const ignoreAspectRatio = this.isPanel || this.layout === "grid"; + if (!this._config || ignoreAspectRatio || !root) { return; } @@ -423,6 +428,13 @@ class HuiMapCard extends LitElement implements LovelaceCard { } ); + public getLayoutOptions(): LovelaceLayoutOptions { + return { + grid_columns: 4, + grid_rows: 4, + }; + } + static get styles(): CSSResultGroup { return css` ha-card { diff --git a/src/panels/lovelace/sections/hui-grid-section.ts b/src/panels/lovelace/sections/hui-grid-section.ts index 11fd8aa0afd3..8b5b8d9bb16c 100644 --- a/src/panels/lovelace/sections/hui-grid-section.ts +++ b/src/panels/lovelace/sections/hui-grid-section.ts @@ -98,6 +98,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement { (cardConfig) => this._getKey(cardConfig), (_cardConfig, idx) => { const card = this.cards![idx]; + card.layout = "grid"; const layoutOptions = card.getLayoutOptions(); const columnSize = diff --git a/src/panels/lovelace/types.ts b/src/panels/lovelace/types.ts index eaf582057322..9eadc1fd017e 100644 --- a/src/panels/lovelace/types.ts +++ b/src/panels/lovelace/types.ts @@ -49,6 +49,7 @@ export interface LovelaceCard extends HTMLElement { hass?: HomeAssistant; isPanel?: boolean; preview?: boolean; + layout?: string; getCardSize(): number | Promise; getLayoutOptions?(): LovelaceLayoutOptions; setConfig(config: LovelaceCardConfig): void; From 9a2051a6797ba3c6688dddbb4e8b763ef26315b1 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jul 2024 21:18:58 +0200 Subject: [PATCH 12/14] Change take control of blueprint UX (#21254) * Change take control of blueprint UX * Add margin to ha-alert --------- Co-authored-by: Paul Bottein --- .../automation/blueprint-automation-editor.ts | 8 -- .../config/automation/ha-automation-editor.ts | 97 ++++++++++------- .../automation/manual-automation-editor.ts | 18 ---- .../blueprint/blueprint-generic-editor.ts | 21 ++-- .../config/script/blueprint-script-editor.ts | 9 -- src/panels/config/script/ha-script-editor.ts | 100 +++++++++++------- .../config/script/manual-script-editor.ts | 18 ---- src/translations/en.json | 12 +-- 8 files changed, 130 insertions(+), 153 deletions(-) diff --git a/src/panels/config/automation/blueprint-automation-editor.ts b/src/panels/config/automation/blueprint-automation-editor.ts index 959230be5f97..78b4a2375bfe 100644 --- a/src/panels/config/automation/blueprint-automation-editor.ts +++ b/src/panels/config/automation/blueprint-automation-editor.ts @@ -20,14 +20,6 @@ export class HaBlueprintAutomationEditor extends HaBlueprintGenericEditor { protected render() { return html` - ${this.disabled - ? html` - ${this.hass.localize("ui.panel.config.automation.editor.read_only")} - - ${this.hass.localize("ui.panel.config.automation.editor.migrate")} - - ` - : nothing} ${this.stateObj?.state === "off" ? html` diff --git a/src/panels/config/automation/ha-automation-editor.ts b/src/panels/config/automation/ha-automation-editor.ts index 939c00af531c..cd7ab59477a7 100644 --- a/src/panels/config/automation/ha-automation-editor.ts +++ b/src/panels/config/automation/ha-automation-editor.ts @@ -81,9 +81,9 @@ declare global { unsub?: UnsubscribeFunc; }; "ui-mode-not-available": Error; - duplicate: undefined; "move-down": undefined; "move-up": undefined; + duplicate: undefined; } } @@ -116,6 +116,8 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { @state() private _validationErrors?: (string | TemplateResult)[]; + @state() private _blueprintConfig?: BlueprintAutomationConfig; + private _configSubscriptions: Record< string, (config?: AutomationConfig) => void @@ -200,7 +202,9 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { ${this.hass.localize("ui.panel.config.automation.editor.rename")} @@ -224,7 +228,8 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { : nothing} @@ -244,7 +249,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { ${this.hass.localize( "ui.panel.config.automation.editor.take_control" @@ -337,6 +342,32 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { : nothing} ` : ""} + ${this._blueprintConfig + ? html` + ${this.hass.localize( + "ui.panel.config.automation.editor.confirm_take_control" + )} +
+ ${this.hass.localize("ui.common.yes")} + ${this.hass.localize("ui.common.no")} +
+
` + : this._readOnly + ? html`${this.hass.localize( + "ui.panel.config.automation.editor.read_only" + )} + + ${this.hass.localize( + "ui.panel.config.automation.editor.migrate" + )} + + ` + : nothing} ${this._mode === "gui" ? html`
` : html` @@ -366,25 +396,12 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { .config=${this._config} .disabled=${Boolean(this._readOnly)} @value-changed=${this._valueChanged} - @duplicate=${this._duplicate} > `}
` : this._mode === "yaml" - ? html` ${this._readOnly - ? html` - ${this.hass.localize( - "ui.panel.config.automation.editor.read_only" - )} - - ${this.hass.localize( - "ui.panel.config.automation.editor.migrate" - )} - - ` - : nothing} - ${stateObj?.state === "off" + ? html`${stateObj?.state === "off" ? html` ${this.hass.localize( @@ -409,7 +426,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { ha-alert { margin: 0 auto; max-width: 1040px; padding: 28px 20px 0; + display: block; } ha-yaml-editor { flex-grow: 1; diff --git a/src/panels/config/automation/manual-automation-editor.ts b/src/panels/config/automation/manual-automation-editor.ts index ceb4da52e033..3e7a23c2f948 100644 --- a/src/panels/config/automation/manual-automation-editor.ts +++ b/src/panels/config/automation/manual-automation-editor.ts @@ -38,14 +38,6 @@ export class HaManualAutomationEditor extends LitElement { protected render() { return html` - ${this.disabled - ? html` - ${this.hass.localize("ui.panel.config.automation.editor.read_only")} - - ${this.hass.localize("ui.panel.config.automation.editor.migrate")} - - ` - : nothing} ${this.stateObj?.state === "off" ? html` @@ -238,10 +230,6 @@ export class HaManualAutomationEditor extends LitElement { }); } - private _duplicate() { - fireEvent(this, "duplicate"); - } - static get styles(): CSSResultGroup { return [ haStyle, @@ -280,12 +268,6 @@ export class HaManualAutomationEditor extends LitElement { font-weight: normal; line-height: 0; } - ha-alert.re-order { - display: block; - margin-bottom: 16px; - border-radius: var(--ha-card-border-radius, 12px); - overflow: hidden; - } `, ]; } diff --git a/src/panels/config/blueprint/blueprint-generic-editor.ts b/src/panels/config/blueprint/blueprint-generic-editor.ts index bae63f6dc7e3..85d7083a8a8e 100644 --- a/src/panels/config/blueprint/blueprint-generic-editor.ts +++ b/src/panels/config/blueprint/blueprint-generic-editor.ts @@ -3,7 +3,6 @@ import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../../../common/dom/fire_event"; import { nestedArrayMove } from "../../../common/util/array-move"; -import "../../../components/ha-alert"; import "../../../components/ha-blueprint-picker"; import "../../../components/ha-card"; import "../../../components/ha-circular-progress"; @@ -126,14 +125,14 @@ export abstract class HaBlueprintGenericEditor extends LitElement { ); const expanded = !section.collapsed || anyRequired; - return html`
${section?.icon - ? html` ` @@ -261,10 +260,6 @@ export abstract class HaBlueprintGenericEditor extends LitElement { }); } - protected _duplicate() { - fireEvent(this, "duplicate"); - } - static get styles(): CSSResultGroup { return [ haStyle, @@ -318,14 +313,6 @@ export abstract class HaBlueprintGenericEditor extends LitElement { margin-left: 8px; margin-right: 8px; } - ha-alert { - margin-bottom: 16px; - display: block; - } - ha-alert.re-order { - border-radius: var(--ha-card-border-radius, 12px); - overflow: hidden; - } div.section-header { display: flex; vertical-align: middle; @@ -333,6 +320,10 @@ export abstract class HaBlueprintGenericEditor extends LitElement { ha-icon.section-header { padding-right: 10px; } + ha-alert { + display: block; + margin-bottom: 16px; + } `, ]; } diff --git a/src/panels/config/script/blueprint-script-editor.ts b/src/panels/config/script/blueprint-script-editor.ts index bc7b624a0cb3..dbe96677de50 100644 --- a/src/panels/config/script/blueprint-script-editor.ts +++ b/src/panels/config/script/blueprint-script-editor.ts @@ -1,7 +1,6 @@ import "@material/mwc-button/mwc-button"; import { html, nothing } from "lit"; import { customElement, property } from "lit/decorators"; -import "../../../components/ha-alert"; import "../../../components/ha-markdown"; import { fetchBlueprints } from "../../../data/blueprint"; import { BlueprintScriptConfig } from "../../../data/script"; @@ -17,14 +16,6 @@ export class HaBlueprintScriptEditor extends HaBlueprintGenericEditor { protected render() { return html` - ${this.disabled - ? html` - ${this.hass.localize("ui.panel.config.script.editor.read_only")} - - ${this.hass.localize("ui.panel.config.script.editor.migrate")} - - ` - : nothing} ${this.config.description ? html` @@ -236,7 +239,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { ${this.hass.localize( "ui.panel.config.script.editor.take_control" @@ -312,6 +315,32 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { : nothing} ` : ""} + ${this._blueprintConfig + ? html` + ${this.hass.localize( + "ui.panel.config.script.editor.confirm_take_control" + )} +
+ ${this.hass.localize("ui.common.yes")} + ${this.hass.localize("ui.common.no")} +
+
` + : this._readOnly + ? html`${this.hass.localize( + "ui.panel.config.script.editor.read_only" + )} + + ${this.hass.localize( + "ui.panel.config.script.editor.migrate" + )} + + ` + : nothing} ${this._mode === "gui" ? html`
` : html` @@ -339,31 +367,18 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { .config=${this._config} .disabled=${this._readOnly} @value-changed=${this._valueChanged} - @duplicate=${this._duplicate} > `}
` : this._mode === "yaml" - ? html` ${this._readOnly - ? html` - ${this.hass.localize( - "ui.panel.config.script.editor.read_only" - )} - - ${this.hass.localize( - "ui.panel.config.script.editor.migrate" - )} - - ` - : nothing} - ` + ? html`` : nothing}
ha-alert { margin: 0 auto; max-width: 1040px; padding: 28px 20px 0; + display: block; } .config-container ha-alert { margin-bottom: 16px; diff --git a/src/panels/config/script/manual-script-editor.ts b/src/panels/config/script/manual-script-editor.ts index f5f946229dd7..63f0b555e4f5 100644 --- a/src/panels/config/script/manual-script-editor.ts +++ b/src/panels/config/script/manual-script-editor.ts @@ -60,14 +60,6 @@ export class HaManualScriptEditor extends LitElement { protected render() { return html` - ${this.disabled - ? html` - ${this.hass.localize("ui.panel.config.script.editor.read_only")} - - ${this.hass.localize("ui.panel.config.script.editor.migrate")} - - ` - : nothing} ${this.config.description ? html` Date: Tue, 2 Jul 2024 21:19:29 +0200 Subject: [PATCH 13/14] Add min/max row/columns to resize card editor (#21244) * Add min/max row/columns to resize card editor * Add humidifier and thermostat card * Removed unused condition * Don't set max rows * Add media card * Add button card * Use same rule if there is footer * Don't show disabled cell * Add min rows to sensor card * Update sizes * Update sizes * Update sizes * Add min rows to weather forecast card --- src/components/ha-grid-size-picker.ts | 22 +++++---- src/panels/lovelace/cards/hui-button-card.ts | 11 ++++- src/panels/lovelace/cards/hui-entity-card.ts | 15 ++++++- .../lovelace/cards/hui-humidifier-card.ts | 24 +++++++++- src/panels/lovelace/cards/hui-iframe-card.ts | 1 + src/panels/lovelace/cards/hui-map-card.ts | 2 + .../lovelace/cards/hui-media-control-card.ts | 15 ++++++- src/panels/lovelace/cards/hui-sensor-card.ts | 2 + .../lovelace/cards/hui-statistic-card.ts | 16 +++++-- .../lovelace/cards/hui-thermostat-card.ts | 24 +++++++++- src/panels/lovelace/cards/hui-tile-card.ts | 18 +++++--- .../cards/hui-weather-forecast-card.ts | 26 ++++++++++- .../card-editor/ha-grid-layout-slider.ts | 23 +++++----- .../card-editor/hui-card-layout-editor.ts | 30 +++++++------ .../lovelace/sections/hui-grid-section.ts | 45 ++++++++++++++++--- src/panels/lovelace/types.ts | 4 ++ 16 files changed, 222 insertions(+), 56 deletions(-) diff --git a/src/components/ha-grid-size-picker.ts b/src/components/ha-grid-size-picker.ts index dca2cbd2fbe1..453a24cb8d30 100644 --- a/src/components/ha-grid-size-picker.ts +++ b/src/components/ha-grid-size-picker.ts @@ -7,6 +7,7 @@ import { mdiRestore } from "@mdi/js"; import { styleMap } from "lit/directives/style-map"; import { fireEvent } from "../common/dom/fire_event"; import { HomeAssistant } from "../types"; +import { conditionalClamp } from "../common/number/clamp"; type GridSizeValue = { rows?: number; @@ -42,6 +43,10 @@ export class HaGridSizeEditor extends LitElement { } protected render() { + const disabledColumns = + this.columnMin !== undefined && this.columnMin === this.columnMax; + const disabledRows = + this.rowMin !== undefined && this.rowMin === this.rowMax; return html`
${!this.isDefault ? html` @@ -100,17 +107,11 @@ export class HaGridSizeEditor extends LitElement { .map((_, index) => { const row = Math.floor(index / this.columns) + 1; const column = (index % this.columns) + 1; - const disabled = - (this.rowMin !== undefined && row < this.rowMin) || - (this.rowMax !== undefined && row > this.rowMax) || - (this.columnMin !== undefined && column < this.columnMin) || - (this.columnMax !== undefined && column > this.columnMax); return html`
`; @@ -126,11 +127,16 @@ export class HaGridSizeEditor extends LitElement { _cellClick(ev) { const cell = ev.currentTarget as HTMLElement; - if (cell.getAttribute("disabled") !== null) return; const rows = Number(cell.getAttribute("data-row")); const columns = Number(cell.getAttribute("data-column")); + const clampedRow = conditionalClamp(rows, this.rowMin, this.rowMax); + const clampedColumn = conditionalClamp( + columns, + this.columnMin, + this.columnMax + ); fireEvent(this, "value-changed", { - value: { rows, columns }, + value: { rows: clampedRow, columns: clampedColumn }, }); } diff --git a/src/panels/lovelace/cards/hui-button-card.ts b/src/panels/lovelace/cards/hui-button-card.ts index 160e5c427747..f7492d0f65a1 100644 --- a/src/panels/lovelace/cards/hui-button-card.ts +++ b/src/panels/lovelace/cards/hui-button-card.ts @@ -145,9 +145,16 @@ export class HuiButtonCard extends LitElement implements LovelaceCard { this._config?.show_icon && (this._config?.show_name || this._config?.show_state) ) { - return { grid_rows: 2, grid_columns: 2 }; + return { + grid_rows: 2, + grid_columns: 2, + grid_min_rows: 2, + }; } - return { grid_rows: 1, grid_columns: 1 }; + return { + grid_rows: 1, + grid_columns: 1, + }; } public setConfig(config: ButtonCardConfig): void { diff --git a/src/panels/lovelace/cards/hui-entity-card.ts b/src/panels/lovelace/cards/hui-entity-card.ts index e6366cd28b6c..42861e70fe4e 100644 --- a/src/panels/lovelace/cards/hui-entity-card.ts +++ b/src/panels/lovelace/cards/hui-entity-card.ts @@ -36,7 +36,11 @@ import { findEntities } from "../common/find-entities"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import { createHeaderFooterElement } from "../create-element/create-header-footer-element"; -import { LovelaceCard, LovelaceHeaderFooter } from "../types"; +import { + LovelaceCard, + LovelaceHeaderFooter, + LovelaceLayoutOptions, +} from "../types"; import { HuiErrorCard } from "./hui-error-card"; import { EntityCardConfig } from "./types"; @@ -241,6 +245,15 @@ export class HuiEntityCard extends LitElement implements LovelaceCard { fireEvent(this, "hass-more-info", { entityId: this._config!.entity }); } + public getLayoutOptions(): LovelaceLayoutOptions { + return { + grid_columns: 2, + grid_rows: 2, + grid_min_columns: 2, + grid_min_rows: 2, + }; + } + static get styles(): CSSResultGroup { return [ iconColorCSS, diff --git a/src/panels/lovelace/cards/hui-humidifier-card.ts b/src/panels/lovelace/cards/hui-humidifier-card.ts index f964148c0a64..405158847a09 100644 --- a/src/panels/lovelace/cards/hui-humidifier-card.ts +++ b/src/panels/lovelace/cards/hui-humidifier-card.ts @@ -22,7 +22,11 @@ import { HomeAssistant } from "../../../types"; import "../card-features/hui-card-features"; import { findEntities } from "../common/find-entities"; import { createEntityNotFoundWarning } from "../components/hui-warning"; -import { LovelaceCard, LovelaceCardEditor } from "../types"; +import { + LovelaceCard, + LovelaceCardEditor, + LovelaceLayoutOptions, +} from "../types"; import { HumidifierCardConfig } from "./types"; @customElement("hui-humidifier-card") @@ -173,6 +177,24 @@ export class HuiHumidifierCard extends LitElement implements LovelaceCard { `; } + public getLayoutOptions(): LovelaceLayoutOptions { + const grid_columns = 4; + let grid_rows = 5; + let grid_min_rows = 2; + const grid_min_columns = 2; + if (this._config?.features?.length) { + const featureHeight = Math.ceil((this._config.features.length * 2) / 3); + grid_rows += featureHeight; + grid_min_rows += featureHeight; + } + return { + grid_columns, + grid_rows, + grid_min_rows, + grid_min_columns, + }; + } + static get styles(): CSSResultGroup { return css` :host { diff --git a/src/panels/lovelace/cards/hui-iframe-card.ts b/src/panels/lovelace/cards/hui-iframe-card.ts index c87766cbae64..36cdea605ec3 100644 --- a/src/panels/lovelace/cards/hui-iframe-card.ts +++ b/src/panels/lovelace/cards/hui-iframe-card.ts @@ -119,6 +119,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard { return { grid_columns: 4, grid_rows: 4, + grid_min_rows: 2, }; } diff --git a/src/panels/lovelace/cards/hui-map-card.ts b/src/panels/lovelace/cards/hui-map-card.ts index ef0d25be529e..0c810280c29c 100644 --- a/src/panels/lovelace/cards/hui-map-card.ts +++ b/src/panels/lovelace/cards/hui-map-card.ts @@ -432,6 +432,8 @@ class HuiMapCard extends LitElement implements LovelaceCard { return { grid_columns: 4, grid_rows: 4, + grid_min_columns: 2, + grid_min_rows: 2, }; } diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index ffdfe2c34a2f..4cd3e0f1058d 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -40,7 +40,11 @@ import { findEntities } from "../common/find-entities"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-marquee"; import { createEntityNotFoundWarning } from "../components/hui-warning"; -import type { LovelaceCard, LovelaceCardEditor } from "../types"; +import type { + LovelaceCard, + LovelaceCardEditor, + LovelaceLayoutOptions, +} from "../types"; import { MediaControlCardConfig } from "./types"; @customElement("hui-media-control-card") @@ -582,6 +586,15 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { } } + public getLayoutOptions(): LovelaceLayoutOptions { + return { + grid_columns: 4, + grid_min_columns: 2, + grid_rows: 3, + grid_min_rows: 3, + }; + } + static get styles(): CSSResultGroup { return css` ha-card { diff --git a/src/panels/lovelace/cards/hui-sensor-card.ts b/src/panels/lovelace/cards/hui-sensor-card.ts index 76ba0fa63626..c456d427b6ab 100644 --- a/src/panels/lovelace/cards/hui-sensor-card.ts +++ b/src/panels/lovelace/cards/hui-sensor-card.ts @@ -76,6 +76,8 @@ class HuiSensorCard extends HuiEntityCard { return { grid_columns: 2, grid_rows: 2, + grid_min_columns: 2, + grid_min_rows: 2, }; } diff --git a/src/panels/lovelace/cards/hui-statistic-card.ts b/src/panels/lovelace/cards/hui-statistic-card.ts index e5beb4a209cc..62338e7a65f3 100644 --- a/src/panels/lovelace/cards/hui-statistic-card.ts +++ b/src/panels/lovelace/cards/hui-statistic-card.ts @@ -1,10 +1,10 @@ import { HassEntity } from "home-assistant-js-websocket"; import { - css, CSSResultGroup, - html, LitElement, PropertyValues, + css, + html, nothing, } from "lit"; import { customElement, property, state } from "lit/decorators"; @@ -16,12 +16,12 @@ import "../../../components/ha-alert"; import "../../../components/ha-card"; import "../../../components/ha-state-icon"; import { + StatisticsMetaData, fetchStatistic, getDisplayUnit, getStatisticLabel, getStatisticMetadata, isExternalStatistic, - StatisticsMetaData, } from "../../../data/recorder"; import { HomeAssistant } from "../../../types"; import { computeCardSize } from "../common/compute-card-size"; @@ -32,6 +32,7 @@ import { LovelaceCard, LovelaceCardEditor, LovelaceHeaderFooter, + LovelaceLayoutOptions, } from "../types"; import { HuiErrorCard } from "./hui-error-card"; import { EntityCardConfig, StatisticCardConfig } from "./types"; @@ -254,6 +255,15 @@ export class HuiStatisticCard extends LitElement implements LovelaceCard { fireEvent(this, "hass-more-info", { entityId: this._config!.entity }); } + public getLayoutOptions(): LovelaceLayoutOptions { + return { + grid_columns: 2, + grid_rows: 2, + grid_min_columns: 2, + grid_min_rows: 2, + }; + } + static get styles(): CSSResultGroup { return [ css` diff --git a/src/panels/lovelace/cards/hui-thermostat-card.ts b/src/panels/lovelace/cards/hui-thermostat-card.ts index d8d58ee9c776..620f17a20562 100644 --- a/src/panels/lovelace/cards/hui-thermostat-card.ts +++ b/src/panels/lovelace/cards/hui-thermostat-card.ts @@ -22,7 +22,11 @@ import { HomeAssistant } from "../../../types"; import "../card-features/hui-card-features"; import { findEntities } from "../common/find-entities"; import { createEntityNotFoundWarning } from "../components/hui-warning"; -import { LovelaceCard, LovelaceCardEditor } from "../types"; +import { + LovelaceCard, + LovelaceCardEditor, + LovelaceLayoutOptions, +} from "../types"; import { ThermostatCardConfig } from "./types"; @customElement("hui-thermostat-card") @@ -165,6 +169,24 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard { `; } + public getLayoutOptions(): LovelaceLayoutOptions { + const grid_columns = 4; + let grid_rows = 5; + let grid_min_rows = 2; + const grid_min_columns = 2; + if (this._config?.features?.length) { + const featureHeight = Math.ceil((this._config.features.length * 2) / 3); + grid_rows += featureHeight; + grid_min_rows += featureHeight; + } + return { + grid_columns, + grid_rows, + grid_min_rows, + grid_min_columns, + }; + } + static get styles(): CSSResultGroup { return css` :host { diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index fa8c2cc6d067..19a05e3bb4ab 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -122,17 +122,21 @@ export class HuiTileCard extends LitElement implements LovelaceCard { } public getLayoutOptions(): LovelaceLayoutOptions { - const options = { - grid_columns: 2, - grid_rows: 1, - }; + const grid_columns = 2; + let grid_rows = 1; if (this._config?.features?.length) { - options.grid_rows += Math.ceil((this._config.features.length * 2) / 3); + const featureHeight = Math.ceil((this._config.features.length * 2) / 3); + grid_rows += featureHeight; } if (this._config?.vertical) { - options.grid_rows++; + grid_rows!++; } - return options; + return { + grid_columns, + grid_rows, + grid_min_rows: grid_rows, + grid_min_columns: grid_columns, + }; } private _handleAction(ev: ActionHandlerEvent) { diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index 40649ed32ae2..fadca1dd5aef 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -38,7 +38,11 @@ import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { createEntityNotFoundWarning } from "../components/hui-warning"; -import type { LovelaceCard, LovelaceCardEditor } from "../types"; +import type { + LovelaceCard, + LovelaceCardEditor, + LovelaceLayoutOptions, +} from "../types"; import type { WeatherForecastCardConfig } from "./types"; @customElement("hui-weather-forecast-card") @@ -421,6 +425,26 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { return typeof item !== "undefined" && item !== null; } + public getLayoutOptions(): LovelaceLayoutOptions { + if ( + this._config?.show_current !== false && + this._config?.show_forecast !== false + ) { + return { + grid_columns: 4, + grid_min_columns: 2, + grid_rows: 3, + grid_min_rows: 3, + }; + } + return { + grid_columns: 4, + grid_min_columns: 2, + grid_rows: 2, + grid_min_rows: 1, + }; + } + static get styles(): CSSResultGroup { return [ weatherSVGStyles, diff --git a/src/panels/lovelace/editor/card-editor/ha-grid-layout-slider.ts b/src/panels/lovelace/editor/card-editor/ha-grid-layout-slider.ts index 2ef6a61f0c40..ab1bebf00fcc 100644 --- a/src/panels/lovelace/editor/card-editor/ha-grid-layout-slider.ts +++ b/src/panels/lovelace/editor/card-editor/ha-grid-layout-slider.ts @@ -255,15 +255,14 @@ export class HaGridLayoutSlider extends LitElement { >
-
-
-
+
+
${this.value !== undefined ? html`
` @@ -323,11 +322,12 @@ export class HaGridLayoutSlider extends LitElement { position: absolute; inset: 0; background: var(--disabled-color); - opacity: 0.5; + opacity: 0.2; } .active { position: absolute; background: grey; + opacity: 0.7; top: 0; right: calc(var(--max) * 100%); bottom: 0; @@ -375,6 +375,9 @@ export class HaGridLayoutSlider extends LitElement { :host(:disabled) .slider { cursor: not-allowed; } + :host(:disabled) .handle:after { + background: var(--disabled-color); + } .pressed .handle { transition: none; } diff --git a/src/panels/lovelace/editor/card-editor/hui-card-layout-editor.ts b/src/panels/lovelace/editor/card-editor/hui-card-layout-editor.ts index 68c0487beee4..5a5690727ce6 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-layout-editor.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-layout-editor.ts @@ -19,7 +19,7 @@ import { LovelaceCardConfig } from "../../../../data/lovelace/config/card"; import { haStyle } from "../../../../resources/styles"; import { HomeAssistant } from "../../../../types"; import { HuiCard } from "../../cards/hui-card"; -import { DEFAULT_GRID_OPTIONS } from "../../sections/hui-grid-section"; +import { computeSizeOnGrid } from "../../sections/hui-grid-section"; import { LovelaceLayoutOptions } from "../../types"; @customElement("hui-card-layout-editor") @@ -38,28 +38,29 @@ export class HuiCardLayoutEditor extends LitElement { private _cardElement?: HuiCard; - private _gridSizeValue = memoizeOne( + private _mergedOptions = memoizeOne( ( options?: LovelaceLayoutOptions, defaultOptions?: LovelaceLayoutOptions ) => ({ - rows: - options?.grid_rows ?? - defaultOptions?.grid_rows ?? - DEFAULT_GRID_OPTIONS.grid_rows, - columns: - options?.grid_columns ?? - defaultOptions?.grid_columns ?? - DEFAULT_GRID_OPTIONS.grid_columns, + ...defaultOptions, + ...options, }) ); + private _gridSizeValue = memoizeOne(computeSizeOnGrid); + private _isDefault = memoizeOne( (options?: LovelaceLayoutOptions) => options?.grid_columns === undefined && options?.grid_rows === undefined ); render() { + const options = this._mergedOptions( + this.config.layout_options, + this._defaultLayoutOptions + ); + return html`

@@ -123,12 +124,13 @@ export class HuiCardLayoutEditor extends LitElement { : html` `} `; diff --git a/src/panels/lovelace/sections/hui-grid-section.ts b/src/panels/lovelace/sections/hui-grid-section.ts index 8b5b8d9bb16c..0cc5c74824c0 100644 --- a/src/panels/lovelace/sections/hui-grid-section.ts +++ b/src/panels/lovelace/sections/hui-grid-section.ts @@ -15,6 +15,7 @@ import { HuiCard } from "../cards/hui-card"; import "../components/hui-card-edit-mode"; import { moveCard } from "../editor/config-util"; import type { Lovelace, LovelaceLayoutOptions } from "../types"; +import { conditionalClamp } from "../../../common/number/clamp"; const CARD_SORTABLE_OPTIONS: HaSortableOptions = { delay: 100, @@ -23,9 +24,41 @@ const CARD_SORTABLE_OPTIONS: HaSortableOptions = { invertedSwapThreshold: 0.7, } as HaSortableOptions; -export const DEFAULT_GRID_OPTIONS: LovelaceLayoutOptions = { +export const DEFAULT_GRID_OPTIONS = { grid_columns: 4, grid_rows: 1, +} as const satisfies LovelaceLayoutOptions; + +type GridSizeValue = { + rows?: number; + columns?: number; +}; + +export const computeSizeOnGrid = ( + options: LovelaceLayoutOptions +): GridSizeValue => { + const rows = + typeof options.grid_rows === "number" + ? conditionalClamp( + options.grid_rows, + options.grid_min_rows, + options.grid_max_rows + ) + : DEFAULT_GRID_OPTIONS.grid_rows; + + const columns = + typeof options.grid_columns === "number" + ? conditionalClamp( + options.grid_columns, + options.grid_min_columns, + options.grid_max_columns + ) + : DEFAULT_GRID_OPTIONS.grid_columns; + + return { + rows, + columns, + }; }; export class GridSection extends LitElement implements LovelaceSectionElement { @@ -101,15 +134,13 @@ export class GridSection extends LitElement implements LovelaceSectionElement { card.layout = "grid"; const layoutOptions = card.getLayoutOptions(); - const columnSize = - layoutOptions.grid_columns ?? DEFAULT_GRID_OPTIONS.grid_columns; - const rowSize = - layoutOptions.grid_rows ?? DEFAULT_GRID_OPTIONS.grid_rows; + const { rows, columns } = computeSizeOnGrid(layoutOptions); + return html`

Date: Tue, 2 Jul 2024 21:21:25 +0200 Subject: [PATCH 14/14] Bumped version to 20240702.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4d2f4be0602b..a045f384a64a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240628.0" +version = "20240702.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md"