mirror of
https://github.com/home-assistant/frontend.git
synced 2025-12-23 00:17:27 +00:00
Compare commits
14 Commits
auto-jsdoc
...
wa-dialog-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
248cb4ce73 | ||
|
|
6ff3b9f761 | ||
|
|
9026009842 | ||
|
|
54398a4784 | ||
|
|
fa3cc970ec | ||
|
|
1cf0560003 | ||
|
|
2a4ac15987 | ||
|
|
f264eebe49 | ||
|
|
dae27e091f | ||
|
|
7ca681e417 | ||
|
|
1adfe63322 | ||
|
|
119a505a0d | ||
|
|
1f8403f6c1 | ||
|
|
7dd7309a47 |
@@ -218,7 +218,7 @@
|
|||||||
"ts-lit-plugin": "2.0.2",
|
"ts-lit-plugin": "2.0.2",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"typescript-eslint": "8.49.0",
|
"typescript-eslint": "8.49.0",
|
||||||
"vite-tsconfig-paths": "5.1.4",
|
"vite-tsconfig-paths": "6.0.1",
|
||||||
"vitest": "4.0.15",
|
"vitest": "4.0.15",
|
||||||
"webpack-stats-plugin": "1.1.3",
|
"webpack-stats-plugin": "1.1.3",
|
||||||
"webpackbar": "7.0.0",
|
"webpackbar": "7.0.0",
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ class HaDevicesPicker extends LitElement {
|
|||||||
(entityId) => html`
|
(entityId) => html`
|
||||||
<div>
|
<div>
|
||||||
<ha-device-picker
|
<ha-device-picker
|
||||||
allow-custom-entity
|
|
||||||
.curValue=${entityId}
|
.curValue=${entityId}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.deviceFilter=${this.deviceFilter}
|
.deviceFilter=${this.deviceFilter}
|
||||||
@@ -79,7 +78,6 @@ class HaDevicesPicker extends LitElement {
|
|||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<ha-device-picker
|
<ha-device-picker
|
||||||
allow-custom-entity
|
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.deviceFilter=${this.deviceFilter}
|
.deviceFilter=${this.deviceFilter}
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ class HaEntitiesPicker extends LitElement {
|
|||||||
(entityId) => html`
|
(entityId) => html`
|
||||||
<div class="entity">
|
<div class="entity">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
allow-custom-entity
|
|
||||||
.curValue=${entityId}
|
.curValue=${entityId}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.includeDomains=${this.includeDomains}
|
.includeDomains=${this.includeDomains}
|
||||||
@@ -129,7 +128,6 @@ class HaEntitiesPicker extends LitElement {
|
|||||||
</ha-sortable>
|
</ha-sortable>
|
||||||
<div>
|
<div>
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
allow-custom-entity
|
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.includeDomains=${this.includeDomains}
|
.includeDomains=${this.includeDomains}
|
||||||
.excludeDomains=${this.excludeDomains}
|
.excludeDomains=${this.excludeDomains}
|
||||||
|
|||||||
@@ -277,12 +277,13 @@ export class HaEntityPicker extends LitElement {
|
|||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.autofocus=${this.autofocus}
|
.autofocus=${this.autofocus}
|
||||||
.allowCustomValue=${this.allowCustomEntity}
|
.allowCustomValue=${this.allowCustomEntity}
|
||||||
|
.required=${this.required}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
|
.placeholder=${placeholder}
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
|
.value=${this.addButton ? undefined : this.value}
|
||||||
.searchLabel=${this.searchLabel}
|
.searchLabel=${this.searchLabel}
|
||||||
.notFoundLabel=${this._notFoundLabel}
|
.notFoundLabel=${this._notFoundLabel}
|
||||||
.placeholder=${placeholder}
|
|
||||||
.value=${this.addButton ? undefined : this.value}
|
|
||||||
.rowRenderer=${this._rowRenderer}
|
.rowRenderer=${this._rowRenderer}
|
||||||
.getItems=${this._getItems}
|
.getItems=${this._getItems}
|
||||||
.getAdditionalItems=${this._getAdditionalItems}
|
.getAdditionalItems=${this._getAdditionalItems}
|
||||||
@@ -290,6 +291,7 @@ export class HaEntityPicker extends LitElement {
|
|||||||
.searchFn=${this._searchFn}
|
.searchFn=${this._searchFn}
|
||||||
.valueRenderer=${this._valueRenderer}
|
.valueRenderer=${this._valueRenderer}
|
||||||
.searchKeys=${entityComboBoxKeys}
|
.searchKeys=${entityComboBoxKeys}
|
||||||
|
use-top-label
|
||||||
.addButtonLabel=${this.addButton
|
.addButtonLabel=${this.addButton
|
||||||
? this.hass.localize("ui.components.entity.entity-picker.add")
|
? this.hass.localize("ui.components.entity.entity-picker.add")
|
||||||
: undefined}
|
: undefined}
|
||||||
|
|||||||
@@ -471,14 +471,14 @@ export class HaStatisticPicker extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.autofocus=${this.autofocus}
|
.autofocus=${this.autofocus}
|
||||||
.allowCustomValue=${this.allowCustomEntity}
|
.allowCustomValue=${this.allowCustomEntity}
|
||||||
.label=${this.label}
|
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
|
.label=${this.label}
|
||||||
|
.placeholder=${placeholder}
|
||||||
|
.value=${this.value}
|
||||||
.notFoundLabel=${this._notFoundLabel}
|
.notFoundLabel=${this._notFoundLabel}
|
||||||
.emptyLabel=${this.hass.localize(
|
.emptyLabel=${this.hass.localize(
|
||||||
"ui.components.statistic-picker.no_statistics"
|
"ui.components.statistic-picker.no_statistics"
|
||||||
)}
|
)}
|
||||||
.placeholder=${placeholder}
|
|
||||||
.value=${this.value}
|
|
||||||
.rowRenderer=${this._rowRenderer}
|
.rowRenderer=${this._rowRenderer}
|
||||||
.getItems=${this._getItems}
|
.getItems=${this._getItems}
|
||||||
.getAdditionalItems=${this._getAdditionalItems}
|
.getAdditionalItems=${this._getAdditionalItems}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
import type { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
|
import type { RenderItemFunction } from "@lit-labs/virtualizer/virtualize";
|
||||||
import { html, LitElement, nothing } from "lit";
|
import { html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { stringCompare } from "../common/string/compare";
|
|
||||||
import type { HassioAddonInfo } from "../data/hassio/addon";
|
|
||||||
import { fetchHassioAddonsInfo } from "../data/hassio/addon";
|
import { fetchHassioAddonsInfo } from "../data/hassio/addon";
|
||||||
import type { HomeAssistant, ValueChangedEvent } from "../types";
|
import type { HomeAssistant, ValueChangedEvent } from "../types";
|
||||||
import "./ha-alert";
|
import "./ha-alert";
|
||||||
import "./ha-combo-box";
|
|
||||||
import type { HaComboBox } from "./ha-combo-box";
|
|
||||||
import "./ha-combo-box-item";
|
import "./ha-combo-box-item";
|
||||||
|
import "./ha-generic-picker";
|
||||||
|
import type { HaGenericPicker } from "./ha-generic-picker";
|
||||||
|
import type { PickerComboBoxItem } from "./ha-picker-combo-box";
|
||||||
|
|
||||||
const rowRenderer: ComboBoxLitRenderer<HassioAddonInfo> = (item) => html`
|
const SEARCH_KEYS = [
|
||||||
|
{ name: "primary", weight: 10 },
|
||||||
|
{ name: "secondary", weight: 8 },
|
||||||
|
{ name: "search_labels.description", weight: 6 },
|
||||||
|
{ name: "search_labels.repository", weight: 5 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const rowRenderer: RenderItemFunction<PickerComboBoxItem> = (item) => html`
|
||||||
<ha-combo-box-item type="button">
|
<ha-combo-box-item type="button">
|
||||||
<span slot="headline">${item.name}</span>
|
<span slot="headline">${item.primary}</span>
|
||||||
<span slot="supporting-text">${item.slug}</span>
|
<span slot="supporting-text">${item.secondary}</span>
|
||||||
${item.icon
|
${item.icon
|
||||||
? html`
|
? html` <img alt="" slot="start" .src=${item.icon} /> `
|
||||||
<img
|
|
||||||
alt=""
|
|
||||||
slot="start"
|
|
||||||
.src="/api/hassio/addons/${item.slug}/icon"
|
|
||||||
/>
|
|
||||||
`
|
|
||||||
: nothing}
|
: nothing}
|
||||||
</ha-combo-box-item>
|
</ha-combo-box-item>
|
||||||
`;
|
`;
|
||||||
@@ -38,22 +38,22 @@ class HaAddonPicker extends LitElement {
|
|||||||
|
|
||||||
@property() public helper?: string;
|
@property() public helper?: string;
|
||||||
|
|
||||||
@state() private _addons?: HassioAddonInfo[];
|
@state() private _addons?: PickerComboBoxItem[];
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@property({ type: Boolean }) public required = false;
|
@property({ type: Boolean }) public required = false;
|
||||||
|
|
||||||
@query("ha-combo-box") private _comboBox!: HaComboBox;
|
@query("ha-generic-picker") private _genericPicker!: HaGenericPicker;
|
||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
public open() {
|
public open() {
|
||||||
this._comboBox?.open();
|
this._genericPicker?.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
public focus() {
|
public focus() {
|
||||||
this._comboBox?.focus();
|
this._genericPicker?.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated() {
|
protected firstUpdated() {
|
||||||
@@ -61,29 +61,34 @@ class HaAddonPicker extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
|
const label =
|
||||||
|
this.label === undefined && this.hass
|
||||||
|
? this.hass.localize("ui.components.addon-picker.addon")
|
||||||
|
: this.label;
|
||||||
|
|
||||||
if (this._error) {
|
if (this._error) {
|
||||||
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
|
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
|
||||||
}
|
}
|
||||||
if (!this._addons) {
|
if (!this._addons) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-combo-box
|
<ha-generic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.label=${this.label === undefined && this.hass
|
.autofocus=${this.autofocus}
|
||||||
? this.hass.localize("ui.components.addon-picker.addon")
|
.label=${label}
|
||||||
: this.label}
|
.valueRenderer=${this._valueRenderer}
|
||||||
.value=${this._value}
|
|
||||||
.required=${this.required}
|
|
||||||
.disabled=${this.disabled}
|
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.renderer=${rowRenderer}
|
.disabled=${this.disabled}
|
||||||
.items=${this._addons}
|
.required=${this.required}
|
||||||
item-value-path="slug"
|
.value=${this.value}
|
||||||
item-id-path="slug"
|
.getItems=${this._getItems}
|
||||||
item-label-path="name"
|
.searchKeys=${SEARCH_KEYS}
|
||||||
|
.rowRenderer=${rowRenderer}
|
||||||
@value-changed=${this._addonChanged}
|
@value-changed=${this._addonChanged}
|
||||||
></ha-combo-box>
|
>
|
||||||
|
</ha-generic-picker>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,9 +98,19 @@ class HaAddonPicker extends LitElement {
|
|||||||
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
|
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
|
||||||
this._addons = addonsInfo.addons
|
this._addons = addonsInfo.addons
|
||||||
.filter((addon) => addon.version)
|
.filter((addon) => addon.version)
|
||||||
.sort((a, b) =>
|
.map((addon) => ({
|
||||||
stringCompare(a.name, b.name, this.hass.locale.language)
|
id: addon.slug,
|
||||||
);
|
primary: addon.name,
|
||||||
|
secondary: addon.slug,
|
||||||
|
icon: addon.icon
|
||||||
|
? `/api/hassio/addons/${addon.slug}/icon`
|
||||||
|
: undefined,
|
||||||
|
search_labels: {
|
||||||
|
description: addon.description || null,
|
||||||
|
repository: addon.repository || null,
|
||||||
|
},
|
||||||
|
sorting_label: [addon.name, addon.slug].filter(Boolean).join("_"),
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
this._error = this.hass.localize(
|
this._error = this.hass.localize(
|
||||||
"ui.components.addon-picker.error.no_supervisor"
|
"ui.components.addon-picker.error.no_supervisor"
|
||||||
@@ -108,6 +123,8 @@ class HaAddonPicker extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _getItems = () => this._addons!;
|
||||||
|
|
||||||
private get _value() {
|
private get _value() {
|
||||||
return this.value || "";
|
return this.value || "";
|
||||||
}
|
}
|
||||||
@@ -128,6 +145,17 @@ class HaAddonPicker extends LitElement {
|
|||||||
fireEvent(this, "change");
|
fireEvent(this, "change");
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _valueRenderer = (itemId: string) => {
|
||||||
|
const item = this._addons!.find((addon) => addon.id === itemId);
|
||||||
|
return html`${item?.icon
|
||||||
|
? html`<img
|
||||||
|
slot="start"
|
||||||
|
alt=${item.primary ?? "Unknown"}
|
||||||
|
.src=${item.icon}
|
||||||
|
/>`
|
||||||
|
: nothing}<span slot="headline">${item?.primary || "Unknown"}</span>`;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -51,9 +51,6 @@ export class HaAreaPicker extends LitElement {
|
|||||||
@property({ type: Boolean, attribute: "no-add" })
|
@property({ type: Boolean, attribute: "no-add" })
|
||||||
public noAdd = false;
|
public noAdd = false;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "show-label" })
|
|
||||||
public showLabel = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show only areas with entities from specific domains.
|
* Show only areas with entities from specific domains.
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
@@ -366,16 +363,19 @@ export class HaAreaPicker extends LitElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const placeholder =
|
const baseLabel =
|
||||||
this.placeholder ?? this.hass.localize("ui.components.area-picker.area");
|
this.label ?? this.hass.localize("ui.components.area-picker.area");
|
||||||
const valueRenderer = this._computeValueRenderer(this.hass.areas);
|
const valueRenderer = this._computeValueRenderer(this.hass.areas);
|
||||||
|
|
||||||
let showLabel = this.showLabel;
|
// Only show label if there's no floor
|
||||||
if (this.value) {
|
let label: string | undefined = baseLabel;
|
||||||
|
if (this.value && baseLabel) {
|
||||||
const area = this.hass.areas[this.value];
|
const area = this.hass.areas[this.value];
|
||||||
if (area) {
|
if (area) {
|
||||||
const { floor } = getAreaContext(area, this.hass.floors);
|
const { floor } = getAreaContext(area, this.hass.floors);
|
||||||
showLabel = !floor && this.showLabel;
|
if (floor) {
|
||||||
|
label = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,14 +383,12 @@ export class HaAreaPicker extends LitElement {
|
|||||||
<ha-generic-picker
|
<ha-generic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.autofocus=${this.autofocus}
|
.autofocus=${this.autofocus}
|
||||||
.label=${this.label}
|
.label=${label}
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.notFoundLabel=${this._notFoundLabel}
|
.notFoundLabel=${this._notFoundLabel}
|
||||||
.emptyLabel=${this.hass.localize("ui.components.area-picker.no_areas")}
|
.emptyLabel=${this.hass.localize("ui.components.area-picker.no_areas")}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
.placeholder=${placeholder}
|
|
||||||
.showLabel=${showLabel}
|
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
.getItems=${this._getItems}
|
.getItems=${this._getItems}
|
||||||
.getAdditionalItems=${this._getAdditionalItems}
|
.getAdditionalItems=${this._getAdditionalItems}
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
import { mdiInvertColorsOff, mdiPalette } from "@mdi/js";
|
import { mdiInvertColorsOff, mdiPalette } from "@mdi/js";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { html, LitElement } from "lit";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { styleMap } from "lit/directives/style-map";
|
import { styleMap } from "lit/directives/style-map";
|
||||||
import { computeCssColor, THEME_COLORS } from "../common/color/compute-color";
|
import { computeCssColor, THEME_COLORS } from "../common/color/compute-color";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { stopPropagation } from "../common/dom/stop_propagation";
|
|
||||||
import type { LocalizeKeys } from "../common/translations/localize";
|
import type { LocalizeKeys } from "../common/translations/localize";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import "./ha-list-item";
|
import "./ha-generic-picker";
|
||||||
import "./ha-md-divider";
|
import type { PickerComboBoxItem } from "./ha-picker-combo-box";
|
||||||
import "./ha-select";
|
import type { PickerValueRenderer } from "./ha-picker-field";
|
||||||
import type { HaSelect } from "./ha-select";
|
|
||||||
|
|
||||||
@customElement("ha-color-picker")
|
@customElement("ha-color-picker")
|
||||||
export class HaColorPicker extends LitElement {
|
export class HaColorPicker extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
|
|
||||||
@property() public helper?: string;
|
@property() public helper?: string;
|
||||||
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property() public value?: string;
|
@property() public value?: string;
|
||||||
|
|
||||||
@property({ type: String, attribute: "default_color" })
|
@property({ type: String, attribute: "default_color" })
|
||||||
@@ -33,137 +31,178 @@ export class HaColorPicker extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@query("ha-select") private _select?: HaSelect;
|
@property({ type: Boolean }) public required = false;
|
||||||
|
|
||||||
connectedCallback(): void {
|
|
||||||
super.connectedCallback();
|
|
||||||
// Refresh layout options when the field is connected to the DOM to ensure current value displayed
|
|
||||||
this._select?.layoutOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _valueSelected(ev) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
if (!this.isConnected) return;
|
|
||||||
const value = ev.target.value;
|
|
||||||
this.value = value === this.defaultColor ? undefined : value;
|
|
||||||
fireEvent(this, "value-changed", {
|
|
||||||
value: this.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const value = this.value || this.defaultColor || "";
|
const effectiveValue = this.value ?? this.defaultColor ?? "";
|
||||||
|
|
||||||
const isCustom = !(
|
|
||||||
THEME_COLORS.has(value) ||
|
|
||||||
value === "none" ||
|
|
||||||
value === "state"
|
|
||||||
);
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-select
|
<ha-generic-picker
|
||||||
.icon=${Boolean(value)}
|
.hass=${this.hass}
|
||||||
.label=${this.label}
|
|
||||||
.value=${value}
|
|
||||||
.helper=${this.helper}
|
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@closed=${stopPropagation}
|
.required=${this.required}
|
||||||
@selected=${this._valueSelected}
|
.hideClearIcon=${!this.value && !!this.defaultColor}
|
||||||
fixedMenuPosition
|
.label=${this.label}
|
||||||
naturalMenuWidth
|
.helper=${this.helper}
|
||||||
.clearable=${!this.defaultColor}
|
.value=${effectiveValue}
|
||||||
|
.getItems=${this._getItems}
|
||||||
|
.rowRenderer=${this._rowRenderer}
|
||||||
|
.valueRenderer=${this._valueRenderer}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
>
|
>
|
||||||
${value
|
</ha-generic-picker>
|
||||||
? html`
|
|
||||||
<span slot="icon">
|
|
||||||
${value === "none"
|
|
||||||
? html`
|
|
||||||
<ha-svg-icon path=${mdiInvertColorsOff}></ha-svg-icon>
|
|
||||||
`
|
|
||||||
: value === "state"
|
|
||||||
? html`<ha-svg-icon path=${mdiPalette}></ha-svg-icon>`
|
|
||||||
: this._renderColorCircle(value || "grey")}
|
|
||||||
</span>
|
|
||||||
`
|
|
||||||
: nothing}
|
|
||||||
${this.includeNone
|
|
||||||
? html`
|
|
||||||
<ha-list-item value="none" graphic="icon">
|
|
||||||
${this.hass.localize("ui.components.color-picker.none")}
|
|
||||||
${this.defaultColor === "none"
|
|
||||||
? ` (${this.hass.localize("ui.components.color-picker.default")})`
|
|
||||||
: nothing}
|
|
||||||
<ha-svg-icon
|
|
||||||
slot="graphic"
|
|
||||||
path=${mdiInvertColorsOff}
|
|
||||||
></ha-svg-icon>
|
|
||||||
</ha-list-item>
|
|
||||||
`
|
|
||||||
: nothing}
|
|
||||||
${this.includeState
|
|
||||||
? html`
|
|
||||||
<ha-list-item value="state" graphic="icon">
|
|
||||||
${this.hass.localize("ui.components.color-picker.state")}
|
|
||||||
${this.defaultColor === "state"
|
|
||||||
? ` (${this.hass.localize("ui.components.color-picker.default")})`
|
|
||||||
: nothing}
|
|
||||||
<ha-svg-icon slot="graphic" path=${mdiPalette}></ha-svg-icon>
|
|
||||||
</ha-list-item>
|
|
||||||
`
|
|
||||||
: nothing}
|
|
||||||
${this.includeState || this.includeNone
|
|
||||||
? html`<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>`
|
|
||||||
: nothing}
|
|
||||||
${Array.from(THEME_COLORS).map(
|
|
||||||
(color) => html`
|
|
||||||
<ha-list-item .value=${color} graphic="icon">
|
|
||||||
${this.hass.localize(
|
|
||||||
`ui.components.color-picker.colors.${color}` as LocalizeKeys
|
|
||||||
) || color}
|
|
||||||
${this.defaultColor === color
|
|
||||||
? ` (${this.hass.localize("ui.components.color-picker.default")})`
|
|
||||||
: nothing}
|
|
||||||
<span slot="graphic">${this._renderColorCircle(color)}</span>
|
|
||||||
</ha-list-item>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
${isCustom
|
|
||||||
? html`
|
|
||||||
<ha-list-item .value=${value} graphic="icon">
|
|
||||||
${value}
|
|
||||||
<span slot="graphic">${this._renderColorCircle(value)}</span>
|
|
||||||
</ha-list-item>
|
|
||||||
`
|
|
||||||
: nothing}
|
|
||||||
</ha-select>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _getItems = () =>
|
||||||
|
this._getColors(
|
||||||
|
this.includeNone,
|
||||||
|
this.includeState,
|
||||||
|
this.defaultColor,
|
||||||
|
this.value
|
||||||
|
);
|
||||||
|
|
||||||
|
private _getColors = (
|
||||||
|
includeNone: boolean,
|
||||||
|
includeState: boolean,
|
||||||
|
defaultColor: string | undefined,
|
||||||
|
currentValue: string | undefined
|
||||||
|
): PickerComboBoxItem[] => {
|
||||||
|
const items: PickerComboBoxItem[] = [];
|
||||||
|
|
||||||
|
const defaultSuffix = this.hass.localize(
|
||||||
|
"ui.components.color-picker.default"
|
||||||
|
);
|
||||||
|
|
||||||
|
const addDefaultSuffix = (label: string, isDefault: boolean) =>
|
||||||
|
isDefault && defaultSuffix ? `${label} (${defaultSuffix})` : label;
|
||||||
|
|
||||||
|
if (includeNone) {
|
||||||
|
const noneLabel =
|
||||||
|
this.hass.localize("ui.components.color-picker.none") || "None";
|
||||||
|
items.push({
|
||||||
|
id: "none",
|
||||||
|
primary: addDefaultSuffix(noneLabel, defaultColor === "none"),
|
||||||
|
icon_path: mdiInvertColorsOff,
|
||||||
|
sorting_label: noneLabel,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeState) {
|
||||||
|
const stateLabel =
|
||||||
|
this.hass.localize("ui.components.color-picker.state") || "State";
|
||||||
|
items.push({
|
||||||
|
id: "state",
|
||||||
|
primary: addDefaultSuffix(stateLabel, defaultColor === "state"),
|
||||||
|
icon_path: mdiPalette,
|
||||||
|
sorting_label: stateLabel,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.from(THEME_COLORS).forEach((color) => {
|
||||||
|
const themeLabel =
|
||||||
|
this.hass.localize(
|
||||||
|
`ui.components.color-picker.colors.${color}` as LocalizeKeys
|
||||||
|
) || color;
|
||||||
|
items.push({
|
||||||
|
id: color,
|
||||||
|
primary: addDefaultSuffix(themeLabel, defaultColor === color),
|
||||||
|
sorting_label: themeLabel,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const isSpecial =
|
||||||
|
currentValue === "none" ||
|
||||||
|
currentValue === "state" ||
|
||||||
|
THEME_COLORS.has(currentValue || "");
|
||||||
|
|
||||||
|
const hasValue = currentValue && currentValue.length > 0;
|
||||||
|
|
||||||
|
if (hasValue && !isSpecial) {
|
||||||
|
items.push({
|
||||||
|
id: currentValue!,
|
||||||
|
primary: currentValue!,
|
||||||
|
sorting_label: currentValue!,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
};
|
||||||
|
|
||||||
|
private _rowRenderer: (
|
||||||
|
item: PickerComboBoxItem,
|
||||||
|
index?: number
|
||||||
|
) => ReturnType<typeof html> = (item) => html`
|
||||||
|
<ha-combo-box-item type="button" compact>
|
||||||
|
${item.id === "none"
|
||||||
|
? html`<ha-svg-icon
|
||||||
|
slot="start"
|
||||||
|
.path=${mdiInvertColorsOff}
|
||||||
|
></ha-svg-icon>`
|
||||||
|
: item.id === "state"
|
||||||
|
? html`<ha-svg-icon slot="start" .path=${mdiPalette}></ha-svg-icon>`
|
||||||
|
: html`<span slot="start">
|
||||||
|
${this._renderColorCircle(item.id)}
|
||||||
|
</span>`}
|
||||||
|
<span slot="headline">${item.primary}</span>
|
||||||
|
</ha-combo-box-item>
|
||||||
|
`;
|
||||||
|
|
||||||
|
private _valueRenderer: PickerValueRenderer = (value: string) => {
|
||||||
|
if (value === "none") {
|
||||||
|
return html`
|
||||||
|
<ha-svg-icon slot="start" .path=${mdiInvertColorsOff}></ha-svg-icon>
|
||||||
|
<span slot="headline">
|
||||||
|
${this.hass.localize("ui.components.color-picker.none")}
|
||||||
|
</span>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
if (value === "state") {
|
||||||
|
return html`
|
||||||
|
<ha-svg-icon slot="start" .path=${mdiPalette}></ha-svg-icon>
|
||||||
|
<span slot="headline">
|
||||||
|
${this.hass.localize("ui.components.color-picker.state")}
|
||||||
|
</span>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<span slot="start">${this._renderColorCircle(value)}</span>
|
||||||
|
<span slot="headline">
|
||||||
|
${this.hass.localize(
|
||||||
|
`ui.components.color-picker.colors.${value}` as LocalizeKeys
|
||||||
|
) || value}
|
||||||
|
</span>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
private _renderColorCircle(color: string) {
|
private _renderColorCircle(color: string) {
|
||||||
return html`
|
return html`
|
||||||
<span
|
<span
|
||||||
class="circle-color"
|
|
||||||
style=${styleMap({
|
style=${styleMap({
|
||||||
"--circle-color": computeCssColor(color),
|
"--circle-color": computeCssColor(color),
|
||||||
|
display: "block",
|
||||||
|
"background-color": "var(--circle-color, var(--divider-color))",
|
||||||
|
border: "1px solid var(--outline-color)",
|
||||||
|
"border-radius": "var(--ha-border-radius-pill)",
|
||||||
|
width: "20px",
|
||||||
|
height: "20px",
|
||||||
|
"box-sizing": "border-box",
|
||||||
})}
|
})}
|
||||||
></span>
|
></span>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = css`
|
private _valueChanged(ev: CustomEvent<{ value?: string }>) {
|
||||||
.circle-color {
|
ev.stopPropagation();
|
||||||
display: block;
|
const selected = ev.detail.value;
|
||||||
background-color: var(--circle-color, var(--divider-color));
|
const normalized =
|
||||||
border: 1px solid var(--outline-color);
|
selected && selected === this.defaultColor
|
||||||
border-radius: var(--ha-border-radius-pill);
|
? undefined
|
||||||
width: 20px;
|
: (selected ?? undefined);
|
||||||
height: 20px;
|
this.value = normalized;
|
||||||
box-sizing: border-box;
|
fireEvent(this, "value-changed", { value: this.value });
|
||||||
}
|
}
|
||||||
ha-select {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -57,10 +57,9 @@ class HaConfigEntryPicker extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-generic-picker
|
<ha-generic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.placeholder=${this.label === undefined && this.hass
|
.label=${this.label === undefined && this.hass
|
||||||
? this.hass.localize("ui.components.config-entry-picker.config_entry")
|
? this.hass.localize("ui.components.config-entry-picker.config_entry")
|
||||||
: this.label}
|
: this.label}
|
||||||
show-label
|
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
|
|||||||
@@ -389,14 +389,14 @@ export class HaFloorPicker extends LitElement {
|
|||||||
<ha-generic-picker
|
<ha-generic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.autofocus=${this.autofocus}
|
.autofocus=${this.autofocus}
|
||||||
|
.disabled=${this.disabled}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.disabled=${this.disabled}
|
.placeholder=${placeholder}
|
||||||
.notFoundLabel=${this._notFoundLabel}
|
.notFoundLabel=${this._notFoundLabel}
|
||||||
.emptyLabel=${this.hass.localize(
|
.emptyLabel=${this.hass.localize(
|
||||||
"ui.components.floor-picker.no_floors"
|
"ui.components.floor-picker.no_floors"
|
||||||
)}
|
)}
|
||||||
.placeholder=${placeholder}
|
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
.getItems=${this._getItems}
|
.getItems=${this._getItems}
|
||||||
.getAdditionalItems=${this._getAdditionalItems}
|
.getAdditionalItems=${this._getAdditionalItems}
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ import { ifDefined } from "lit/directives/if-defined";
|
|||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { tinykeys } from "tinykeys";
|
import { tinykeys } from "tinykeys";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { PickerMixin } from "../mixins/picker-mixin";
|
||||||
import type { FuseWeightedKey } from "../resources/fuseMultiTerm";
|
import type { FuseWeightedKey } from "../resources/fuseMultiTerm";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
import { isIosApp } from "../util/is_ios";
|
||||||
import "./ha-bottom-sheet";
|
import "./ha-bottom-sheet";
|
||||||
import "./ha-button";
|
import "./ha-button";
|
||||||
import "./ha-combo-box-item";
|
import "./ha-combo-box-item";
|
||||||
@@ -20,39 +22,18 @@ import type {
|
|||||||
PickerComboBoxSearchFn,
|
PickerComboBoxSearchFn,
|
||||||
} from "./ha-picker-combo-box";
|
} from "./ha-picker-combo-box";
|
||||||
import "./ha-picker-field";
|
import "./ha-picker-field";
|
||||||
import type { PickerValueRenderer } from "./ha-picker-field";
|
|
||||||
import "./ha-svg-icon";
|
import "./ha-svg-icon";
|
||||||
|
|
||||||
@customElement("ha-generic-picker")
|
@customElement("ha-generic-picker")
|
||||||
export class HaGenericPicker extends LitElement {
|
export class HaGenericPicker extends PickerMixin(LitElement) {
|
||||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public required = false;
|
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "allow-custom-value" })
|
@property({ type: Boolean, attribute: "allow-custom-value" })
|
||||||
public allowCustomValue;
|
public allowCustomValue;
|
||||||
|
|
||||||
@property() public value?: string;
|
|
||||||
|
|
||||||
@property() public icon?: string;
|
|
||||||
|
|
||||||
@property() public label?: string;
|
|
||||||
|
|
||||||
@property() public helper?: string;
|
|
||||||
|
|
||||||
@property() public placeholder?: string;
|
|
||||||
|
|
||||||
@property({ type: String, attribute: "search-label" })
|
@property({ type: String, attribute: "search-label" })
|
||||||
public searchLabel?: string;
|
public searchLabel?: string;
|
||||||
|
|
||||||
@property({ attribute: "hide-clear-icon", type: Boolean })
|
|
||||||
public hideClearIcon = false;
|
|
||||||
|
|
||||||
@property({ attribute: "show-label", type: Boolean })
|
|
||||||
public showLabel = false;
|
|
||||||
|
|
||||||
/** To prevent lags, getItems needs to be memoized */
|
/** To prevent lags, getItems needs to be memoized */
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public getItems!: (
|
public getItems!: (
|
||||||
@@ -66,9 +47,6 @@ export class HaGenericPicker extends LitElement {
|
|||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public rowRenderer?: RenderItemFunction<PickerComboBoxItem>;
|
public rowRenderer?: RenderItemFunction<PickerComboBoxItem>;
|
||||||
|
|
||||||
@property({ attribute: false })
|
|
||||||
public valueRenderer?: PickerValueRenderer;
|
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public searchFn?: PickerComboBoxSearchFn<PickerComboBoxItem>;
|
public searchFn?: PickerComboBoxSearchFn<PickerComboBoxItem>;
|
||||||
|
|
||||||
@@ -118,7 +96,11 @@ export class HaGenericPicker extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: "selected-section" }) public selectedSection?: string;
|
@property({ attribute: "selected-section" }) public selectedSection?: string;
|
||||||
|
|
||||||
@property({ attribute: "unknown-item-text" }) public unknownItemText?: string;
|
@property({ type: Boolean, attribute: "use-top-label" })
|
||||||
|
public useTopLabel = false;
|
||||||
|
|
||||||
|
@property({ attribute: "custom-value-label" })
|
||||||
|
public customValueLabel?: string;
|
||||||
|
|
||||||
@query(".container") private _containerElement?: HTMLDivElement;
|
@query(".container") private _containerElement?: HTMLDivElement;
|
||||||
|
|
||||||
@@ -149,11 +131,13 @@ export class HaGenericPicker extends LitElement {
|
|||||||
private _unsubscribeTinyKeys?: () => void;
|
private _unsubscribeTinyKeys?: () => void;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`
|
// Only show label if it's not a top label and there is a value.
|
||||||
${this.label
|
const label = this.useTopLabel && this.value ? undefined : this.label;
|
||||||
? html`<label ?disabled=${this.disabled}>${this.label}</label>`
|
|
||||||
: nothing}
|
return html`<div class="container">
|
||||||
<div class="container">
|
${this.useTopLabel && this.label
|
||||||
|
? html`<label ?disabled=${this.disabled}>${this.label}</label>`
|
||||||
|
: nothing}
|
||||||
<div id="picker">
|
<div id="picker">
|
||||||
<slot name="field">
|
<slot name="field">
|
||||||
${this.addButtonLabel && !this.value
|
${this.addButtonLabel && !this.value
|
||||||
@@ -173,14 +157,20 @@ export class HaGenericPicker extends LitElement {
|
|||||||
type="button"
|
type="button"
|
||||||
class=${this._opened ? "opened" : ""}
|
class=${this._opened ? "opened" : ""}
|
||||||
compact
|
compact
|
||||||
.unknown=${this._unknownValue(this.value, this.getItems())}
|
.unknown=${this._unknownValue(
|
||||||
|
this.allowCustomValue,
|
||||||
|
this.value,
|
||||||
|
this.getItems()
|
||||||
|
)}
|
||||||
.unknownItemText=${this.unknownItemText}
|
.unknownItemText=${this.unknownItemText}
|
||||||
aria-label=${ifDefined(this.label)}
|
aria-label=${ifDefined(this.label)}
|
||||||
@click=${this.open}
|
@click=${this.open}
|
||||||
@clear=${this._clear}
|
@clear=${this._clear}
|
||||||
.icon=${this.icon}
|
.icon=${this.icon}
|
||||||
.showLabel=${this.showLabel}
|
.image=${this.image}
|
||||||
|
.label=${label}
|
||||||
.placeholder=${this.placeholder}
|
.placeholder=${this.placeholder}
|
||||||
|
.helper=${this.helper}
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
.valueRenderer=${this.valueRenderer}
|
.valueRenderer=${this.valueRenderer}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
@@ -188,6 +178,7 @@ export class HaGenericPicker extends LitElement {
|
|||||||
.invalid=${this.invalid}
|
.invalid=${this.invalid}
|
||||||
.hideClearIcon=${this.hideClearIcon}
|
.hideClearIcon=${this.hideClearIcon}
|
||||||
>
|
>
|
||||||
|
<slot name="start"></slot>
|
||||||
</ha-picker-field>`}
|
</ha-picker-field>`}
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -226,8 +217,7 @@ export class HaGenericPicker extends LitElement {
|
|||||||
</ha-bottom-sheet>`
|
</ha-bottom-sheet>`
|
||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${this._renderHelper()}
|
${this._renderHelper()}`;
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderComboBox(dialogMode = false) {
|
private _renderComboBox(dialogMode = false) {
|
||||||
@@ -236,6 +226,7 @@ export class HaGenericPicker extends LitElement {
|
|||||||
}
|
}
|
||||||
return html`
|
return html`
|
||||||
<ha-picker-combo-box
|
<ha-picker-combo-box
|
||||||
|
id="combo-box"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.allowCustomValue=${this.allowCustomValue}
|
.allowCustomValue=${this.allowCustomValue}
|
||||||
.label=${this.searchLabel}
|
.label=${this.searchLabel}
|
||||||
@@ -252,13 +243,24 @@ export class HaGenericPicker extends LitElement {
|
|||||||
.sectionTitleFunction=${this.sectionTitleFunction}
|
.sectionTitleFunction=${this.sectionTitleFunction}
|
||||||
.selectedSection=${this.selectedSection}
|
.selectedSection=${this.selectedSection}
|
||||||
.searchKeys=${this.searchKeys}
|
.searchKeys=${this.searchKeys}
|
||||||
|
.customValueLabel=${this.customValueLabel}
|
||||||
></ha-picker-combo-box>
|
></ha-picker-combo-box>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _unknownValue = memoizeOne(
|
private _unknownValue = memoizeOne(
|
||||||
(value?: string, items?: (PickerComboBoxItem | string)[]) => {
|
(
|
||||||
if (value === undefined || value === null || value === "" || !items) {
|
allowCustomValue: boolean,
|
||||||
|
value?: string,
|
||||||
|
items?: (PickerComboBoxItem | string)[]
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
allowCustomValue ||
|
||||||
|
value === undefined ||
|
||||||
|
value === null ||
|
||||||
|
value === "" ||
|
||||||
|
!items
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +286,15 @@ export class HaGenericPicker extends LitElement {
|
|||||||
private _dialogOpened = () => {
|
private _dialogOpened = () => {
|
||||||
this._opened = true;
|
this._opened = true;
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
|
if (this.hass && isIosApp(this.hass)) {
|
||||||
|
this.hass.auth.external!.fireMessage({
|
||||||
|
type: "focus_element",
|
||||||
|
payload: {
|
||||||
|
element_id: "combo-box",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._comboBox?.focus();
|
this._comboBox?.focus();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -310,7 +321,7 @@ export class HaGenericPicker extends LitElement {
|
|||||||
this._newValue = value;
|
this._newValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _clear(e) {
|
private _clear(e: CustomEvent) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this._setValue(undefined);
|
this._setValue(undefined);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ export class HaIconPicker extends LitElement {
|
|||||||
<ha-generic-picker
|
<ha-generic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
allow-custom-value
|
allow-custom-value
|
||||||
show-label
|
|
||||||
.getItems=${this._getIconPickerItems}
|
.getItems=${this._getIconPickerItems}
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@@ -122,7 +121,7 @@ export class HaIconPicker extends LitElement {
|
|||||||
.invalid=${this.invalid}
|
.invalid=${this.invalid}
|
||||||
.rowRenderer=${rowRenderer}
|
.rowRenderer=${rowRenderer}
|
||||||
.icon=${this._icon}
|
.icon=${this._icon}
|
||||||
.placeholder=${this.label}
|
.label=${this.label}
|
||||||
.value=${this._value}
|
.value=${this._value}
|
||||||
.searchFn=${this._filterIcons}
|
.searchFn=${this._filterIcons}
|
||||||
.notFoundLabel=${this.hass?.localize(
|
.notFoundLabel=${this.hass?.localize(
|
||||||
@@ -131,6 +130,7 @@ export class HaIconPicker extends LitElement {
|
|||||||
popover-placement="bottom-start"
|
popover-placement="bottom-start"
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
>
|
>
|
||||||
|
<slot name="start"></slot>
|
||||||
</ha-generic-picker>
|
</ha-generic-picker>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,11 @@ export class HaLanguagePicker extends LitElement {
|
|||||||
> `;
|
> `;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
|
const label =
|
||||||
|
this.label ??
|
||||||
|
(this.hass?.localize("ui.components.language-picker.language") ||
|
||||||
|
"Language");
|
||||||
|
|
||||||
const value =
|
const value =
|
||||||
this.value ??
|
this.value ??
|
||||||
(this.required && !this.disabled ? this._getItems()[0].id : this.value);
|
(this.required && !this.disabled ? this._getItems()[0].id : this.value);
|
||||||
@@ -129,10 +134,7 @@ export class HaLanguagePicker extends LitElement {
|
|||||||
.emptyLabel=${this.hass?.localize(
|
.emptyLabel=${this.hass?.localize(
|
||||||
"ui.components.language-picker.no_languages"
|
"ui.components.language-picker.no_languages"
|
||||||
) || "No languages available"}
|
) || "No languages available"}
|
||||||
.placeholder=${this.label ??
|
.label=${label}
|
||||||
(this.hass?.localize("ui.components.language-picker.language") ||
|
|
||||||
"Language")}
|
|
||||||
show-label
|
|
||||||
.value=${value}
|
.value=${value}
|
||||||
.valueRenderer=${this._valueRenderer}
|
.valueRenderer=${this._valueRenderer}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
|
|||||||
@@ -1,55 +1,17 @@
|
|||||||
import type { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
|
import { html, LitElement, nothing } from "lit";
|
||||||
import type { PropertyValues, TemplateResult } from "lit";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { titleCase } from "../common/string/title-case";
|
import { titleCase } from "../common/string/title-case";
|
||||||
import { fetchConfig } from "../data/lovelace/config/types";
|
import { fetchConfig } from "../data/lovelace/config/types";
|
||||||
import type { LovelaceViewRawConfig } from "../data/lovelace/config/view";
|
|
||||||
import { getPanelIcon, getPanelTitle } from "../data/panel";
|
import { getPanelIcon, getPanelTitle } from "../data/panel";
|
||||||
import type { HomeAssistant, PanelInfo, ValueChangedEvent } from "../types";
|
import type { HomeAssistant, ValueChangedEvent } from "../types";
|
||||||
import "./ha-combo-box";
|
import "./ha-generic-picker";
|
||||||
import type { HaComboBox } from "./ha-combo-box";
|
|
||||||
import "./ha-combo-box-item";
|
|
||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
|
import type { PickerComboBoxItem } from "./ha-picker-combo-box";
|
||||||
interface NavigationItem {
|
|
||||||
path: string;
|
|
||||||
icon: string;
|
|
||||||
title: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_ITEMS: NavigationItem[] = [];
|
|
||||||
|
|
||||||
const rowRenderer: ComboBoxLitRenderer<NavigationItem> = (item) => html`
|
|
||||||
<ha-combo-box-item type="button">
|
|
||||||
<ha-icon .icon=${item.icon} slot="start"></ha-icon>
|
|
||||||
<span slot="headline">${item.title || item.path}</span>
|
|
||||||
${item.title
|
|
||||||
? html`<span slot="supporting-text">${item.path}</span>`
|
|
||||||
: nothing}
|
|
||||||
</ha-combo-box-item>
|
|
||||||
`;
|
|
||||||
|
|
||||||
const createViewNavigationItem = (
|
|
||||||
prefix: string,
|
|
||||||
view: LovelaceViewRawConfig,
|
|
||||||
index: number
|
|
||||||
) => ({
|
|
||||||
path: `/${prefix}/${view.path ?? index}`,
|
|
||||||
icon: view.icon ?? "mdi:view-compact",
|
|
||||||
title: view.title ?? (view.path ? titleCase(view.path) : `${index}`),
|
|
||||||
});
|
|
||||||
|
|
||||||
const createPanelNavigationItem = (hass: HomeAssistant, panel: PanelInfo) => ({
|
|
||||||
path: `/${panel.url_path}`,
|
|
||||||
icon: getPanelIcon(panel) || "mdi:view-dashboard",
|
|
||||||
title: getPanelTitle(hass, panel) || "",
|
|
||||||
});
|
|
||||||
|
|
||||||
@customElement("ha-navigation-picker")
|
@customElement("ha-navigation-picker")
|
||||||
export class HaNavigationPicker extends LitElement {
|
export class HaNavigationPicker extends LitElement {
|
||||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
|
|
||||||
@@ -61,46 +23,51 @@ export class HaNavigationPicker extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean }) public required = false;
|
@property({ type: Boolean }) public required = false;
|
||||||
|
|
||||||
@state() private _opened = false;
|
@state() private _loading = true;
|
||||||
|
|
||||||
private navigationItemsLoaded = false;
|
protected firstUpdated() {
|
||||||
|
this._loadNavigationItems();
|
||||||
|
}
|
||||||
|
|
||||||
private navigationItems: NavigationItem[] = DEFAULT_ITEMS;
|
private _navigationItems: PickerComboBoxItem[] = [];
|
||||||
|
|
||||||
@query("ha-combo-box", true) private comboBox!: HaComboBox;
|
protected render() {
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
return html`
|
return html`
|
||||||
<ha-combo-box
|
<ha-generic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
item-value-path="path"
|
.value=${this._loading ? undefined : this.value}
|
||||||
item-label-path="path"
|
|
||||||
.value=${this._value}
|
|
||||||
allow-custom-value
|
allow-custom-value
|
||||||
.filteredItems=${this.navigationItems}
|
.placeholder=${this.label}
|
||||||
.label=${this.label}
|
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this._loading || this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
.renderer=${rowRenderer}
|
.getItems=${this._getItems}
|
||||||
@opened-changed=${this._openedChanged}
|
.valueRenderer=${this._valueRenderer}
|
||||||
|
.customValueLabel=${this.hass.localize(
|
||||||
|
"ui.components.navigation-picker.add_custom_path"
|
||||||
|
)}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
@filter-changed=${this._filterChanged}
|
|
||||||
>
|
>
|
||||||
</ha-combo-box>
|
</ha-generic-picker>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _openedChanged(ev: ValueChangedEvent<boolean>) {
|
private _valueRenderer = (itemId: string) => {
|
||||||
this._opened = ev.detail.value;
|
const item = this._navigationItems.find((navItem) => navItem.id === itemId);
|
||||||
if (this._opened && !this.navigationItemsLoaded) {
|
return html`
|
||||||
this._loadNavigationItems();
|
${item?.icon
|
||||||
}
|
? html`<ha-icon slot="start" .icon=${item.icon}></ha-icon>`
|
||||||
}
|
: nothing}
|
||||||
|
<span slot="headline">${item?.primary || itemId}</span>
|
||||||
|
${item?.primary
|
||||||
|
? html`<span slot="supporting-text">${itemId}</span>`
|
||||||
|
: nothing}
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
private _getItems = () => this._navigationItems;
|
||||||
|
|
||||||
private async _loadNavigationItems() {
|
private async _loadNavigationItems() {
|
||||||
this.navigationItemsLoaded = true;
|
|
||||||
|
|
||||||
const panels = Object.entries(this.hass!.panels).map(([id, panel]) => ({
|
const panels = Object.entries(this.hass!.panels).map(([id, panel]) => ({
|
||||||
id,
|
id,
|
||||||
...panel,
|
...panel,
|
||||||
@@ -124,27 +91,47 @@ export class HaNavigationPicker extends LitElement {
|
|||||||
|
|
||||||
const panelViewConfig = new Map(viewConfigs);
|
const panelViewConfig = new Map(viewConfigs);
|
||||||
|
|
||||||
this.navigationItems = [];
|
this._navigationItems = [];
|
||||||
|
|
||||||
for (const panel of panels) {
|
for (const panel of panels) {
|
||||||
this.navigationItems.push(createPanelNavigationItem(this.hass!, panel));
|
const path = `/${panel.url_path}`;
|
||||||
|
const panelTitle = getPanelTitle(this.hass, panel);
|
||||||
|
const primary = panelTitle || path;
|
||||||
|
this._navigationItems.push({
|
||||||
|
id: path,
|
||||||
|
primary,
|
||||||
|
secondary: panelTitle ? path : undefined,
|
||||||
|
icon: getPanelIcon(panel) || "mdi:view-dashboard",
|
||||||
|
sorting_label: [
|
||||||
|
primary.startsWith("/") ? `zzz${primary}` : primary,
|
||||||
|
path,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("_"),
|
||||||
|
});
|
||||||
|
|
||||||
const config = panelViewConfig.get(panel.id);
|
const config = panelViewConfig.get(panel.id);
|
||||||
|
|
||||||
if (!config || !("views" in config)) continue;
|
if (!config || !("views" in config)) continue;
|
||||||
|
|
||||||
config.views.forEach((view, index) =>
|
config.views.forEach((view, index) => {
|
||||||
this.navigationItems.push(
|
const viewPath = `/${panel.url_path}/${view.path ?? index}`;
|
||||||
createViewNavigationItem(panel.url_path, view, index)
|
const viewPrimary =
|
||||||
)
|
view.title ?? (view.path ? titleCase(view.path) : `${index}`);
|
||||||
);
|
this._navigationItems.push({
|
||||||
|
id: viewPath,
|
||||||
|
secondary: viewPath,
|
||||||
|
icon: view.icon ?? "mdi:view-compact",
|
||||||
|
primary: viewPrimary,
|
||||||
|
sorting_label: [
|
||||||
|
viewPrimary.startsWith("/") ? `zzz${viewPrimary}` : viewPrimary,
|
||||||
|
viewPath,
|
||||||
|
].join("_"),
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.comboBox.filteredItems = this.navigationItems;
|
this._loading = false;
|
||||||
}
|
|
||||||
|
|
||||||
protected shouldUpdate(changedProps: PropertyValues) {
|
|
||||||
return !this._opened || changedProps.has("_opened");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _valueChanged(ev: ValueChangedEvent<string>) {
|
private _valueChanged(ev: ValueChangedEvent<string>) {
|
||||||
@@ -152,61 +139,18 @@ export class HaNavigationPicker extends LitElement {
|
|||||||
this._setValue(ev.detail.value);
|
this._setValue(ev.detail.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setValue(value: string) {
|
private _setValue(value = "") {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
fireEvent(
|
fireEvent(
|
||||||
this,
|
this,
|
||||||
"value-changed",
|
"value-changed",
|
||||||
{ value: this._value },
|
{ value: this.value },
|
||||||
{
|
{
|
||||||
bubbles: false,
|
bubbles: false,
|
||||||
composed: false,
|
composed: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _filterChanged(ev: CustomEvent): void {
|
|
||||||
const filterString = ev.detail.value.toLowerCase();
|
|
||||||
const characterCount = filterString.length;
|
|
||||||
if (characterCount >= 2) {
|
|
||||||
const filteredItems: NavigationItem[] = [];
|
|
||||||
|
|
||||||
this.navigationItems.forEach((item) => {
|
|
||||||
if (
|
|
||||||
item.path.toLowerCase().includes(filterString) ||
|
|
||||||
item.title.toLowerCase().includes(filterString)
|
|
||||||
) {
|
|
||||||
filteredItems.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (filteredItems.length > 0) {
|
|
||||||
this.comboBox.filteredItems = filteredItems;
|
|
||||||
} else {
|
|
||||||
this.comboBox.filteredItems = [];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.comboBox.filteredItems = this.navigationItems;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _value() {
|
|
||||||
return this.value || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = css`
|
|
||||||
ha-icon,
|
|
||||||
ha-svg-icon {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
position: relative;
|
|
||||||
bottom: 0px;
|
|
||||||
}
|
|
||||||
*[slot="prefix"] {
|
|
||||||
margin-right: 8px;
|
|
||||||
margin-inline-end: 8px;
|
|
||||||
margin-inline-start: initial;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { LitVirtualizer } from "@lit-labs/virtualizer";
|
import type { LitVirtualizer } from "@lit-labs/virtualizer";
|
||||||
import type { RenderItemFunction } from "@lit-labs/virtualizer/virtualize";
|
import type { RenderItemFunction } from "@lit-labs/virtualizer/virtualize";
|
||||||
import { mdiMagnify, mdiMinusBoxOutline } from "@mdi/js";
|
import { mdiMagnify, mdiMinusBoxOutline, mdiPlus } from "@mdi/js";
|
||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import {
|
import {
|
||||||
@@ -91,6 +91,9 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
|
|||||||
@property({ type: Boolean, attribute: "allow-custom-value" })
|
@property({ type: Boolean, attribute: "allow-custom-value" })
|
||||||
public allowCustomValue;
|
public allowCustomValue;
|
||||||
|
|
||||||
|
@property({ attribute: "custom-value-label" })
|
||||||
|
public customValueLabel?: string;
|
||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
|
|
||||||
@property() public value?: string;
|
@property() public value?: string;
|
||||||
@@ -187,10 +190,15 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
|
const searchLabel =
|
||||||
|
this.label ??
|
||||||
|
(this.allowCustomValue
|
||||||
|
? (this.hass?.localize("ui.components.combo-box.search_or_custom") ??
|
||||||
|
"Search | Add custom value")
|
||||||
|
: (this.hass?.localize("ui.common.search") ?? "Search"));
|
||||||
|
|
||||||
return html`<ha-textfield
|
return html`<ha-textfield
|
||||||
.label=${this.label ??
|
.label=${searchLabel}
|
||||||
this.hass?.localize("ui.common.search") ??
|
|
||||||
"Search"}
|
|
||||||
@input=${this._filterChanged}
|
@input=${this._filterChanged}
|
||||||
></ha-textfield>
|
></ha-textfield>
|
||||||
${this._renderSectionButtons()}
|
${this._renderSectionButtons()}
|
||||||
@@ -438,13 +446,23 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.allowCustomValue && searchString) {
|
||||||
|
filteredItems.push({
|
||||||
|
id: searchString,
|
||||||
|
primary:
|
||||||
|
this.customValueLabel ??
|
||||||
|
this.hass?.localize("ui.components.combo-box.add_custom_item") ??
|
||||||
|
"Add custom item",
|
||||||
|
secondary: `"${searchString}"`,
|
||||||
|
icon_path: mdiPlus,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this._items = filteredItems as PickerComboBoxItem[];
|
this._items = filteredItems as PickerComboBoxItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
this._selectedItemIndex = -1;
|
this._selectedItemIndex = -1;
|
||||||
if (this._virtualizerElement) {
|
this._valuePinned = true;
|
||||||
this._virtualizerElement.scrollTo(0, 0);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private _toggleSection(ev: Event) {
|
private _toggleSection(ev: Event) {
|
||||||
@@ -639,7 +657,7 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
|
|||||||
typeof item === "string" ? item : item?.id;
|
typeof item === "string" ? item : item?.id;
|
||||||
|
|
||||||
private _getInitialSelectedIndex() {
|
private _getInitialSelectedIndex() {
|
||||||
if (!this._virtualizerElement || !this.value) {
|
if (!this._virtualizerElement || this._search || !this.value) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import {
|
|||||||
type TemplateResult,
|
type TemplateResult,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
|
import { ifDefined } from "lit/directives/if-defined";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { PickerMixin } from "../mixins/picker-mixin";
|
||||||
import { localizeContext } from "../data/context";
|
import { localizeContext } from "../data/context";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import "./ha-combo-box-item";
|
import "./ha-combo-box-item";
|
||||||
@@ -26,32 +28,7 @@ declare global {
|
|||||||
export type PickerValueRenderer = (value: string) => TemplateResult<1>;
|
export type PickerValueRenderer = (value: string) => TemplateResult<1>;
|
||||||
|
|
||||||
@customElement("ha-picker-field")
|
@customElement("ha-picker-field")
|
||||||
export class HaPickerField extends LitElement {
|
export class HaPickerField extends PickerMixin(LitElement) {
|
||||||
@property({ type: Boolean }) public disabled = false;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public required = false;
|
|
||||||
|
|
||||||
@property() public value?: string;
|
|
||||||
|
|
||||||
@property() public icon?: string;
|
|
||||||
|
|
||||||
@property() public helper?: string;
|
|
||||||
|
|
||||||
@property() public placeholder?: string;
|
|
||||||
|
|
||||||
@property({ type: Boolean, reflect: true }) public unknown = false;
|
|
||||||
|
|
||||||
@property({ attribute: "unknown-item-text" }) public unknownItemText?: string;
|
|
||||||
|
|
||||||
@property({ attribute: "hide-clear-icon", type: Boolean })
|
|
||||||
public hideClearIcon = false;
|
|
||||||
|
|
||||||
@property({ attribute: "show-label", type: Boolean })
|
|
||||||
public showLabel = false;
|
|
||||||
|
|
||||||
@property({ attribute: false })
|
|
||||||
public valueRenderer?: PickerValueRenderer;
|
|
||||||
|
|
||||||
@property({ type: Boolean, reflect: true }) public invalid = false;
|
@property({ type: Boolean, reflect: true }) public invalid = false;
|
||||||
|
|
||||||
@query("ha-combo-box-item", true) public item!: HaComboBoxItem;
|
@query("ha-combo-box-item", true) public item!: HaComboBoxItem;
|
||||||
@@ -66,31 +43,48 @@ export class HaPickerField extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const hasValue = !!this.value?.length;
|
const hasValue = !!this.value;
|
||||||
|
|
||||||
const showClearIcon =
|
const showClearIcon =
|
||||||
!!this.value && !this.required && !this.disabled && !this.hideClearIcon;
|
!!this.value && !this.required && !this.disabled && !this.hideClearIcon;
|
||||||
|
|
||||||
|
const placeholderText = this.placeholder ?? this.label;
|
||||||
|
|
||||||
const overlineLabel =
|
const overlineLabel =
|
||||||
this.showLabel && hasValue && this.placeholder
|
this.label && hasValue
|
||||||
? html`<span slot="overline">${this.placeholder}</span>`
|
? html`<span slot="overline"
|
||||||
|
>${this.label}${this.required ? " *" : ""}</span
|
||||||
|
>`
|
||||||
: nothing;
|
: nothing;
|
||||||
|
|
||||||
const headlineContent = hasValue
|
const headlineContent = hasValue
|
||||||
? this.valueRenderer
|
? this.valueRenderer
|
||||||
? this.valueRenderer(this.value ?? "")
|
? this.valueRenderer(this.value ?? "")
|
||||||
: html`<span slot="headline">${this.value}</span>`
|
: html`<span slot="headline">${this.value}</span>`
|
||||||
: this.placeholder
|
: placeholderText
|
||||||
? html`<span slot="headline" class="placeholder">
|
? html`<span slot="headline" class="placeholder">
|
||||||
${this.placeholder}
|
${placeholderText}${this.required ? " *" : ""}
|
||||||
</span>`
|
</span>`
|
||||||
: nothing;
|
: nothing;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-combo-box-item .disabled=${this.disabled} type="button" compact>
|
<ha-combo-box-item
|
||||||
${this.icon
|
aria-label=${ifDefined(this.label || this.placeholder)}
|
||||||
? html`<ha-icon slot="start" .icon=${this.icon}></ha-icon>`
|
.disabled=${this.disabled}
|
||||||
: nothing}
|
type="button"
|
||||||
|
compact
|
||||||
|
>
|
||||||
|
${this.image
|
||||||
|
? html`<img
|
||||||
|
alt=${this.label ?? ""}
|
||||||
|
slot="start"
|
||||||
|
.src=${this.image}
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
/>`
|
||||||
|
: this.icon
|
||||||
|
? html`<ha-icon slot="start" .icon=${this.icon}></ha-icon>`
|
||||||
|
: html`<slot name="start"></slot>`}
|
||||||
${overlineLabel}${headlineContent}
|
${overlineLabel}${headlineContent}
|
||||||
${this.unknown
|
${this.unknown
|
||||||
? html`<div slot="supporting-text" class="unknown">
|
? html`<div slot="supporting-text" class="unknown">
|
||||||
@@ -117,7 +111,7 @@ export class HaPickerField extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _clear(e) {
|
private _clear(e: CustomEvent) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
fireEvent(this, "clear");
|
fireEvent(this, "clear");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ export class HaAddonSelector extends LitElement {
|
|||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
allow-custom-entity
|
|
||||||
></ha-addon-picker>`;
|
></ha-addon-picker>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ export class HaConfigEntrySelector extends LitElement {
|
|||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
.integration=${this.selector.config_entry?.integration}
|
.integration=${this.selector.config_entry?.integration}
|
||||||
allow-custom-entity
|
|
||||||
></ha-config-entry-picker>`;
|
></ha-config-entry-picker>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ export class HaDeviceSelector extends LitElement {
|
|||||||
.placeholder=${this.placeholder}
|
.placeholder=${this.placeholder}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
allow-custom-entity
|
|
||||||
></ha-device-picker>
|
></ha-device-picker>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,15 +66,14 @@ export class HaEntitySelector extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
|
.placeholder=${this.placeholder}
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.includeEntities=${this.selector.entity?.include_entities}
|
.includeEntities=${this.selector.entity?.include_entities}
|
||||||
.excludeEntities=${this.selector.entity?.exclude_entities}
|
.excludeEntities=${this.selector.entity?.exclude_entities}
|
||||||
.entityFilter=${this._filterEntities}
|
.entityFilter=${this._filterEntities}
|
||||||
.createDomains=${this._createDomains}
|
.createDomains=${this._createDomains}
|
||||||
.placeholder=${this.placeholder}
|
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
allow-custom-entity
|
|
||||||
></ha-entity-picker>`;
|
></ha-entity-picker>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,13 +82,13 @@ export class HaEntitySelector extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
|
.placeholder=${this.placeholder}
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.includeEntities=${this.selector.entity.include_entities}
|
.includeEntities=${this.selector.entity.include_entities}
|
||||||
.excludeEntities=${this.selector.entity.exclude_entities}
|
.excludeEntities=${this.selector.entity.exclude_entities}
|
||||||
.reorder=${this.selector.entity.reorder ?? false}
|
.reorder=${this.selector.entity.reorder ?? false}
|
||||||
.entityFilter=${this._filterEntities}
|
.entityFilter=${this._filterEntities}
|
||||||
.createDomains=${this._createDomains}
|
.createDomains=${this._createDomains}
|
||||||
.placeholder=${this.placeholder}
|
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
></ha-entities-picker>
|
></ha-entities-picker>
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export class HaIconSelector extends LitElement {
|
|||||||
${!placeholder && stateObj
|
${!placeholder && stateObj
|
||||||
? html`
|
? html`
|
||||||
<ha-state-icon
|
<ha-state-icon
|
||||||
slot="fallback"
|
slot="start"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.stateObj=${stateObj}
|
.stateObj=${stateObj}
|
||||||
></ha-state-icon>
|
></ha-state-icon>
|
||||||
|
|||||||
@@ -135,7 +135,6 @@ class HaServicePicker extends LitElement {
|
|||||||
<ha-generic-picker
|
<ha-generic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.autofocus=${this.autofocus}
|
.autofocus=${this.autofocus}
|
||||||
allow-custom-value
|
|
||||||
.notFoundLabel=${this.hass.localize(
|
.notFoundLabel=${this.hass.localize(
|
||||||
"ui.components.service-picker.no_match"
|
"ui.components.service-picker.no_match"
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { fireEvent } from "../common/dom/fire_event";
|
|||||||
import { ScrollableFadeMixin } from "../mixins/scrollable-fade-mixin";
|
import { ScrollableFadeMixin } from "../mixins/scrollable-fade-mixin";
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
import { isIosApp } from "../util/is_ios";
|
||||||
import "./ha-dialog-header";
|
import "./ha-dialog-header";
|
||||||
import "./ha-icon-button";
|
import "./ha-icon-button";
|
||||||
|
|
||||||
@@ -184,6 +185,21 @@ export class HaWaDialog extends ScrollableFadeMixin(LitElement) {
|
|||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
|
if (isIosApp(this.hass)) {
|
||||||
|
const element = this.querySelector("[autofocus]");
|
||||||
|
if (element !== null) {
|
||||||
|
if (!element.id) {
|
||||||
|
element.id = "ha-wa-dialog-autofocus";
|
||||||
|
}
|
||||||
|
this.hass.auth.external!.fireMessage({
|
||||||
|
type: "focus_element",
|
||||||
|
payload: {
|
||||||
|
element_id: element.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
(this.querySelector("[autofocus]") as HTMLElement | null)?.focus();
|
(this.querySelector("[autofocus]") as HTMLElement | null)?.focus();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -235,6 +251,12 @@ export class HaWaDialog extends ScrollableFadeMixin(LitElement) {
|
|||||||
);
|
);
|
||||||
max-width: var(--ha-dialog-max-width, var(--safe-width));
|
max-width: var(--ha-dialog-max-width, var(--safe-width));
|
||||||
}
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
wa-dialog {
|
||||||
|
--show-duration: 0ms;
|
||||||
|
--hide-duration: 0ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:host([width="small"]) wa-dialog {
|
:host([width="small"]) wa-dialog {
|
||||||
--width: min(var(--ha-dialog-width-sm, 320px), var(--full-width));
|
--width: min(var(--ha-dialog-width-sm, 320px), var(--full-width));
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ class HaUserPicker extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.autofocus=${this.autofocus}
|
.autofocus=${this.autofocus}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
.notFoundLabel=${this._notFoundLabel}
|
|
||||||
.placeholder=${placeholder}
|
.placeholder=${placeholder}
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
|
.notFoundLabel=${this._notFoundLabel}
|
||||||
.getItems=${this._getItems}
|
.getItems=${this._getItems}
|
||||||
.valueRenderer=${this._valueRenderer}
|
.valueRenderer=${this._valueRenderer}
|
||||||
.rowRenderer=${this._rowRenderer}
|
.rowRenderer=${this._rowRenderer}
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ export const DOMAINS_HIDE_DEFAULT_MORE_INFO = [
|
|||||||
"select",
|
"select",
|
||||||
"text",
|
"text",
|
||||||
"update",
|
"update",
|
||||||
"event",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Domains that should have the history hidden in the more info dialog. */
|
/** Domains that should have the history hidden in the more info dialog. */
|
||||||
|
|||||||
@@ -176,6 +176,13 @@ interface EMOutgoingMessageAddEntityTo extends EMMessage {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface EMOutgoingMessageFocusElement extends EMMessage {
|
||||||
|
type: "focus_element";
|
||||||
|
payload: {
|
||||||
|
element_id: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
type EMOutgoingMessageWithoutAnswer =
|
type EMOutgoingMessageWithoutAnswer =
|
||||||
| EMMessageResultError
|
| EMMessageResultError
|
||||||
| EMMessageResultSuccess
|
| EMMessageResultSuccess
|
||||||
@@ -197,7 +204,8 @@ type EMOutgoingMessageWithoutAnswer =
|
|||||||
| EMOutgoingMessageThreadStoreInPlatformKeychain
|
| EMOutgoingMessageThreadStoreInPlatformKeychain
|
||||||
| EMOutgoingMessageImprovScan
|
| EMOutgoingMessageImprovScan
|
||||||
| EMOutgoingMessageImprovConfigureDevice
|
| EMOutgoingMessageImprovConfigureDevice
|
||||||
| EMOutgoingMessageAddEntityTo;
|
| EMOutgoingMessageAddEntityTo
|
||||||
|
| EMOutgoingMessageFocusElement;
|
||||||
|
|
||||||
export interface EMIncomingMessageRestart {
|
export interface EMIncomingMessageRestart {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
38
src/mixins/picker-mixin.ts
Normal file
38
src/mixins/picker-mixin.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import type { ReactiveElement } from "lit";
|
||||||
|
import { property } from "lit/decorators";
|
||||||
|
import type { Constructor } from "../types";
|
||||||
|
import type { PickerValueRenderer } from "../components/ha-picker-field";
|
||||||
|
|
||||||
|
export const PickerMixin = <T extends Constructor<ReactiveElement>>(
|
||||||
|
superClass: T
|
||||||
|
) => {
|
||||||
|
class PickerFieldClass extends superClass {
|
||||||
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public required = false;
|
||||||
|
|
||||||
|
@property() public icon?: string;
|
||||||
|
|
||||||
|
@property() public image?: string;
|
||||||
|
|
||||||
|
@property() public label?: string;
|
||||||
|
|
||||||
|
@property() public placeholder?: string;
|
||||||
|
|
||||||
|
@property() public helper?: string;
|
||||||
|
|
||||||
|
@property() public value?: string;
|
||||||
|
|
||||||
|
@property({ type: Boolean, reflect: true }) public unknown = false;
|
||||||
|
|
||||||
|
@property({ attribute: "unknown-item-text" })
|
||||||
|
public unknownItemText?: string;
|
||||||
|
|
||||||
|
@property({ attribute: "hide-clear-icon", type: Boolean })
|
||||||
|
public hideClearIcon = false;
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public valueRenderer?: PickerValueRenderer;
|
||||||
|
}
|
||||||
|
return PickerFieldClass;
|
||||||
|
};
|
||||||
@@ -160,7 +160,7 @@ class DialogFloorDetail extends LitElement {
|
|||||||
${!this._icon
|
${!this._icon
|
||||||
? html`
|
? html`
|
||||||
<ha-floor-icon
|
<ha-floor-icon
|
||||||
slot="fallback"
|
slot="start"
|
||||||
.floor=${{ level: this._level }}
|
.floor=${{ level: this._level }}
|
||||||
></ha-floor-icon>
|
></ha-floor-icon>
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ class DialogAutomationSave extends LitElement implements HassDialog {
|
|||||||
@value-changed=${this._iconChanged}
|
@value-changed=${this._iconChanged}
|
||||||
>
|
>
|
||||||
<ha-domain-icon
|
<ha-domain-icon
|
||||||
slot="fallback"
|
slot="start"
|
||||||
domain=${this._params.domain}
|
domain=${this._params.domain}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
>
|
>
|
||||||
@@ -176,8 +176,10 @@ class DialogAutomationSave extends LitElement implements HassDialog {
|
|||||||
id="category"
|
id="category"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.scope=${this._params.domain}
|
.scope=${this._params.domain}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.components.category-picker.category"
|
||||||
|
)}
|
||||||
.value=${this._entryUpdates.category}
|
.value=${this._entryUpdates.category}
|
||||||
show-label
|
|
||||||
@value-changed=${this._registryEntryChanged}
|
@value-changed=${this._registryEntryChanged}
|
||||||
></ha-category-picker>`
|
></ha-category-picker>`
|
||||||
: nothing}
|
: nothing}
|
||||||
@@ -194,7 +196,6 @@ class DialogAutomationSave extends LitElement implements HassDialog {
|
|||||||
id="area"
|
id="area"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._entryUpdates.area}
|
.value=${this._entryUpdates.area}
|
||||||
show-label
|
|
||||||
@value-changed=${this._registryEntryChanged}
|
@value-changed=${this._registryEntryChanged}
|
||||||
></ha-area-picker>`
|
></ha-area-picker>`
|
||||||
: nothing}
|
: nothing}
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ export class HaZoneCondition extends LitElement {
|
|||||||
@value-changed=${this._entityPicked}
|
@value-changed=${this._entityPicked}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
allow-custom-entity
|
|
||||||
.entityFilter=${zoneAndLocationFilter}
|
.entityFilter=${zoneAndLocationFilter}
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
@@ -51,7 +50,6 @@ export class HaZoneCondition extends LitElement {
|
|||||||
@value-changed=${this._zonePicked}
|
@value-changed=${this._zonePicked}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
allow-custom-entity
|
|
||||||
.includeDomains=${includeDomains}
|
.includeDomains=${includeDomains}
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ export class HaZoneTrigger extends LitElement {
|
|||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@value-changed=${this._entityPicked}
|
@value-changed=${this._entityPicked}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
allow-custom-entity
|
|
||||||
.entityFilter=${zoneAndLocationFilter}
|
.entityFilter=${zoneAndLocationFilter}
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
@@ -54,7 +53,6 @@ export class HaZoneTrigger extends LitElement {
|
|||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@value-changed=${this._zonePicked}
|
@value-changed=${this._zonePicked}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
allow-custom-entity
|
|
||||||
.includeDomains=${includeDomains}
|
.includeDomains=${includeDomains}
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ class DialogAssignCategory extends LitElement {
|
|||||||
<ha-category-picker
|
<ha-category-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.scope=${this._scope}
|
.scope=${this._scope}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.components.category-picker.category"
|
||||||
|
)}
|
||||||
.value=${this._category}
|
.value=${this._category}
|
||||||
@value-changed=${this._categoryChanged}
|
@value-changed=${this._categoryChanged}
|
||||||
></ha-category-picker>
|
></ha-category-picker>
|
||||||
|
|||||||
@@ -39,9 +39,6 @@ export class HaCategoryPicker extends SubscribeMixin(LitElement) {
|
|||||||
@property({ type: Boolean, attribute: "no-add" })
|
@property({ type: Boolean, attribute: "no-add" })
|
||||||
public noAdd = false;
|
public noAdd = false;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "show-label" })
|
|
||||||
public showLabel = false;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@property({ type: Boolean }) public required = false;
|
@property({ type: Boolean }) public required = false;
|
||||||
@@ -183,10 +180,6 @@ export class HaCategoryPicker extends SubscribeMixin(LitElement) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const placeholder =
|
|
||||||
this.placeholder ??
|
|
||||||
this.hass.localize("ui.components.category-picker.category");
|
|
||||||
|
|
||||||
const valueRenderer = this._computeValueRenderer(this._categories);
|
const valueRenderer = this._computeValueRenderer(this._categories);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
@@ -194,13 +187,12 @@ export class HaCategoryPicker extends SubscribeMixin(LitElement) {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.autofocus=${this.autofocus}
|
.autofocus=${this.autofocus}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
|
.placeholder=${this.placeholder}
|
||||||
|
.value=${this.value}
|
||||||
.notFoundLabel=${this._notFoundLabel}
|
.notFoundLabel=${this._notFoundLabel}
|
||||||
.emptyLabel=${this.hass.localize(
|
.emptyLabel=${this.hass.localize(
|
||||||
"ui.components.category-picker.no_categories"
|
"ui.components.category-picker.no_categories"
|
||||||
)}
|
)}
|
||||||
.placeholder=${placeholder}
|
|
||||||
.showLabel=${this.showLabel}
|
|
||||||
.value=${this.value}
|
|
||||||
.getItems=${this._getItems}
|
.getItems=${this._getItems}
|
||||||
.getAdditionalItems=${this._getAdditionalItems}
|
.getAdditionalItems=${this._getAdditionalItems}
|
||||||
.valueRenderer=${valueRenderer}
|
.valueRenderer=${valueRenderer}
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ class DialogDeviceRegistryDetail extends LitElement {
|
|||||||
<ha-area-picker
|
<ha-area-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._areaId}
|
.value=${this._areaId}
|
||||||
show-label
|
|
||||||
@value-changed=${this._areaPicked}
|
@value-changed=${this._areaPicked}
|
||||||
></ha-area-picker>
|
></ha-area-picker>
|
||||||
<ha-labels-picker
|
<ha-labels-picker
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
|||||||
${!this._icon && !stateObj?.attributes.icon && stateObj
|
${!this._icon && !stateObj?.attributes.icon && stateObj
|
||||||
? html`
|
? html`
|
||||||
<ha-state-icon
|
<ha-state-icon
|
||||||
slot="fallback"
|
slot="start"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.stateObj=${stateObj}
|
.stateObj=${stateObj}
|
||||||
></ha-state-icon>
|
></ha-state-icon>
|
||||||
@@ -778,7 +778,6 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._areaId}
|
.value=${this._areaId}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
show-label
|
|
||||||
@value-changed=${this._areaPicked}
|
@value-changed=${this._areaPicked}
|
||||||
></ha-area-picker>`
|
></ha-area-picker>`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -1013,7 +1012,6 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
|||||||
? html`<ha-area-picker
|
? html`<ha-area-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._areaId}
|
.value=${this._areaId}
|
||||||
show-label
|
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@value-changed=${this._areaPicked}
|
@value-changed=${this._areaPicked}
|
||||||
></ha-area-picker>`
|
></ha-area-picker>`
|
||||||
@@ -1545,6 +1543,12 @@ export class EntityRegistrySettingsEditor extends LitElement {
|
|||||||
margin-inline-end: 0;
|
margin-inline-end: 0;
|
||||||
margin-inline-start: initial;
|
margin-inline-start: initial;
|
||||||
}
|
}
|
||||||
|
ha-settings-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
gap: var(--ha-space-4);
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
ha-textfield,
|
ha-textfield,
|
||||||
ha-icon-picker,
|
ha-icon-picker,
|
||||||
ha-select,
|
ha-select,
|
||||||
|
|||||||
@@ -16,13 +16,14 @@ import "../../../../../components/buttons/ha-progress-button";
|
|||||||
import type { HaProgressButton } from "../../../../../components/buttons/ha-progress-button";
|
import type { HaProgressButton } from "../../../../../components/buttons/ha-progress-button";
|
||||||
import "../../../../../components/ha-alert";
|
import "../../../../../components/ha-alert";
|
||||||
import "../../../../../components/ha-card";
|
import "../../../../../components/ha-card";
|
||||||
|
import "../../../../../components/ha-generic-picker";
|
||||||
import "../../../../../components/ha-list-item";
|
import "../../../../../components/ha-list-item";
|
||||||
|
import type { PickerComboBoxItem } from "../../../../../components/ha-picker-combo-box";
|
||||||
import "../../../../../components/ha-select";
|
import "../../../../../components/ha-select";
|
||||||
import "../../../../../components/ha-selector/ha-selector-boolean";
|
import "../../../../../components/ha-selector/ha-selector-boolean";
|
||||||
import "../../../../../components/ha-settings-row";
|
import "../../../../../components/ha-settings-row";
|
||||||
import "../../../../../components/ha-svg-icon";
|
import "../../../../../components/ha-svg-icon";
|
||||||
import "../../../../../components/ha-textfield";
|
import "../../../../../components/ha-textfield";
|
||||||
import "../../../../../components/ha-combo-box";
|
|
||||||
import type {
|
import type {
|
||||||
ZWaveJSNodeCapabilities,
|
ZWaveJSNodeCapabilities,
|
||||||
ZWaveJSNodeConfigParam,
|
ZWaveJSNodeConfigParam,
|
||||||
@@ -329,19 +330,22 @@ class ZWaveJSNodeConfig extends LitElement {
|
|||||||
) {
|
) {
|
||||||
return html`
|
return html`
|
||||||
${labelAndDescription}
|
${labelAndDescription}
|
||||||
<ha-combo-box
|
<ha-generic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${item.value?.toString()}
|
.value=${item.value?.toString()}
|
||||||
allow-custom-value
|
allow-custom-value
|
||||||
hide-clear-icon
|
hide-clear-icon
|
||||||
.items=${this._getComboBoxOptions(item.metadata.states)}
|
.getItems=${this._getManualEntryItems(item.metadata.states)}
|
||||||
.disabled=${!item.metadata.writeable}
|
.disabled=${!item.metadata.writeable}
|
||||||
.invalid=${result?.status === "error"}
|
.invalid=${result?.status === "error"}
|
||||||
.placeholder=${item.metadata.unit}
|
.placeholder=${item.metadata.unit}
|
||||||
.helper=${`${this.hass.localize("ui.panel.config.zwave_js.node_config.between_min_max", { min: item.metadata.min, max: item.metadata.max })}${defaultLabel ? `, ${defaultLabel}` : ""}`}
|
.helper=${`${this.hass.localize("ui.panel.config.zwave_js.node_config.between_min_max", { min: item.metadata.min, max: item.metadata.max })}${defaultLabel ? `, ${defaultLabel}` : ""}`}
|
||||||
|
.valueRenderer=${this._enumeratedPickerValueRenderer(
|
||||||
|
item.metadata.states
|
||||||
|
)}
|
||||||
@value-changed=${this._getComboBoxValueChangedCallback(id, item)}
|
@value-changed=${this._getComboBoxValueChangedCallback(id, item)}
|
||||||
>
|
>
|
||||||
</ha-combo-box>
|
</ha-generic-picker>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
return html`${labelAndDescription}
|
return html`${labelAndDescription}
|
||||||
@@ -363,7 +367,10 @@ class ZWaveJSNodeConfig extends LitElement {
|
|||||||
</ha-textfield>`;
|
</ha-textfield>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.configuration_value_type === "enumerated") {
|
if (
|
||||||
|
item.configuration_value_type === "enumerated" &&
|
||||||
|
Object.keys(item.metadata.states).length < 5
|
||||||
|
) {
|
||||||
return html`
|
return html`
|
||||||
${labelAndDescription}
|
${labelAndDescription}
|
||||||
<ha-select
|
<ha-select
|
||||||
@@ -385,6 +392,28 @@ class ZWaveJSNodeConfig extends LitElement {
|
|||||||
</ha-select>
|
</ha-select>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
if (item.configuration_value_type === "enumerated") {
|
||||||
|
return html`
|
||||||
|
${labelAndDescription}
|
||||||
|
<ha-generic-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.disabled=${!item.metadata.writeable}
|
||||||
|
.value=${item.value?.toString()}
|
||||||
|
.key=${id}
|
||||||
|
hide-clear-icon
|
||||||
|
@value-changed=${this._pickerValueChanged}
|
||||||
|
.helper=${defaultLabel}
|
||||||
|
.getItems=${this._getEnumeratedPickerItems(item.metadata.states!)}
|
||||||
|
.valueRenderer=${this._enumeratedPickerValueRenderer(
|
||||||
|
item.metadata.states!
|
||||||
|
)}
|
||||||
|
.property=${item.property}
|
||||||
|
.endpoint=${item.endpoint}
|
||||||
|
.propertyKey=${item.property_key}
|
||||||
|
>
|
||||||
|
</ha-generic-picker>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
return html`${labelAndDescription}
|
return html`${labelAndDescription}
|
||||||
<p>${item.value}</p>`;
|
<p>${item.value}</p>`;
|
||||||
@@ -429,15 +458,23 @@ class ZWaveJSNodeConfig extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _dropdownSelected(ev) {
|
private _dropdownSelected(ev) {
|
||||||
|
this._handleEnumeratedPickerValueChanged(ev, ev.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _pickerValueChanged(ev) {
|
||||||
|
this._handleEnumeratedPickerValueChanged(ev, ev.detail.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleEnumeratedPickerValueChanged(ev, value: string) {
|
||||||
if (ev.target === undefined || this._config![ev.target.key] === undefined) {
|
if (ev.target === undefined || this._config![ev.target.key] === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this._config![ev.target.key].value?.toString() === ev.target.value) {
|
if (this._config![ev.target.key].value?.toString() === value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._setResult(ev.target.key, undefined);
|
this._setResult(ev.target.key, undefined);
|
||||||
|
|
||||||
this._updateConfigParameter(ev.target, Number(ev.target.value));
|
this._updateConfigParameter(ev.target, Number(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _numericInputChanged(ev) {
|
private _numericInputChanged(ev) {
|
||||||
@@ -474,11 +511,36 @@ class ZWaveJSNodeConfig extends LitElement {
|
|||||||
this._updateConfigParameter(ev.target, value);
|
this._updateConfigParameter(ev.target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getComboBoxOptions = memoizeOne((states: Record<string, string>) =>
|
private _getEnumeratedPickerItems = memoizeOne(
|
||||||
Object.entries(states).map(([value, label]) => ({
|
(states: Record<string, string>) => {
|
||||||
value,
|
const items: PickerComboBoxItem[] = Object.entries(states).map(
|
||||||
label: `${value} - ${label}`,
|
([value, label]) => ({
|
||||||
}))
|
id: value,
|
||||||
|
primary: label,
|
||||||
|
sorting_label: `${label}_${value}`,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return () => items;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
private _enumeratedPickerValueRenderer = memoizeOne(
|
||||||
|
(states: Record<string, string>) => (value: string) =>
|
||||||
|
html`<span slot="headline">${states[value] || value}</span>`
|
||||||
|
);
|
||||||
|
|
||||||
|
private _getManualEntryItems = memoizeOne(
|
||||||
|
(states: Record<string, string>) => {
|
||||||
|
const items: PickerComboBoxItem[] = Object.entries(states).map(
|
||||||
|
([value, label]) => ({
|
||||||
|
id: value,
|
||||||
|
primary: `${label}`,
|
||||||
|
secondary: value,
|
||||||
|
sorting_label: `${label}_${value}`,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return () => items;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
private _getComboBoxValueChangedCallback(
|
private _getComboBoxValueChangedCallback(
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
|||||||
import "../../../components/ha-alert";
|
import "../../../components/ha-alert";
|
||||||
import "../../../components/ha-button";
|
import "../../../components/ha-button";
|
||||||
import "../../../components/ha-color-picker";
|
import "../../../components/ha-color-picker";
|
||||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
import "../../../components/ha-dialog-footer";
|
||||||
import "../../../components/ha-icon-picker";
|
import "../../../components/ha-icon-picker";
|
||||||
import "../../../components/ha-switch";
|
import "../../../components/ha-switch";
|
||||||
|
import "../../../components/ha-wa-dialog";
|
||||||
import "../../../components/ha-textarea";
|
import "../../../components/ha-textarea";
|
||||||
import "../../../components/ha-textfield";
|
import "../../../components/ha-textfield";
|
||||||
import type { LabelRegistryEntryMutableParams } from "../../../data/label/label_registry";
|
import type { LabelRegistryEntryMutableParams } from "../../../data/label/label_registry";
|
||||||
@@ -37,6 +38,8 @@ class DialogLabelDetail
|
|||||||
|
|
||||||
@state() private _submitting = false;
|
@state() private _submitting = false;
|
||||||
|
|
||||||
|
@state() private _open = false;
|
||||||
|
|
||||||
public showDialog(params: LabelDetailDialogParams): void {
|
public showDialog(params: LabelDetailDialogParams): void {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
@@ -51,20 +54,17 @@ class DialogLabelDetail
|
|||||||
this._color = "";
|
this._color = "";
|
||||||
this._description = "";
|
this._description = "";
|
||||||
}
|
}
|
||||||
document.body.addEventListener("keydown", this._handleKeyPress);
|
this._open = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleKeyPress = (ev: KeyboardEvent) => {
|
|
||||||
if (ev.key === "Escape") {
|
|
||||||
ev.stopPropagation();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public closeDialog() {
|
public closeDialog() {
|
||||||
|
this._open = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _dialogClosed(): void {
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
document.body.removeEventListener("keydown", this._handleKeyPress);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
@@ -73,17 +73,13 @@ class DialogLabelDetail
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-dialog
|
<ha-wa-dialog
|
||||||
open
|
.hass=${this.hass}
|
||||||
@closed=${this.closeDialog}
|
.open=${this._open}
|
||||||
scrimClickAction
|
header-title=${this._params.entry
|
||||||
escapeKeyAction
|
? this._params.entry.name || this._params.entry.label_id
|
||||||
.heading=${createCloseHeading(
|
: this.hass!.localize("ui.dialogs.label-detail.new_label")}
|
||||||
this.hass,
|
@closed=${this._dialogClosed}
|
||||||
this._params.entry
|
|
||||||
? this._params.entry.name || this._params.entry.label_id
|
|
||||||
: this.hass!.localize("ui.dialogs.label-detail.new_label")
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
${this._error
|
${this._error
|
||||||
@@ -91,7 +87,7 @@ class DialogLabelDetail
|
|||||||
: ""}
|
: ""}
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<ha-textfield
|
<ha-textfield
|
||||||
dialogInitialFocus
|
autofocus
|
||||||
.value=${this._name}
|
.value=${this._name}
|
||||||
.configValue=${"name"}
|
.configValue=${"name"}
|
||||||
@input=${this._input}
|
@input=${this._input}
|
||||||
@@ -125,29 +121,32 @@ class DialogLabelDetail
|
|||||||
></ha-textarea>
|
></ha-textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
${this._params.entry && this._params.removeEntry
|
|
||||||
? html`
|
<ha-dialog-footer slot="footer">
|
||||||
<ha-button
|
${this._params.entry && this._params.removeEntry
|
||||||
slot="secondaryAction"
|
? html`
|
||||||
variant="danger"
|
<ha-button
|
||||||
appearance="plain"
|
slot="secondaryAction"
|
||||||
@click=${this._deleteEntry}
|
variant="danger"
|
||||||
.disabled=${this._submitting}
|
appearance="plain"
|
||||||
>
|
@click=${this._deleteEntry}
|
||||||
${this.hass!.localize("ui.common.delete")}
|
.disabled=${this._submitting}
|
||||||
</ha-button>
|
>
|
||||||
`
|
${this.hass!.localize("ui.common.delete")}
|
||||||
: nothing}
|
</ha-button>
|
||||||
<ha-button
|
`
|
||||||
slot="primaryAction"
|
: nothing}
|
||||||
@click=${this._updateEntry}
|
<ha-button
|
||||||
.disabled=${this._submitting || !this._name}
|
slot="primaryAction"
|
||||||
>
|
@click=${this._updateEntry}
|
||||||
${this._params.entry
|
.disabled=${this._submitting || !this._name}
|
||||||
? this.hass!.localize("ui.common.update")
|
>
|
||||||
: this.hass!.localize("ui.common.create")}
|
${this._params.entry
|
||||||
</ha-button>
|
? this.hass!.localize("ui.common.update")
|
||||||
</ha-dialog>
|
: this.hass!.localize("ui.common.create")}
|
||||||
|
</ha-button>
|
||||||
|
</ha-dialog-footer>
|
||||||
|
</ha-wa-dialog>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -144,7 +144,6 @@ class HaPanelDevState extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._entityId}
|
.value=${this._entityId}
|
||||||
@value-changed=${this._entityIdChanged}
|
@value-changed=${this._entityIdChanged}
|
||||||
allow-custom-entity
|
|
||||||
show-entity-id
|
show-entity-id
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
${this._entityId
|
${this._entityId
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ export class DialogEditHome
|
|||||||
"ui.panel.home.editor.favorite_entities_helper"
|
"ui.panel.home.editor.favorite_entities_helper"
|
||||||
)}
|
)}
|
||||||
reorder
|
reorder
|
||||||
allow-custom-entity
|
|
||||||
@value-changed=${this._favoriteEntitiesChanged}
|
@value-changed=${this._favoriteEntitiesChanged}
|
||||||
></ha-entities-picker>
|
></ha-entities-picker>
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,6 @@ export class HuiEntityEditor extends LitElement {
|
|||||||
.index=${index}
|
.index=${index}
|
||||||
.entityFilter=${this.entityFilter}
|
.entityFilter=${this.entityFilter}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
allow-custom-entity
|
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ export class HuiGraphFooterEditor
|
|||||||
return html`
|
return html`
|
||||||
<div class="card-config">
|
<div class="card-config">
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
allow-custom-entity
|
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.lovelace.editor.card.generic.entity"
|
"ui.panel.lovelace.editor.card.generic.entity"
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ export class HuiHeadingBadgesEditor extends LitElement {
|
|||||||
${isEntityBadge && entityBadge
|
${isEntityBadge && entityBadge
|
||||||
? html`
|
? html`
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
allow-custom-entity
|
|
||||||
hide-clear-icon
|
hide-clear-icon
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${entityBadge.entity ?? ""}
|
.value=${entityBadge.entity ?? ""}
|
||||||
@@ -131,7 +130,6 @@ export class HuiHeadingBadgesEditor extends LitElement {
|
|||||||
@value-changed=${this._entityPicked}
|
@value-changed=${this._entityPicked}
|
||||||
.value=${undefined}
|
.value=${undefined}
|
||||||
@click=${preventDefault}
|
@click=${preventDefault}
|
||||||
allow-custom-entity
|
|
||||||
add-button
|
add-button
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -316,7 +316,6 @@ export class HuiStatisticsGraphCardEditor
|
|||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></ha-form>
|
></ha-form>
|
||||||
<ha-statistics-picker
|
<ha-statistics-picker
|
||||||
allow-custom-entity
|
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.placeholder=${this.hass!.localize(
|
.placeholder=${this.hass!.localize(
|
||||||
"ui.panel.lovelace.editor.card.statistics-graph.pick_statistic"
|
"ui.panel.lovelace.editor.card.statistics-graph.pick_statistic"
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ export class HuiEntitiesCardRowEditor extends LitElement {
|
|||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
allow-custom-entity
|
|
||||||
hide-clear-icon
|
hide-clear-icon
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${(entityConf as EntityConfig).entity}
|
.value=${(entityConf as EntityConfig).entity}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ export class HuiHomeDashboardStrategyEditor
|
|||||||
"ui.panel.lovelace.editor.strategy.home.add_favorite_entity"
|
"ui.panel.lovelace.editor.strategy.home.add_favorite_entity"
|
||||||
)}
|
)}
|
||||||
reorder
|
reorder
|
||||||
allow-custom-entity
|
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
>
|
>
|
||||||
</ha-entities-picker>
|
</ha-entities-picker>
|
||||||
|
|||||||
@@ -1308,7 +1308,9 @@
|
|||||||
"combo-box": {
|
"combo-box": {
|
||||||
"no_match": "No matching items found",
|
"no_match": "No matching items found",
|
||||||
"no_items": "No items available",
|
"no_items": "No items available",
|
||||||
"unknown_item": "Unknown item"
|
"unknown_item": "Unknown item",
|
||||||
|
"search_or_custom": "Search | Add custom item",
|
||||||
|
"add_custom_item": "Add custom item"
|
||||||
},
|
},
|
||||||
"suggest_with_ai": {
|
"suggest_with_ai": {
|
||||||
"label": "Suggest",
|
"label": "Suggest",
|
||||||
@@ -1317,6 +1319,9 @@
|
|||||||
"suggesting_3": "Enchanting…",
|
"suggesting_3": "Enchanting…",
|
||||||
"done": "Done!",
|
"done": "Done!",
|
||||||
"error": "Fail!"
|
"error": "Fail!"
|
||||||
|
},
|
||||||
|
"navigation-picker": {
|
||||||
|
"add_custom_path": "Add custom path"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dialogs": {
|
"dialogs": {
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@@ -9354,7 +9354,7 @@ __metadata:
|
|||||||
typescript: "npm:5.9.3"
|
typescript: "npm:5.9.3"
|
||||||
typescript-eslint: "npm:8.49.0"
|
typescript-eslint: "npm:8.49.0"
|
||||||
ua-parser-js: "npm:2.0.7"
|
ua-parser-js: "npm:2.0.7"
|
||||||
vite-tsconfig-paths: "npm:5.1.4"
|
vite-tsconfig-paths: "npm:6.0.1"
|
||||||
vitest: "npm:4.0.15"
|
vitest: "npm:4.0.15"
|
||||||
vue: "npm:2.7.16"
|
vue: "npm:2.7.16"
|
||||||
vue2-daterange-picker: "npm:0.6.8"
|
vue2-daterange-picker: "npm:0.6.8"
|
||||||
@@ -14698,9 +14698,9 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"vite-tsconfig-paths@npm:5.1.4":
|
"vite-tsconfig-paths@npm:6.0.1":
|
||||||
version: 5.1.4
|
version: 6.0.1
|
||||||
resolution: "vite-tsconfig-paths@npm:5.1.4"
|
resolution: "vite-tsconfig-paths@npm:6.0.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: "npm:^4.1.1"
|
debug: "npm:^4.1.1"
|
||||||
globrex: "npm:^0.1.2"
|
globrex: "npm:^0.1.2"
|
||||||
@@ -14710,7 +14710,7 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
vite:
|
vite:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10/b409dbd17829f560021a71dba3e473b9c06dcf5fdc9d630b72c1f787145ec478b38caff1be04868971ac8bdcbf0f5af45eeece23dbc9c59c54b901f867740ae0
|
checksum: 10/7ac6d17efee21be805ed62857269d4e41d939774a8cc698e77145b4312edf996a9536e7a3b37e25486ae77d36fc5ae011378058ff290be39da16e52a47e87da7
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user