import type { TemplateResult } from "lit"; import { css, html, LitElement } from "lit"; import { customElement, state } from "lit/decorators"; import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry"; import { mockConfigEntries } from "../../../../demo/src/stubs/config_entries"; import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry"; import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry"; import { mockFloorRegistry } from "../../../../demo/src/stubs/floor_registry"; import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor"; import { mockLabelRegistry } from "../../../../demo/src/stubs/label_registry"; import "../../../../src/components/ha-formfield"; import "../../../../src/components/ha-selector/ha-selector"; import "../../../../src/components/ha-settings-row"; import type { AreaRegistryEntry } from "../../../../src/data/area_registry"; import type { BlueprintInput } from "../../../../src/data/blueprint"; import type { DeviceRegistryEntry } from "../../../../src/data/device_registry"; import type { FloorRegistryEntry } from "../../../../src/data/floor_registry"; import type { LabelRegistryEntry } from "../../../../src/data/label_registry"; import { showDialog } from "../../../../src/dialogs/make-dialog-manager"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import type { ProvideHassElement } from "../../../../src/mixins/provide-hass-lit-mixin"; import type { HomeAssistant } from "../../../../src/types"; import "../../components/demo-black-white-row"; const ENTITIES = [ getEntity("alarm_control_panel", "alarm", "disarmed", { friendly_name: "Alarm", }), getEntity("media_player", "livingroom", "playing", { friendly_name: "Livingroom", }), getEntity("media_player", "lounge", "idle", { friendly_name: "Lounge", supported_features: 444983, }), getEntity("light", "bedroom", "on", { friendly_name: "Bedroom", }), getEntity("switch", "coffee", "off", { friendly_name: "Coffee", }), ]; const DEVICES: DeviceRegistryEntry[] = [ { area_id: "bedroom", configuration_url: null, config_entries: ["config_entry_1"], config_entries_subentries: {}, connections: [], disabled_by: null, entry_type: null, id: "device_1", identifiers: [["demo", "volume1"] as [string, string]], manufacturer: null, model: null, model_id: null, name_by_user: null, name: "Dishwasher", sw_version: null, hw_version: null, via_device_id: null, serial_number: null, labels: [], created_at: 0, modified_at: 0, primary_config_entry: null, }, { area_id: "backyard", configuration_url: null, config_entries: ["config_entry_2"], config_entries_subentries: {}, connections: [], disabled_by: null, entry_type: null, id: "device_2", identifiers: [["demo", "pwm1"] as [string, string]], manufacturer: null, model: null, model_id: null, name_by_user: null, name: "Lamp", sw_version: null, hw_version: null, via_device_id: null, serial_number: null, labels: [], created_at: 0, modified_at: 0, primary_config_entry: null, }, { area_id: null, configuration_url: null, config_entries: ["config_entry_3"], config_entries_subentries: {}, connections: [], disabled_by: null, entry_type: null, id: "device_3", identifiers: [["demo", "pwm1"] as [string, string]], manufacturer: null, model: null, model_id: null, name_by_user: "User name", name: "Technical name", sw_version: null, hw_version: null, via_device_id: null, serial_number: null, labels: [], created_at: 0, modified_at: 0, primary_config_entry: null, }, ]; const AREAS: AreaRegistryEntry[] = [ { area_id: "backyard", floor_id: "ground", name: "Backyard", icon: null, picture: null, aliases: [], labels: [], temperature_entity_id: null, humidity_entity_id: null, created_at: 0, modified_at: 0, }, { area_id: "bedroom", floor_id: "first", name: "Bedroom", icon: "mdi:bed", picture: null, aliases: [], labels: [], temperature_entity_id: null, humidity_entity_id: null, created_at: 0, modified_at: 0, }, { area_id: "livingroom", floor_id: "ground", name: "Livingroom", icon: "mdi:sofa", picture: null, aliases: [], labels: [], temperature_entity_id: null, humidity_entity_id: null, created_at: 0, modified_at: 0, }, ]; const FLOORS: FloorRegistryEntry[] = [ { floor_id: "ground", name: "Ground floor", level: 0, icon: null, aliases: [], created_at: 0, modified_at: 0, }, { floor_id: "first", name: "First floor", level: 1, icon: "mdi:numeric-1", aliases: [], created_at: 0, modified_at: 0, }, { floor_id: "second", name: "Second floor", level: 2, icon: "mdi:numeric-2", aliases: [], created_at: 0, modified_at: 0, }, ]; const LABELS: LabelRegistryEntry[] = [ { label_id: "energy", name: "Energy", icon: null, color: "yellow", description: null, created_at: 0, modified_at: 0, }, { label_id: "entertainment", name: "Entertainment", icon: "mdi:popcorn", color: "blue", description: null, created_at: 0, modified_at: 0, }, ]; const SCHEMAS: { name: string; input: Record; }[] = [ { name: "One of each", input: { label: { name: "Label", selector: { label: {} } }, floor: { name: "Floor", selector: { floor: {} } }, area: { name: "Area", selector: { area: {} } }, device: { name: "Device", selector: { device: {} } }, entity: { name: "Entity", selector: { entity: {} } }, target: { name: "Target", selector: { target: {} } }, state: { name: "State", selector: { state: { entity_id: "alarm_control_panel.alarm" } }, }, attribute: { name: "Attribute", selector: { attribute: { entity_id: "" } }, }, config_entry: { name: "Integration", selector: { config_entry: {} }, }, duration: { name: "Duration", selector: { duration: {} } }, addon: { name: "Addon", selector: { addon: {} } }, number_box: { name: "Number Box", selector: { number: { min: 0, max: 10, mode: "box", }, }, }, number_slider: { name: "Number Slider", selector: { number: { min: 0, max: 10, mode: "slider", }, }, }, boolean: { name: "Boolean", selector: { boolean: {} } }, time: { name: "Time", selector: { time: {} } }, date: { name: "Date", selector: { date: {} } }, datetime: { name: "Date Time", selector: { datetime: {} } }, action: { name: "Action", selector: { action: {} } }, text: { name: "Text", selector: { text: {} }, }, password: { name: "Password", selector: { text: { type: "password" } }, }, text_multiline: { name: "Text multiline", selector: { text: { multiline: true }, }, }, object: { name: "Object", selector: { object: {} } }, select_radio: { name: "Select (Radio)", selector: { select: { options: ["Option 1", "Option 2"], mode: "list" }, }, }, template: { name: "Template", selector: { template: {} } }, select: { name: "Select", selector: { select: { options: [ "Option 1", "Option 2", "Option 3", "Option 4", "Option 5", "Option 6", ], }, }, }, select_disabled_list: { name: "Select disabled option", selector: { select: { options: [ { label: "Option 1", value: "Option 1" }, { label: "Option 2", value: "Option 2" }, { label: "Option 3", value: "Option 3", disabled: true }, ], mode: "list", }, }, }, select_disabled_multiple: { name: "Select disabled option", selector: { select: { multiple: true, options: [ { label: "Option 1", value: "Option 1" }, { label: "Option 2", value: "Option 2" }, { label: "Option 3", value: "Option 3", disabled: true }, ], mode: "list", }, }, }, select_disabled: { name: "Select disabled option", selector: { select: { options: [ { label: "Option 1", value: "Option 1" }, { label: "Option 2", value: "Option 2" }, { label: "Option 3", value: "Option 3", disabled: true }, { label: "Option 4", value: "Option 4", disabled: true }, { label: "Option 5", value: "Option 5", disabled: true }, { label: "Option 6", value: "Option 6" }, ], }, }, }, select_custom: { name: "Select (Custom)", selector: { select: { custom_value: true, options: [ "Option 1", "Option 2", "Option 3", "Option 4", "Option 5", "Option 6", ], }, }, }, icon: { name: "Icon", selector: { icon: {} } }, media: { name: "Media", selector: { media: {} } }, location: { name: "Location", selector: { location: {} } }, location_radius: { name: "Location with radius", selector: { location: { radius: true, icon: "mdi:home" } }, }, color_temp: { name: "Color Temperature", selector: { color_temp: {} }, }, color_rgb: { name: "Color", selector: { color_rgb: {} } }, qr_code: { name: "QR Code", selector: { qr_code: { data: "https://home-assistant.io" } }, }, constant: { name: "Constant", selector: { constant: { value: true, label: "Yes!" } }, }, }, }, { name: "Multiples", input: { entity: { name: "Entity", selector: { entity: { multiple: true } } }, device: { name: "Device", selector: { device: { multiple: true } } }, area: { name: "Area", selector: { area: { multiple: true } } }, floor: { name: "Floor", selector: { floor: { multiple: true } } }, label: { name: "Label", selector: { label: { multiple: true } } }, select: { name: "Select Multiple", selector: { select: { multiple: true, custom_value: true, options: [ "Option 1", "Option 2", "Option 3", "Option 4", "Option 5", "Option 6", ], }, }, }, select_checkbox: { name: "Select Multiple (Checkbox)", required: false, selector: { select: { mode: "list", multiple: true, options: ["Option 1", "Option 2", "Option 3", "Option 4"], }, }, }, items: { name: "Items", selector: { object: { label_field: "name", description_field: "value", multiple: true, fields: { name: { label: "Name", selector: { text: {} }, required: true, }, value: { label: "Value", selector: { number: { mode: "slider", min: 0, max: 100, unit_of_measurement: "%", }, }, }, }, }, }, }, }, }, ]; @customElement("demo-components-ha-selector") class DemoHaSelector extends LitElement implements ProvideHassElement { @state() public hass!: HomeAssistant; @state() private _disabled = false; @state() private _required = false; @state() private _helper = false; @state() private _label = true; private data = SCHEMAS.map(() => ({})); constructor() { super(); const hass = provideHass(this); hass.updateTranslations(null, "en"); hass.updateTranslations("config", "en"); hass.addEntities(ENTITIES); mockEntityRegistry(hass); mockDeviceRegistry(hass, DEVICES); mockConfigEntries(hass); mockAreaRegistry(hass, AREAS); mockFloorRegistry(hass, FLOORS); mockLabelRegistry(hass, LABELS); mockHassioSupervisor(hass); hass.mockWS("auth/sign_path", (params) => params); hass.mockWS("media_player/browse_media", this._browseMedia); } public provideHass(el) { el.hass = this.hass; } public connectedCallback() { super.connectedCallback(); this.addEventListener("show-dialog", this._dialogManager); } public disconnectedCallback() { super.disconnectedCallback(); this.removeEventListener("show-dialog", this._dialogManager); } private _browseMedia = ({ media_content_id }) => { if (media_content_id === undefined) { return { title: "Media", media_class: "directory", media_content_type: "", media_content_id: "media-source://media_source/local/.", can_play: false, can_expand: true, children_media_class: "directory", thumbnail: null, children: [ { title: "Misc", media_class: "directory", media_content_type: "", media_content_id: "media-source://media_source/local/misc", can_play: false, can_expand: true, children_media_class: null, thumbnail: null, }, { title: "Movies", media_class: "directory", media_content_type: "", media_content_id: "media-source://media_source/local/movies", can_play: true, can_expand: true, children_media_class: "movie", thumbnail: null, }, { title: "Music", media_class: "album", media_content_type: "", media_content_id: "media-source://media_source/local/music", can_play: false, can_expand: true, children_media_class: "music", thumbnail: "/images/album_cover_2.jpg", }, ], }; } return { title: "Subfolder", media_class: "directory", media_content_type: "", media_content_id: "media-source://media_source/local/sub", can_play: false, can_expand: true, children_media_class: "directory", thumbnail: null, children: [ { title: "audio.mp3", media_class: "music", media_content_type: "audio/mpeg", media_content_id: "media-source://media_source/local/audio.mp3", can_play: true, can_expand: false, children_media_class: null, thumbnail: "/images/album_cover.jpg", }, { title: "image.jpg", media_class: "image", media_content_type: "image/jpeg", media_content_id: "media-source://media_source/local/image.jpg", can_play: true, can_expand: false, children_media_class: null, thumbnail: "https://brands.home-assistant.io/_/image/logo.png", }, { title: "movie.mp4", media_class: "movie", media_content_type: "image/jpeg", media_content_id: "media-source://media_source/local/movie.mp4", can_play: true, can_expand: false, children_media_class: null, thumbnail: null, }, ], }; }; private _dialogManager = (e) => { const { dialogTag, dialogImport, dialogParams, addHistory } = e.detail; showDialog( this, this.shadowRoot!, dialogTag, dialogParams, dialogImport, addHistory ); }; protected render(): TemplateResult { return html`
${SCHEMAS.map((info, idx) => { const data = this.data[idx]; return html` ${["light", "dark"].map((slot) => Object.entries(info.input).map( ([key, value]) => html` ${value?.name || key} ${value?.description} ` ) )} `; })} `; } private _handleValueChanged(ev) { const idx = ev.target.sampleIdx; this.data[idx] = { ...this.data[idx], [ev.target.key]: ev.detail.value, }; this.requestUpdate(); } private _handleOptionChange(ev) { this[`_${ev.target.name}`] = ev.target.checked; } static styles = css` .options { max-width: 800px; margin: 16px auto; } .options ha-formfield { margin-right: 16px; } `; } declare global { interface HTMLElementTagNameMap { "demo-components-ha-selector": DemoHaSelector; } }