From ddb4f21ae3f1d5c6b5ca7d2c676d3e7e6e5d13aa Mon Sep 17 00:00:00 2001 From: karwosts Date: Sat, 18 Nov 2023 09:25:13 -0800 Subject: [PATCH 1/9] Add a picture uploader to picture-card-editor --- .../hui-picture-card-editor.ts | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts index 1ce62d6a78..ba2c9d9e52 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts @@ -4,12 +4,14 @@ import { assert, assign, object, optional, string } from "superstruct"; import { fireEvent } from "../../../../common/dom/fire_event"; import { SchemaUnion } from "../../../../components/ha-form/types"; import "../../../../components/ha-theme-picker"; -import { HomeAssistant } from "../../../../types"; +import { HomeAssistant, ValueChangedEvent } from "../../../../types"; import { PictureCardConfig } from "../../cards/types"; import "../../components/hui-action-editor"; import { LovelaceCardEditor } from "../../types"; import { actionConfigStruct } from "../structs/action-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct"; +import "../../../../components/ha-picture-upload"; +import type { HaPictureUpload } from "../../../../components/ha-picture-upload"; const cardConfigStruct = assign( baseLovelaceCardConfig, @@ -58,6 +60,15 @@ export class HuiPictureCardEditor } return html` + + ) { + const picture = (ev.target as HaPictureUpload).value; + if (picture) { + fireEvent(this, "config-changed", { + config: { ...this._config!, image: picture }, + }); + } + } + private _computeLabelCallback = (schema: SchemaUnion) => { switch (schema.name) { case "theme": From adc48233460c4bab5b2f952e3d13670fb7a31925 Mon Sep 17 00:00:00 2001 From: karwosts Date: Wed, 22 Nov 2023 07:12:38 -0800 Subject: [PATCH 2/9] add imageSelector --- .../ha-selector/ha-selector-image.ts | 113 ++++++++++++++++++ src/components/ha-selector/ha-selector.ts | 1 + src/data/selector.ts | 6 + .../hui-picture-card-editor.ts | 24 +--- .../hui-picture-entity-card-editor.ts | 2 +- .../hui-picture-glance-card-editor.ts | 2 +- 6 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 src/components/ha-selector/ha-selector-image.ts diff --git a/src/components/ha-selector/ha-selector-image.ts b/src/components/ha-selector/ha-selector-image.ts new file mode 100644 index 0000000000..e3effc8608 --- /dev/null +++ b/src/components/ha-selector/ha-selector-image.ts @@ -0,0 +1,113 @@ +import { mdiUpload, mdiUploadOff } from "@mdi/js"; +import { css, CSSResultGroup, html, nothing, LitElement } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { fireEvent } from "../../common/dom/fire_event"; +import { ImageSelector } from "../../data/selector"; +import { HomeAssistant } from "../../types"; +import "../ha-icon-button"; +import "../ha-textarea"; +import "../ha-textfield"; +import "../ha-picture-upload"; +import type { HaPictureUpload } from "../ha-picture-upload"; + +@customElement("ha-selector-image") +export class HaImageSelector extends LitElement { + @property() public hass!: HomeAssistant; + + @property() public value?: any; + + @property() public name?: string; + + @property() public label?: string; + + @property() public placeholder?: string; + + @property() public helper?: string; + + @property() public selector!: ImageSelector; + + @property({ type: Boolean }) public disabled = false; + + @property({ type: Boolean }) public required = true; + + @state() private showUpload = false; + + protected render() { + return html` +
+ + + +
+ ${this.showUpload + ? html` + + ` + : nothing} + `; + } + + private _handleUploadToggle() { + this.showUpload = !this.showUpload; + } + + private _pictureChanged(ev) { + const value = (ev.target as HaPictureUpload).value; + if (value) { + fireEvent(this, "value-changed", { value }); + } + } + + private _handleChange(ev) { + let value = ev.target.value; + if (this.value === value) { + return; + } + if (value === "" && !this.required) { + value = undefined; + } + + fireEvent(this, "value-changed", { value }); + } + + static get styles(): CSSResultGroup { + return css` + :host { + display: block; + position: relative; + } + div { + display: flex; + align-items: center; + } + ha-textarea, + ha-textfield { + width: 100%; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-selector-image": HaImageSelector; + } +} diff --git a/src/components/ha-selector/ha-selector.ts b/src/components/ha-selector/ha-selector.ts index 3bfbb7741e..89dc735259 100644 --- a/src/components/ha-selector/ha-selector.ts +++ b/src/components/ha-selector/ha-selector.ts @@ -29,6 +29,7 @@ const LOAD_ELEMENTS = { entity: () => import("./ha-selector-entity"), statistic: () => import("./ha-selector-statistic"), file: () => import("./ha-selector-file"), + image: () => import("./ha-selector-image"), language: () => import("./ha-selector-language"), navigation: () => import("./ha-selector-navigation"), number: () => import("./ha-selector-number"), diff --git a/src/data/selector.ts b/src/data/selector.ts index 1f34ba3e77..edb87c830f 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -33,6 +33,7 @@ export type Selector = | LegacyEntitySelector | FileSelector | IconSelector + | ImageSelector | LanguageSelector | LocationSelector | MediaSelector @@ -233,6 +234,11 @@ export interface IconSelector { } | null; } +export interface ImageSelector { + // eslint-disable-next-line @typescript-eslint/ban-types + image: {} | null; +} + export interface LanguageSelector { language: { languages?: string[]; diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts index ba2c9d9e52..20ff12e88b 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts @@ -4,14 +4,12 @@ import { assert, assign, object, optional, string } from "superstruct"; import { fireEvent } from "../../../../common/dom/fire_event"; import { SchemaUnion } from "../../../../components/ha-form/types"; import "../../../../components/ha-theme-picker"; -import { HomeAssistant, ValueChangedEvent } from "../../../../types"; +import { HomeAssistant } from "../../../../types"; import { PictureCardConfig } from "../../cards/types"; import "../../components/hui-action-editor"; import { LovelaceCardEditor } from "../../types"; import { actionConfigStruct } from "../structs/action-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct"; -import "../../../../components/ha-picture-upload"; -import type { HaPictureUpload } from "../../../../components/ha-picture-upload"; const cardConfigStruct = assign( baseLovelaceCardConfig, @@ -26,7 +24,7 @@ const cardConfigStruct = assign( ); const SCHEMA = [ - { name: "image", selector: { text: {} } }, + { name: "image", selector: { image: {} } }, { name: "image_entity", selector: { entity: { domain: "image" } } }, { name: "alt_text", selector: { text: {} } }, { name: "theme", selector: { theme: {} } }, @@ -60,15 +58,6 @@ export class HuiPictureCardEditor } return html` - - ) { - const picture = (ev.target as HaPictureUpload).value; - if (picture) { - fireEvent(this, "config-changed", { - config: { ...this._config!, image: picture }, - }); - } - } - private _computeLabelCallback = (schema: SchemaUnion) => { switch (schema.name) { case "theme": diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-entity-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-entity-card-editor.ts index bf5ffe1539..5cc9d84edf 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-entity-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-entity-card-editor.ts @@ -32,7 +32,7 @@ const cardConfigStruct = assign( const SCHEMA = [ { name: "entity", required: true, selector: { entity: {} } }, { name: "name", selector: { text: {} } }, - { name: "image", selector: { text: {} } }, + { name: "image", selector: { image: {} } }, { name: "camera_image", selector: { entity: { domain: "camera" } } }, { name: "", diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-glance-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-glance-card-editor.ts index 5d4d15c431..1c74428d38 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-glance-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-glance-card-editor.ts @@ -35,7 +35,7 @@ const cardConfigStruct = assign( const SCHEMA = [ { name: "title", selector: { text: {} } }, - { name: "image", selector: { text: {} } }, + { name: "image", selector: { image: {} } }, { name: "image_entity", selector: { entity: { domain: "image" } } }, { name: "camera_image", selector: { entity: { domain: "camera" } } }, { From b6199bf43071d85d1c325f3b9eba04b01d7c40bc Mon Sep 17 00:00:00 2001 From: karwosts Date: Wed, 22 Nov 2023 07:26:12 -0800 Subject: [PATCH 3/9] lint --- src/components/ha-selector/ha-selector-image.ts | 6 +++++- src/translations/en.json | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/ha-selector/ha-selector-image.ts b/src/components/ha-selector/ha-selector-image.ts index e3effc8608..7152bb0758 100644 --- a/src/components/ha-selector/ha-selector-image.ts +++ b/src/components/ha-selector/ha-selector-image.ts @@ -49,7 +49,11 @@ export class HaImageSelector extends LitElement { diff --git a/src/translations/en.json b/src/translations/en.json index 20e3ad35d3..ba8b7d1ebe 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -329,6 +329,10 @@ "upload_failed": "Upload failed", "unknown_file": "Unknown file" }, + "image": { + "upload_on": "Show Upload Form", + "upload_off": "Hide Upload Form" + }, "text": { "show_password": "Show password", "hide_password": "Hide password" From de3a92f0f5067a81f22b501f6a02fb5d06ba3798 Mon Sep 17 00:00:00 2001 From: karwosts Date: Thu, 7 Dec 2023 08:35:04 -0800 Subject: [PATCH 4/9] Add delete button to picture-upload --- src/components/ha-picture-upload.ts | 94 ++++++++++++++++++----------- src/data/image_upload.ts | 18 +++++- src/resources/styles.ts | 1 + 3 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/components/ha-picture-upload.ts b/src/components/ha-picture-upload.ts index 7a23a3b093..429d694a3b 100644 --- a/src/components/ha-picture-upload.ts +++ b/src/components/ha-picture-upload.ts @@ -2,7 +2,13 @@ import { mdiImagePlus } from "@mdi/js"; import { LitElement, TemplateResult, css, html } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; -import { createImage, generateImageThumbnailUrl } from "../data/image_upload"; +import { haStyle } from "../resources/styles"; +import { + createImage, + deleteImage, + generateImageThumbnailUrl, + getIdFromUrl, +} from "../data/image_upload"; import { showAlertDialog } from "../dialogs/generic/show-dialog-box"; import { CropOptions, @@ -60,13 +66,21 @@ export class HaPictureUpload extends LitElement { alt=${this.currentImageAltText || this.hass.localize("ui.components.picture-upload.current_image_alt")} /> - - +
+ + + + +
`; } @@ -76,6 +90,15 @@ export class HaPictureUpload extends LitElement { fireEvent(this, "change"); } + private async _handleDelete() { + const id = getIdFromUrl(this.value!); + if (id) { + await deleteImage(this.hass, id); + this.value = null; + fireEvent(this, "change"); + } + } + private async _handleFilePicked(ev) { const file = ev.detail.files[0]; if (this.crop) { @@ -134,32 +157,35 @@ export class HaPictureUpload extends LitElement { } static get styles() { - return css` - :host { - display: block; - height: 240px; - } - ha-file-upload { - height: 100%; - } - .center-vertical { - display: flex; - align-items: center; - height: 100%; - } - .value { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; - } - img { - max-width: 100%; - max-height: 200px; - margin-bottom: 4px; - border-radius: var(--file-upload-image-border-radius); - } - `; + return [ + haStyle, + css` + :host { + display: block; + height: 240px; + } + ha-file-upload { + height: 100%; + } + .center-vertical { + display: flex; + align-items: center; + height: 100%; + } + .value { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + } + img { + max-width: 100%; + max-height: 200px; + margin-bottom: 4px; + border-radius: var(--file-upload-image-border-radius); + } + `, + ]; } } diff --git a/src/data/image_upload.ts b/src/data/image_upload.ts index 94198de6dc..700bd4172a 100644 --- a/src/data/image_upload.ts +++ b/src/data/image_upload.ts @@ -8,12 +8,26 @@ interface Image { id: string; } +const URL_PREFIX = "/api/image/serve/"; + export interface ImageMutableParams { name: string; } +export const getIdFromUrl = (url: string): string | undefined => { + let id; + if (url.startsWith(URL_PREFIX)) { + id = url.substring(URL_PREFIX.length); + const idx = id.indexOf("/"); + if (idx >= 0) { + id = id.substring(0, idx); + } + } + return id; +}; + export const generateImageThumbnailUrl = (mediaId: string, size: number) => - `/api/image/serve/${mediaId}/${size}x${size}`; + `${URL_PREFIX}${mediaId}/${size}x${size}`; export const fetchImages = (hass: HomeAssistant) => hass.callWS({ type: "image/list" }); @@ -50,5 +64,5 @@ export const updateImage = ( export const deleteImage = (hass: HomeAssistant, id: string) => hass.callWS({ type: "image/delete", - media_id: id, + image_id: id, }); diff --git a/src/resources/styles.ts b/src/resources/styles.ts index 80eef864e7..be69f4fe08 100644 --- a/src/resources/styles.ts +++ b/src/resources/styles.ts @@ -80,6 +80,7 @@ export const haStyle = css` color: var(--error-color); } + ha-button.warning, mwc-button.warning { --mdc-theme-primary: var(--error-color); } From ec048b32a7c88e4e63fc4362560088840ca15af5 Mon Sep 17 00:00:00 2001 From: karwosts Date: Thu, 7 Dec 2023 12:31:44 -0800 Subject: [PATCH 5/9] updates from feedback --- src/components/ha-picture-upload.ts | 18 +-- .../ha-selector/ha-selector-image.ts | 105 +++++++++++------- src/data/image_upload.ts | 2 +- src/translations/en.json | 5 +- 4 files changed, 81 insertions(+), 49 deletions(-) diff --git a/src/components/ha-picture-upload.ts b/src/components/ha-picture-upload.ts index 429d694a3b..128c8dcbf5 100644 --- a/src/components/ha-picture-upload.ts +++ b/src/components/ha-picture-upload.ts @@ -1,5 +1,5 @@ import { mdiImagePlus } from "@mdi/js"; -import { LitElement, TemplateResult, css, html } from "lit"; +import { LitElement, TemplateResult, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; import { haStyle } from "../resources/styles"; @@ -35,6 +35,8 @@ export class HaPictureUpload extends LitElement { @property({ type: Boolean }) public crop = false; + @property({ type: Boolean }) public canDelete = false; + @property({ attribute: false }) public cropOptions?: CropOptions; @property({ type: Number }) public size = 512; @@ -74,12 +76,14 @@ export class HaPictureUpload extends LitElement { )} > - - + ${this.canDelete + ? html` + ` + : nothing} `; diff --git a/src/components/ha-selector/ha-selector-image.ts b/src/components/ha-selector/ha-selector-image.ts index 7152bb0758..486762648b 100644 --- a/src/components/ha-selector/ha-selector-image.ts +++ b/src/components/ha-selector/ha-selector-image.ts @@ -1,5 +1,4 @@ -import { mdiUpload, mdiUploadOff } from "@mdi/js"; -import { css, CSSResultGroup, html, nothing, LitElement } from "lit"; +import { css, CSSResultGroup, html, LitElement } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../../common/dom/fire_event"; import { ImageSelector } from "../../data/selector"; @@ -8,7 +7,9 @@ import "../ha-icon-button"; import "../ha-textarea"; import "../ha-textfield"; import "../ha-picture-upload"; +import "../ha-radio"; import type { HaPictureUpload } from "../ha-picture-upload"; +import { URL_PREFIX } from "../../data/image_upload"; @customElement("ha-selector-image") export class HaImageSelector extends LitElement { @@ -32,52 +33,74 @@ export class HaImageSelector extends LitElement { @state() private showUpload = false; + protected firstUpdated(changedProps): void { + super.firstUpdated(changedProps); + + if (!this.value || this.value.startsWith(URL_PREFIX)) { + this.showUpload = true; + } + } + protected render() { return html` -
- - - +
+ + ${!this.showUpload + ? html` + + ` + : html` + + `}
- ${this.showUpload - ? html` - - ` - : nothing} `; } - private _handleUploadToggle() { - this.showUpload = !this.showUpload; + private _radioGroupPicked(ev): void { + this.showUpload = ev.target.value === "upload"; } private _pictureChanged(ev) { const value = (ev.target as HaPictureUpload).value; - if (value) { - fireEvent(this, "value-changed", { value }); - } + + fireEvent(this, "value-changed", { value: value ?? undefined }); } private _handleChange(ev) { @@ -100,7 +123,11 @@ export class HaImageSelector extends LitElement { } div { display: flex; - align-items: center; + flex-direction: column; + } + label { + display: flex; + flex-direction: column; } ha-textarea, ha-textfield { diff --git a/src/data/image_upload.ts b/src/data/image_upload.ts index 700bd4172a..9524484e8e 100644 --- a/src/data/image_upload.ts +++ b/src/data/image_upload.ts @@ -8,7 +8,7 @@ interface Image { id: string; } -const URL_PREFIX = "/api/image/serve/"; +export const URL_PREFIX = "/api/image/serve/"; export interface ImageMutableParams { name: string; diff --git a/src/translations/en.json b/src/translations/en.json index ba8b7d1ebe..ed56a9708b 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -330,8 +330,9 @@ "unknown_file": "Unknown file" }, "image": { - "upload_on": "Show Upload Form", - "upload_off": "Hide Upload Form" + "select_image": "Select image", + "upload": "Upload picture", + "url": "Local path or web URL" }, "text": { "show_password": "Show password", From d5528a21602aa08ae1ab91ae1c0cd94aa4fcd7f3 Mon Sep 17 00:00:00 2001 From: karwosts Date: Fri, 16 Feb 2024 16:33:57 -0800 Subject: [PATCH 6/9] fix lint --- src/components/ha-selector/ha-selector-image.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ha-selector/ha-selector-image.ts b/src/components/ha-selector/ha-selector-image.ts index 486762648b..504a61cbe4 100644 --- a/src/components/ha-selector/ha-selector-image.ts +++ b/src/components/ha-selector/ha-selector-image.ts @@ -13,7 +13,7 @@ import { URL_PREFIX } from "../../data/image_upload"; @customElement("ha-selector-image") export class HaImageSelector extends LitElement { - @property() public hass!: HomeAssistant; + @property({ attribute: false }) public hass!: HomeAssistant; @property() public value?: any; @@ -25,7 +25,7 @@ export class HaImageSelector extends LitElement { @property() public helper?: string; - @property() public selector!: ImageSelector; + @property({ attribute: false }) public selector!: ImageSelector; @property({ type: Boolean }) public disabled = false; From 2a5a49e472062b5813edd72354b8235e87dd7078 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Fri, 19 Apr 2024 19:48:12 -0700 Subject: [PATCH 7/9] Update en.json --- src/translations/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/translations/en.json b/src/translations/en.json index 43e7dbda2d..ec6099e69f 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -381,6 +381,7 @@ "select_image": "Select image", "upload": "Upload picture", "url": "Local path or web URL" + }, "location": { "latitude": "[%key:ui::panel::config::zone::detail::latitude%]", "longitude": "[%key:ui::panel::config::zone::detail::longitude%]", From 0f45ccadb0d8f55096feb2b134ab8f803ca1145b Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Fri, 19 Apr 2024 19:55:42 -0700 Subject: [PATCH 8/9] Update selector.ts --- src/data/selector.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data/selector.ts b/src/data/selector.ts index e549f171bb..fc8eed8c93 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -259,6 +259,7 @@ export interface IconSelector { export interface ImageSelector { // eslint-disable-next-line @typescript-eslint/ban-types image: {} | null; +} export interface LabelSelector { label: { From 94aa3b845db737bbff770b4bf949211a7871b812 Mon Sep 17 00:00:00 2001 From: karwosts Date: Thu, 25 Apr 2024 10:56:13 -0700 Subject: [PATCH 9/9] remove delete --- src/components/ha-picture-upload.ts | 28 ++----------------- .../ha-selector/ha-selector-image.ts | 1 - 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/src/components/ha-picture-upload.ts b/src/components/ha-picture-upload.ts index 128c8dcbf5..eef4bea748 100644 --- a/src/components/ha-picture-upload.ts +++ b/src/components/ha-picture-upload.ts @@ -1,14 +1,9 @@ import { mdiImagePlus } from "@mdi/js"; -import { LitElement, TemplateResult, css, html, nothing } from "lit"; +import { LitElement, TemplateResult, css, html } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; import { haStyle } from "../resources/styles"; -import { - createImage, - deleteImage, - generateImageThumbnailUrl, - getIdFromUrl, -} from "../data/image_upload"; +import { createImage, generateImageThumbnailUrl } from "../data/image_upload"; import { showAlertDialog } from "../dialogs/generic/show-dialog-box"; import { CropOptions, @@ -35,8 +30,6 @@ export class HaPictureUpload extends LitElement { @property({ type: Boolean }) public crop = false; - @property({ type: Boolean }) public canDelete = false; - @property({ attribute: false }) public cropOptions?: CropOptions; @property({ type: Number }) public size = 512; @@ -76,14 +69,6 @@ export class HaPictureUpload extends LitElement { )} > - ${this.canDelete - ? html` - ` - : nothing}
`; @@ -94,15 +79,6 @@ export class HaPictureUpload extends LitElement { fireEvent(this, "change"); } - private async _handleDelete() { - const id = getIdFromUrl(this.value!); - if (id) { - await deleteImage(this.hass, id); - this.value = null; - fireEvent(this, "change"); - } - } - private async _handleFilePicked(ev) { const file = ev.detail.files[0]; if (this.crop) { diff --git a/src/components/ha-selector/ha-selector-image.ts b/src/components/ha-selector/ha-selector-image.ts index 504a61cbe4..80eccaf787 100644 --- a/src/components/ha-selector/ha-selector-image.ts +++ b/src/components/ha-selector/ha-selector-image.ts @@ -83,7 +83,6 @@ export class HaImageSelector extends LitElement { ` : html`