Update dependency prettier to v3 (#17215)

* Update dependency prettier to v3

* Update config and remove .prettierignore

* Reformat

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
pull/17312/head
renovate[bot] 2023-07-14 17:40:17 +00:00 committed by GitHub
parent 9bf76a07b8
commit cb0bc762b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
127 changed files with 1842 additions and 1820 deletions

View File

@ -1,9 +0,0 @@
build
translations/*
node_modules/*
hass_frontend/*
pip-selfcheck.json
# vscode
.vscode/*
!.vscode/extensions.json

View File

@ -85,17 +85,16 @@ class DemoHaAutomationEditorAction extends LitElement {
.value=${this.data[sampleIdx]} .value=${this.data[sampleIdx]}
> >
${["light", "dark"].map( ${["light", "dark"].map(
(slot) => (slot) => html`
html` <ha-automation-action
<ha-automation-action slot=${slot}
slot=${slot} .hass=${this.hass}
.hass=${this.hass} .actions=${this.data[sampleIdx]}
.actions=${this.data[sampleIdx]} .sampleIdx=${sampleIdx}
.sampleIdx=${sampleIdx} .disabled=${this._disabled}
.disabled=${this._disabled} @value-changed=${valueChanged}
@value-changed=${valueChanged} ></ha-automation-action>
></ha-automation-action> `
`
)} )}
</demo-black-white-row> </demo-black-white-row>
` `

View File

@ -121,17 +121,16 @@ class DemoHaAutomationEditorCondition extends LitElement {
.value=${this.data[sampleIdx]} .value=${this.data[sampleIdx]}
> >
${["light", "dark"].map( ${["light", "dark"].map(
(slot) => (slot) => html`
html` <ha-automation-condition
<ha-automation-condition slot=${slot}
slot=${slot} .hass=${this.hass}
.hass=${this.hass} .conditions=${this.data[sampleIdx]}
.conditions=${this.data[sampleIdx]} .sampleIdx=${sampleIdx}
.sampleIdx=${sampleIdx} .disabled=${this._disabled}
.disabled=${this._disabled} @value-changed=${valueChanged}
@value-changed=${valueChanged} ></ha-automation-condition>
></ha-automation-condition> `
`
)} )}
</demo-black-white-row> </demo-black-white-row>
` `

View File

@ -167,17 +167,16 @@ class DemoHaAutomationEditorTrigger extends LitElement {
.value=${this.data[sampleIdx]} .value=${this.data[sampleIdx]}
> >
${["light", "dark"].map( ${["light", "dark"].map(
(slot) => (slot) => html`
html` <ha-automation-trigger
<ha-automation-trigger slot=${slot}
slot=${slot} .hass=${this.hass}
.hass=${this.hass} .triggers=${this.data[sampleIdx]}
.triggers=${this.data[sampleIdx]} .sampleIdx=${sampleIdx}
.sampleIdx=${sampleIdx} .disabled=${this._disabled}
.disabled=${this._disabled} @value-changed=${valueChanged}
@value-changed=${valueChanged} ></ha-automation-trigger>
></ha-automation-trigger> `
`
)} )}
</demo-black-white-row> </demo-black-white-row>
` `

View File

@ -497,24 +497,23 @@ class DemoHaSelector extends LitElement implements ProvideHassElement {
<demo-black-white-row .title=${info.name} .value=${this.data[idx]}> <demo-black-white-row .title=${info.name} .value=${this.data[idx]}>
${["light", "dark"].map((slot) => ${["light", "dark"].map((slot) =>
Object.entries(info.input).map( Object.entries(info.input).map(
([key, value]) => ([key, value]) => html`
html` <ha-settings-row narrow slot=${slot}>
<ha-settings-row narrow slot=${slot}> <span slot="heading">${value?.name || key}</span>
<span slot="heading">${value?.name || key}</span> <span slot="description">${value?.description}</span>
<span slot="description">${value?.description}</span> <ha-selector
<ha-selector .hass=${this.hass}
.hass=${this.hass} .selector=${value!.selector}
.selector=${value!.selector} .key=${key}
.key=${key} .label=${this._label ? value!.name : undefined}
.label=${this._label ? value!.name : undefined} .value=${data[key] ?? value!.default}
.value=${data[key] ?? value!.default} .disabled=${this._disabled}
.disabled=${this._disabled} .required=${this._required}
.required=${this._required} @value-changed=${valueChanged}
@value-changed=${valueChanged} .helper=${this._helper ? "Helper text" : undefined}
.helper=${this._helper ? "Helper text" : undefined} ></ha-selector>
></ha-selector> </ha-settings-row>
</ha-settings-row> `
`
) )
)} )}
</demo-black-white-row> </demo-black-white-row>

View File

@ -20,9 +20,8 @@ export class DemoHaTip extends LitElement {
<ha-card header="ha-tip ${mode} demo"> <ha-card header="ha-tip ${mode} demo">
<div class="card-content"> <div class="card-content">
${tips.map( ${tips.map(
(tip) => html`<ha-tip .hass=${provideHass(this)} (tip) =>
>${tip}</ha-tip html`<ha-tip .hass=${provideHass(this)}>${tip}</ha-tip>`
>`
)} )}
</div> </div>
</ha-card> </ha-card>

View File

@ -544,14 +544,13 @@ class HassioAddonInfo extends LitElement {
<code slot="description"> ${this.addon.hostname} </code> <code slot="description"> ${this.addon.hostname} </code>
</ha-settings-row> </ha-settings-row>
${metrics.map( ${metrics.map(
(metric) => (metric) => html`
html` <supervisor-metric
<supervisor-metric .description=${metric.description}
.description=${metric.description} .value=${metric.value ?? 0}
.value=${metric.value ?? 0} .tooltip=${metric.tooltip}
.tooltip=${metric.tooltip} ></supervisor-metric>
></supervisor-metric> `
`
)}` )}`
: ""} : ""}
</div> </div>

View File

@ -384,28 +384,30 @@ export class SupervisorBackupContent extends LitElement {
: undefined; : undefined;
let checkedItems = 0; let checkedItems = 0;
this[section].forEach((item) => { this[section].forEach((item) => {
templates.push(html`<ha-formfield templates.push(
.label=${html`<supervisor-formfield-label html`<ha-formfield
.label=${item.name} .label=${html`<supervisor-formfield-label
.iconPath=${section === "addons" ? mdiPuzzle : mdiFolder} .label=${item.name}
.imageUrl=${section === "addons" && .iconPath=${section === "addons" ? mdiPuzzle : mdiFolder}
!this.onboarding && .imageUrl=${section === "addons" &&
atLeastVersion(this.hass.config.version, 0, 105) && !this.onboarding &&
addons?.get(item.slug)?.icon atLeastVersion(this.hass.config.version, 0, 105) &&
? `/api/hassio/addons/${item.slug}/icon` addons?.get(item.slug)?.icon
: undefined} ? `/api/hassio/addons/${item.slug}/icon`
.version=${item.version} : undefined}
.version=${item.version}
>
</supervisor-formfield-label>`}
> >
</supervisor-formfield-label>`} <ha-checkbox
> .item=${item}
<ha-checkbox .checked=${item.checked}
.item=${item} .section=${section}
.checked=${item.checked} @change=${this._updateSectionEntry}
.section=${section} >
@change=${this._updateSectionEntry} </ha-checkbox>
> </ha-formfield>`
</ha-checkbox> );
</ha-formfield>`);
if (item.checked) { if (item.checked) {
checkedItems++; checkedItems++;

View File

@ -168,25 +168,24 @@ export class DialogHassioNetwork
${this._accessPoints.accesspoints ${this._accessPoints.accesspoints
.filter((ap) => ap.ssid) .filter((ap) => ap.ssid)
.map( .map(
(ap) => (ap) => html`
html` <mwc-list-item
<mwc-list-item twoline
twoline @click=${this._selectAP}
@click=${this._selectAP} .activated=${ap.ssid ===
.activated=${ap.ssid === this._wifiConfiguration?.ssid}
this._wifiConfiguration?.ssid} .ap=${ap}
.ap=${ap} >
> <span>${ap.ssid}</span>
<span>${ap.ssid}</span> <span slot="secondary">
<span slot="secondary"> ${ap.mac} -
${ap.mac} - ${this.supervisor.localize(
${this.supervisor.localize( "dialog.network.signal_strength"
"dialog.network.signal_strength" )}:
)}: ${ap.signal}
${ap.signal} </span>
</span> </mwc-list-item>
</mwc-list-item> `
`
)} )}
</mwc-list> </mwc-list>
` `

View File

@ -157,10 +157,11 @@ class HassioRegistriesDialog extends LitElement {
} }
public focus(): void { public focus(): void {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -209,10 +209,11 @@ class HassioRepositoriesDialog extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -81,14 +81,13 @@ class HassioCoreInfo extends LitElement {
</div> </div>
<div> <div>
${metrics.map( ${metrics.map(
(metric) => (metric) => html`
html` <supervisor-metric
<supervisor-metric .description=${metric.description}
.description=${metric.description} .value=${metric.value ?? 0}
.value=${metric.value ?? 0} .tooltip=${metric.tooltip}
.tooltip=${metric.tooltip} ></supervisor-metric>
></supervisor-metric> `
`
)} )}
</div> </div>
</div> </div>

View File

@ -154,14 +154,13 @@ class HassioHostInfo extends LitElement {
</ha-settings-row>` </ha-settings-row>`
: ""} : ""}
${metrics.map( ${metrics.map(
(metric) => (metric) => html`
html` <supervisor-metric
<supervisor-metric .description=${metric.description}
.description=${metric.description} .value=${metric.value ?? 0}
.value=${metric.value ?? 0} .tooltip=${metric.tooltip}
.tooltip=${metric.tooltip} ></supervisor-metric>
></supervisor-metric> `
`
)} )}
</div> </div>
</div> </div>

View File

@ -178,14 +178,13 @@ class HassioSupervisorInfo extends LitElement {
</div> </div>
<div class="metrics-block"> <div class="metrics-block">
${metrics.map( ${metrics.map(
(metric) => (metric) => html`
html` <supervisor-metric
<supervisor-metric .description=${metric.description}
.description=${metric.description} .value=${metric.value ?? 0}
.value=${metric.value ?? 0} .tooltip=${metric.tooltip}
.tooltip=${metric.tooltip} ></supervisor-metric>
></supervisor-metric> `
`
)} )}
</div> </div>
</div> </div>

View File

@ -227,7 +227,7 @@
"object-hash": "3.0.0", "object-hash": "3.0.0",
"open": "9.1.0", "open": "9.1.0",
"pinst": "3.0.0", "pinst": "3.0.0",
"prettier": "2.8.8", "prettier": "3.0.0",
"rollup": "2.79.1", "rollup": "2.79.1",
"rollup-plugin-string": "3.0.0", "rollup-plugin-string": "3.0.0",
"rollup-plugin-terser": "7.0.2", "rollup-plugin-terser": "7.0.2",
@ -256,9 +256,5 @@
"sortablejs@1.15.0": "patch:sortablejs@npm%3A1.15.0#./.yarn/patches/sortablejs-npm-1.15.0-f3a393abcc.patch", "sortablejs@1.15.0": "patch:sortablejs@npm%3A1.15.0#./.yarn/patches/sortablejs-npm-1.15.0-f3a393abcc.patch",
"leaflet-draw@1.0.4": "patch:leaflet-draw@npm%3A1.0.4#./.yarn/patches/leaflet-draw-npm-1.0.4-0ca0ebcf65.patch" "leaflet-draw@1.0.4": "patch:leaflet-draw@npm%3A1.0.4#./.yarn/patches/leaflet-draw-npm-1.0.4-0ca0ebcf65.patch"
}, },
"prettier": {
"trailingComma": "es5",
"arrowParens": "always"
},
"packageManager": "yarn@3.6.1" "packageManager": "yarn@3.6.1"
} }

3
prettier.config.js Normal file
View File

@ -0,0 +1,3 @@
export default {
trailingComma: "es5",
};

View File

@ -38,7 +38,7 @@ export type LocalizeKeys =
// Tweaked from https://www.raygesualdo.com/posts/flattening-object-keys-with-typescript-types // Tweaked from https://www.raygesualdo.com/posts/flattening-object-keys-with-typescript-types
export type FlattenObjectKeys< export type FlattenObjectKeys<
T extends Record<string, any>, T extends Record<string, any>,
Key extends keyof T = keyof T Key extends keyof T = keyof T,
> = Key extends string > = Key extends string
? T[Key] extends Record<string, unknown> ? T[Key] extends Record<string, unknown>
? `${Key}.${FlattenObjectKeys<T[Key]>}` ? `${Key}.${FlattenObjectKeys<T[Key]>}`

View File

@ -108,23 +108,24 @@ export default class HaChartBase extends LitElement {
? html`<div class="chartLegend"> ? html`<div class="chartLegend">
<ul> <ul>
${this.data.datasets.map( ${this.data.datasets.map(
(dataset, index) => html`<li (dataset, index) =>
.datasetIndex=${index} html`<li
@click=${this._legendClick} .datasetIndex=${index}
class=${classMap({ @click=${this._legendClick}
hidden: this._hiddenDatasets.has(index), class=${classMap({
})} hidden: this._hiddenDatasets.has(index),
.title=${dataset.label}
>
<div
class="bullet"
style=${styleMap({
backgroundColor: dataset.backgroundColor as string,
borderColor: dataset.borderColor as string,
})} })}
></div> .title=${dataset.label}
<div class="label">${dataset.label}</div> >
</li>` <div
class="bullet"
style=${styleMap({
backgroundColor: dataset.backgroundColor as string,
borderColor: dataset.borderColor as string,
})}
></div>
<div class="label">${dataset.label}</div>
</li>`
)} )}
</ul> </ul>
</div>` </div>`
@ -156,18 +157,19 @@ export default class HaChartBase extends LitElement {
<div> <div>
<ul> <ul>
${this._tooltip.body.map( ${this._tooltip.body.map(
(item, i) => html`<li> (item, i) =>
<div html`<li>
class="bullet" <div
style=${styleMap({ class="bullet"
backgroundColor: this._tooltip!.labelColors[i] style=${styleMap({
.backgroundColor as string, backgroundColor: this._tooltip!.labelColors[i]
borderColor: this._tooltip!.labelColors[i] .backgroundColor as string,
.borderColor as string, borderColor: this._tooltip!.labelColors[i]
})} .borderColor as string,
></div> })}
${item.lines.join("\n")} ></div>
</li>` ${item.lines.join("\n")}
</li>`
)} )}
</ul> </ul>
</div> </div>

View File

@ -36,12 +36,11 @@ interface AreaDevices {
devices: string[]; devices: string[];
} }
const rowRenderer: ComboBoxLitRenderer<AreaDevices> = ( const rowRenderer: ComboBoxLitRenderer<AreaDevices> = (item) =>
item html`<mwc-list-item twoline>
) => html`<mwc-list-item twoline> <span>${item.name}</span>
<span>${item.name}</span> <span slot="secondary">${item.devices.length} devices</span>
<span slot="secondary">${item.devices.length} devices</span> </mwc-list-item>`;
</mwc-list-item>`;
@customElement("ha-area-devices-picker") @customElement("ha-area-devices-picker")
export class HaAreaDevicesPicker extends SubscribeMixin(LitElement) { export class HaAreaDevicesPicker extends SubscribeMixin(LitElement) {

View File

@ -17,7 +17,7 @@ const NO_AUTOMATION_KEY = "NO_AUTOMATION";
const UNKNOWN_AUTOMATION_KEY = "UNKNOWN_AUTOMATION"; const UNKNOWN_AUTOMATION_KEY = "UNKNOWN_AUTOMATION";
export abstract class HaDeviceAutomationPicker< export abstract class HaDeviceAutomationPicker<
T extends DeviceAutomation T extends DeviceAutomation,
> extends LitElement { > extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;

View File

@ -45,12 +45,11 @@ export type HaDevicePickerDeviceFilterFunc = (
export type HaDevicePickerEntityFilterFunc = (entity: HassEntity) => boolean; export type HaDevicePickerEntityFilterFunc = (entity: HassEntity) => boolean;
const rowRenderer: ComboBoxLitRenderer<Device> = (item) => html`<mwc-list-item const rowRenderer: ComboBoxLitRenderer<Device> = (item) =>
.twoline=${!!item.area} html`<mwc-list-item .twoline=${!!item.area}>
> <span>${item.name}</span>
<span>${item.name}</span> <span slot="secondary">${item.area}</span>
<span slot="secondary">${item.area}</span> </mwc-list-item>`;
</mwc-list-item>`;
@customElement("ha-device-picker") @customElement("ha-device-picker")
export class HaDevicePicker extends SubscribeMixin(LitElement) { export class HaDevicePicker extends SubscribeMixin(LitElement) {

View File

@ -130,9 +130,9 @@ class HaEntitiesPickerLight extends LitElement {
private _getEntityFilter = memoizeOne( private _getEntityFilter = memoizeOne(
( (
value: string[] | undefined, value: string[] | undefined,
entityFilter: HaEntityPickerEntityFilterFunc | undefined entityFilter: HaEntityPickerEntityFilterFunc | undefined
): HaEntityPickerEntityFilterFunc => ): HaEntityPickerEntityFilterFunc =>
(stateObj: HassEntity) => (stateObj: HassEntity) =>
(!value || !value.includes(stateObj.entity_id)) && (!value || !value.includes(stateObj.entity_id)) &&
(!entityFilter || entityFilter(stateObj)) (!entityFilter || entityFilter(stateObj))

View File

@ -87,26 +87,28 @@ export class HaStatisticPicker extends LitElement {
private _statistics: StatisticItem[] = []; private _statistics: StatisticItem[] = [];
private _rowRenderer: ComboBoxLitRenderer<StatisticItem> = ( private _rowRenderer: ComboBoxLitRenderer<StatisticItem> = (item) =>
item html`<mwc-list-item graphic="avatar" twoline>
) => html`<mwc-list-item graphic="avatar" twoline> ${item.state
${item.state ? html`<state-badge
? html`<state-badge slot="graphic" .stateObj=${item.state}></state-badge>` slot="graphic"
: ""} .stateObj=${item.state}
<span>${item.name}</span> ></state-badge>`
<span slot="secondary" : ""}
>${item.id === "" || item.id === "__missing" <span>${item.name}</span>
? html`<a <span slot="secondary"
target="_blank" >${item.id === "" || item.id === "__missing"
rel="noopener noreferrer" ? html`<a
href=${documentationUrl(this.hass, "/more-info/statistics/")} target="_blank"
>${this.hass.localize( rel="noopener noreferrer"
"ui.components.statistic-picker.learn_more" href=${documentationUrl(this.hass, "/more-info/statistics/")}
)}</a >${this.hass.localize(
>` "ui.components.statistic-picker.learn_more"
: item.id}</span )}</a
> >`
</mwc-list-item>`; : item.id}</span
>
</mwc-list-item>`;
private _getStatistics = memoizeOne( private _getStatistics = memoizeOne(
( (

View File

@ -211,7 +211,9 @@ export class StateBadge extends LitElement {
background: var(--divider-color); background: var(--divider-color);
} }
ha-state-icon { ha-state-icon {
transition: color 0.3s ease-in-out, filter 0.3s ease-in-out; transition:
color 0.3s ease-in-out,
filter 0.3s ease-in-out;
} }
.missing { .missing {
color: #fce588; color: #fce588;

View File

@ -11,19 +11,18 @@ import "./ha-combo-box";
import type { HaComboBox } from "./ha-combo-box"; import type { HaComboBox } from "./ha-combo-box";
import "./ha-list-item"; import "./ha-list-item";
const rowRenderer: ComboBoxLitRenderer<HassioAddonInfo> = ( const rowRenderer: ComboBoxLitRenderer<HassioAddonInfo> = (item) =>
item html`<ha-list-item twoline graphic="icon">
) => html`<ha-list-item twoline graphic="icon"> <span>${item.name}</span>
<span>${item.name}</span> <span slot="secondary">${item.slug}</span>
<span slot="secondary">${item.slug}</span> ${item.icon
${item.icon ? html`<img
? html`<img alt=""
alt="" slot="graphic"
slot="graphic" .src="/api/hassio/addons/${item.slug}/icon"
.src="/api/hassio/addons/${item.slug}/icon" />`
/>` : ""}
: ""} </ha-list-item>`;
</ha-list-item>`;
@customElement("ha-addon-picker") @customElement("ha-addon-picker")
class HaAddonPicker extends LitElement { class HaAddonPicker extends LitElement {

View File

@ -53,39 +53,38 @@ export class HaAnalytics extends LitElement {
</ha-switch> </ha-switch>
</ha-settings-row> </ha-settings-row>
${ADDITIONAL_PREFERENCES.map( ${ADDITIONAL_PREFERENCES.map(
(preference) => (preference) => html`
html` <ha-settings-row>
<ha-settings-row> <span slot="heading" data-for=${preference}>
<span slot="heading" data-for=${preference}> ${this.localize(
${this.localize( `ui.panel.${this.translationKeyPanel}.analytics.preferences.${preference}.title`
`ui.panel.${this.translationKeyPanel}.analytics.preferences.${preference}.title` )}
)} </span>
</span> <span slot="description" data-for=${preference}>
<span slot="description" data-for=${preference}> ${this.localize(
${this.localize( `ui.panel.${this.translationKeyPanel}.analytics.preferences.${preference}.description`
`ui.panel.${this.translationKeyPanel}.analytics.preferences.${preference}.description` )}
)} </span>
</span> <span>
<span> <ha-switch
<ha-switch @change=${this._handleRowClick}
@change=${this._handleRowClick} .checked=${this.analytics?.preferences[preference]}
.checked=${this.analytics?.preferences[preference]} .preference=${preference}
.preference=${preference} name=${preference}
name=${preference} >
> </ha-switch>
</ha-switch> ${!baseEnabled
${!baseEnabled ? html`
? html` <simple-tooltip animation-delay="0" position="right">
<simple-tooltip animation-delay="0" position="right"> ${this.localize(
${this.localize( `ui.panel.${this.translationKeyPanel}.analytics.need_base_enabled`
`ui.panel.${this.translationKeyPanel}.analytics.need_base_enabled` )}
)} </simple-tooltip>
</simple-tooltip> `
` : ""}
: ""} </span>
</span> </ha-settings-row>
</ha-settings-row> `
`
)} )}
<ha-settings-row> <ha-settings-row>
<span slot="heading" data-for="diagnostics"> <span slot="heading" data-for="diagnostics">

View File

@ -34,13 +34,12 @@ import "./ha-svg-icon";
type ScorableAreaRegistryEntry = ScorableTextItem & AreaRegistryEntry; type ScorableAreaRegistryEntry = ScorableTextItem & AreaRegistryEntry;
const rowRenderer: ComboBoxLitRenderer<AreaRegistryEntry> = ( const rowRenderer: ComboBoxLitRenderer<AreaRegistryEntry> = (item) =>
item html`<mwc-list-item
) => html`<mwc-list-item class=${classMap({ "add-new": item.area_id === "add_new" })}
class=${classMap({ "add-new": item.area_id === "add_new" })} >
> ${item.name}
${item.name} </mwc-list-item>`;
</mwc-list-item>`;
@customElement("ha-area-picker") @customElement("ha-area-picker")
export class HaAreaPicker extends LitElement { export class HaAreaPicker extends LitElement {

View File

@ -94,7 +94,9 @@ export class HaButtonToggleGroup extends LitElement {
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
content: ""; content: "";
transition: opacity 15ms linear, background-color 15ms linear; transition:
opacity 15ms linear,
background-color 15ms linear;
} }
ha-icon-button[active]::before, ha-icon-button[active]::before,
mwc-button[active]::before { mwc-button[active]::before {

View File

@ -47,29 +47,28 @@ class HaConfigEntryPicker extends LitElement {
this._getConfigEntries(); this._getConfigEntries();
} }
private _rowRenderer: ComboBoxLitRenderer<ConfigEntryExtended> = ( private _rowRenderer: ComboBoxLitRenderer<ConfigEntryExtended> = (item) =>
item html`<mwc-list-item twoline graphic="icon">
) => html`<mwc-list-item twoline graphic="icon"> <span
<span >${item.title ||
>${item.title || this.hass.localize(
this.hass.localize( "ui.panel.config.integrations.config_entry.unnamed_entry"
"ui.panel.config.integrations.config_entry.unnamed_entry" )}</span
)}</span >
> <span slot="secondary">${item.localized_domain_name}</span>
<span slot="secondary">${item.localized_domain_name}</span> <img
<img alt=""
alt="" slot="graphic"
slot="graphic" src=${brandsUrl({
src=${brandsUrl({ domain: item.domain,
domain: item.domain, type: "icon",
type: "icon", darkOptimized: this.hass.themes?.darkMode,
darkOptimized: this.hass.themes?.darkMode, })}
})} referrerpolicy="no-referrer"
referrerpolicy="no-referrer" @error=${this._onImageError}
@error=${this._onImageError} @load=${this._onImageLoad}
@load=${this._onImageLoad} />
/> </mwc-list-item>`;
</mwc-list-item>`;
protected render() { protected render() {
if (!this._configEntries) { if (!this._configEntries) {

View File

@ -122,7 +122,8 @@ export class HaControlButton extends LitElement {
height: 100%; height: 100%;
width: 100%; width: 100%;
background-color: var(--control-button-background-color); background-color: var(--control-button-background-color);
transition: background-color 180ms ease-in-out, transition:
background-color 180ms ease-in-out,
opacity 180ms ease-in-out; opacity 180ms ease-in-out;
opacity: var(--control-button-background-opacity); opacity: var(--control-button-background-opacity);
} }

View File

@ -566,7 +566,9 @@ export class HaControlCircularSlider extends LitElement {
fill: none; fill: none;
stroke: var(--control-circular-slider-background); stroke: var(--control-circular-slider-background);
opacity: var(--control-circular-slider-background-opacity); opacity: var(--control-circular-slider-background-opacity);
transition: stroke 180ms ease-in-out, opacity 180ms ease-in-out; transition:
stroke 180ms ease-in-out,
opacity 180ms ease-in-out;
stroke-linecap: round; stroke-linecap: round;
stroke-width: 24px; stroke-width: 24px;
} }
@ -576,9 +578,11 @@ export class HaControlCircularSlider extends LitElement {
fill: none; fill: none;
stroke-linecap: round; stroke-linecap: round;
stroke-width: 24px; stroke-width: 24px;
transition: stroke-width 300ms ease-in-out, transition:
stroke-width 300ms ease-in-out,
stroke-dasharray 300ms ease-in-out, stroke-dasharray 300ms ease-in-out,
stroke-dashoffset 300ms ease-in-out, stroke 180ms ease-in-out, stroke-dashoffset 300ms ease-in-out,
stroke 180ms ease-in-out,
opacity 180ms ease-in-out; opacity 180ms ease-in-out;
} }

View File

@ -283,7 +283,9 @@ export class HaControlSelect extends LitElement {
width: 100%; width: 100%;
background-color: var(--control-select-color); background-color: var(--control-select-color);
opacity: 0; opacity: 0;
transition: background-color ease-in-out 180ms, opacity ease-in-out 80ms; transition:
background-color ease-in-out 180ms,
opacity ease-in-out 80ms;
} }
.option.focused::before, .option.focused::before,
.option:hover::before { .option:hover::before {

View File

@ -327,7 +327,8 @@ export class HaControlSlider extends LitElement {
height: 100%; height: 100%;
width: 100%; width: 100%;
background-color: var(--control-slider-color); background-color: var(--control-slider-color);
transition: transform 180ms ease-in-out, transition:
transform 180ms ease-in-out,
background-color 180ms ease-in-out; background-color 180ms ease-in-out;
} }
.slider .slider-track-bar.show-handle { .slider .slider-track-bar.show-handle {
@ -427,7 +428,9 @@ export class HaControlSlider extends LitElement {
position: absolute; position: absolute;
background-color: white; background-color: white;
border-radius: var(--handle-size); border-radius: var(--handle-size);
transition: left 180ms ease-in-out, bottom 180ms ease-in-out; transition:
left 180ms ease-in-out,
bottom 180ms ease-in-out;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: calc(var(--value, 0) * (100% - var(--cursor-size))); left: calc(var(--value, 0) * (100% - var(--cursor-size)));

View File

@ -208,7 +208,8 @@ export class HaControlSwitch extends LitElement {
border-radius: calc( border-radius: calc(
var(--control-switch-border-radius) - var(--control-switch-padding) var(--control-switch-border-radius) - var(--control-switch-padding)
); );
transition: transform 180ms ease-in-out, transition:
transform 180ms ease-in-out,
background-color 180ms ease-in-out; background-color 180ms ease-in-out;
background-color: var(--control-switch-off-color); background-color: var(--control-switch-off-color);
color: white; color: white;

View File

@ -55,17 +55,16 @@ export class HaFormGrid extends LitElement implements HaFormElement {
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
${this.schema.schema.map( ${this.schema.schema.map(
(item) => (item) => html`
html` <ha-form
<ha-form .hass=${this.hass}
.hass=${this.hass} .data=${this.data}
.data=${this.data} .schema=${[item]}
.schema=${[item]} .disabled=${this.disabled}
.disabled=${this.disabled} .computeLabel=${this.computeLabel}
.computeLabel=${this.computeLabel} .computeHelper=${this.computeHelper}
.computeHelper=${this.computeHelper} ></ha-form>
></ha-form> `
`
)} )}
`; `;
} }

View File

@ -98,7 +98,7 @@ export interface HaFormTimeSchema extends HaFormBaseSchema {
// Type utility to unionize a schema array by flattening any grid schemas // Type utility to unionize a schema array by flattening any grid schemas
export type SchemaUnion< export type SchemaUnion<
SchemaArray extends readonly HaFormSchema[], SchemaArray extends readonly HaFormSchema[],
Schema = SchemaArray[number] Schema = SchemaArray[number],
> = Schema extends HaFormGridSchema | HaFormExpandableSchema > = Schema extends HaFormGridSchema | HaFormExpandableSchema
? SchemaUnion<Schema["schema"]> ? SchemaUnion<Schema["schema"]>
: Schema; : Schema;

View File

@ -138,12 +138,12 @@ export class Gauge extends LitElement {
: this.valueText || : this.valueText ||
formatNumber(this.value, this.locale, this.formatOptions) formatNumber(this.value, this.locale, this.formatOptions)
}${ }${
this._segment_label this._segment_label
? "" ? ""
: this.label === "%" : this.label === "%"
? blankBeforePercent(this.locale) + "%" ? blankBeforePercent(this.locale) + "%"
: ` ${this.label}` : ` ${this.label}`
} }
</text> </text>
</svg>`; </svg>`;
} }

View File

@ -406,7 +406,9 @@ class HaHsColorPicker extends LitElement {
filter: url(#marker-shadow); filter: url(#marker-shadow);
} }
.container:not(.pressed) circle { .container:not(.pressed) circle {
transition: transform 100ms ease-in-out, fill 100ms ease-in-out; transition:
transform 100ms ease-in-out,
fill 100ms ease-in-out;
} }
.container:not(.pressed) .cursor { .container:not(.pressed) .cursor {
transition: transform 200ms ease-in-out; transition: transform 200ms ease-in-out;

View File

@ -81,28 +81,25 @@ class HaMountPicker extends LitElement {
? dataDiskOption ? dataDiskOption
: nothing} : nothing}
${this._filterMounts(this._mounts, this.usage).map( ${this._filterMounts(this._mounts, this.usage).map(
(mount) => html`<ha-list-item (mount) =>
twoline html`<ha-list-item twoline graphic="icon" .value=${mount.name}>
graphic="icon" <span>${mount.name}</span>
.value=${mount.name} <span slot="secondary"
> >${mount.server}${mount.port
<span>${mount.name}</span> ? `:${mount.port}`
<span slot="secondary" : nothing}${mount.type === SupervisorMountType.NFS
>${mount.server}${mount.port ? mount.path
? `:${mount.port}` : `:${mount.share}`}</span
: nothing}${mount.type === SupervisorMountType.NFS >
? mount.path <ha-svg-icon
: `:${mount.share}`}</span slot="graphic"
> .path=${mount.usage === SupervisorMountUsage.MEDIA
<ha-svg-icon ? mdiPlayBox
slot="graphic" : mount.usage === SupervisorMountUsage.SHARE
.path=${mount.usage === SupervisorMountUsage.MEDIA ? mdiFolder
? mdiPlayBox : mdiBackupRestore}
: mount.usage === SupervisorMountUsage.SHARE ></ha-svg-icon>
? mdiFolder </ha-list-item>`
: mdiBackupRestore}
></ha-svg-icon>
</ha-list-item>`
)} )}
${this.usage === SupervisorMountUsage.BACKUP && ${this.usage === SupervisorMountUsage.BACKUP &&
this._mounts.default_backup_mount this._mounts.default_backup_mount

View File

@ -112,19 +112,18 @@ export class HaSelectSelector extends LitElement {
${value?.length ${value?.length
? html`<ha-chip-set> ? html`<ha-chip-set>
${value.map( ${value.map(
(item, idx) => (item, idx) => html`
html` <ha-chip hasTrailingIcon>
<ha-chip hasTrailingIcon> ${options.find((option) => option.value === item)?.label ||
${options.find((option) => option.value === item) item}
?.label || item} <ha-svg-icon
<ha-svg-icon slot="trailing-icon"
slot="trailing-icon" .path=${mdiClose}
.path=${mdiClose} .idx=${idx}
.idx=${idx} @click=${this._removeItem}
@click=${this._removeItem} ></ha-svg-icon>
></ha-svg-icon> </ha-chip>
</ha-chip> `
`
)} )}
</ha-chip-set>` </ha-chip-set>`
: ""} : ""}

View File

@ -10,12 +10,13 @@ import "./ha-combo-box";
const rowRenderer: ComboBoxLitRenderer<{ service: string; name: string }> = ( const rowRenderer: ComboBoxLitRenderer<{ service: string; name: string }> = (
item item
) => html`<mwc-list-item twoline> ) =>
<span>${item.name}</span> html`<mwc-list-item twoline>
<span slot="secondary" <span>${item.name}</span>
>${item.name === item.service ? "" : item.service}</span <span slot="secondary"
> >${item.name === item.service ? "" : item.service}</span
</mwc-list-item>`; >
</mwc-list-item>`;
@customElement("ha-service-picker") @customElement("ha-service-picker")
class HaServicePicker extends LitElement { class HaServicePicker extends LitElement {

View File

@ -418,7 +418,9 @@ class HaTempColorPicker extends LitElement {
filter: url(#marker-shadow); filter: url(#marker-shadow);
} }
.container:not(.pressed) circle { .container:not(.pressed) circle {
transition: transform 100ms ease-in-out, fill 100ms ease-in-out; transition:
transform 100ms ease-in-out,
fill 100ms ease-in-out;
} }
.container:not(.pressed) .cursor { .container:not(.pressed) .cursor {
transition: transform 200ms ease-in-out; transition: transform 200ms ease-in-out;

View File

@ -62,9 +62,10 @@ export class HaTTSVoicePicker extends LitElement {
</ha-list-item>` </ha-list-item>`
: nothing} : nothing}
${this._voices.map( ${this._voices.map(
(voice) => html`<ha-list-item .value=${voice.voice_id}> (voice) =>
${voice.name} html`<ha-list-item .value=${voice.voice_id}>
</ha-list-item>` ${voice.name}
</ha-list-item>`
)} )}
</ha-select> </ha-select>
`; `;

View File

@ -930,7 +930,9 @@ export class HaMediaPlayerBrowse extends LitElement {
margin-right: 16px; margin-right: 16px;
background-size: cover; background-size: cover;
border-radius: 2px; border-radius: 2px;
transition: width 0.4s, height 0.4s; transition:
width 0.4s,
height 0.4s;
} }
.header-info { .header-info {
display: flex; display: flex;
@ -977,7 +979,9 @@ export class HaMediaPlayerBrowse extends LitElement {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
margin-bottom: 0; margin-bottom: 0;
transition: height 0.5s, margin 0.5s; transition:
height 0.5s,
margin 0.5s;
} }
.not-shown { .not-shown {
@ -1121,7 +1125,9 @@ export class HaMediaPlayerBrowse extends LitElement {
top: auto; top: auto;
bottom: 0px; bottom: 0px;
right: 8px; right: 8px;
transition: bottom 0.1s ease-out, opacity 0.1s ease-out; transition:
bottom 0.1s ease-out,
opacity 0.1s ease-out;
} }
.child .play:hover { .child .play:hover {
@ -1220,7 +1226,10 @@ export class HaMediaPlayerBrowse extends LitElement {
position: relative; position: relative;
background-position: center; background-position: center;
border-radius: 0; border-radius: 0;
transition: width 0.4s, height 0.4s, padding-bottom 0.4s; transition:
width 0.4s,
height 0.4s,
padding-bottom 0.4s;
} }
ha-fab { ha-fab {
position: absolute; position: absolute;

View File

@ -40,38 +40,40 @@ class HaUsersPickerLight extends LitElement {
const notSelectedUsers = this._notSelectedUsers(this.users, this.value); const notSelectedUsers = this._notSelectedUsers(this.users, this.value);
return html` return html`
${guard([notSelectedUsers], () => ${guard(
this.value?.map( [notSelectedUsers],
(user_id, idx) => html` () =>
<div> this.value?.map(
<ha-user-picker (user_id, idx) => html`
.label=${this.pickedUserLabel} <div>
.noUserLabel=${this.hass!.localize( <ha-user-picker
"ui.components.user-picker.remove_user" .label=${this.pickedUserLabel}
)} .noUserLabel=${this.hass!.localize(
.index=${idx} "ui.components.user-picker.remove_user"
.hass=${this.hass} )}
.value=${user_id} .index=${idx}
.users=${this._notSelectedUsersAndSelected( .hass=${this.hass}
user_id, .value=${user_id}
this.users, .users=${this._notSelectedUsersAndSelected(
notSelectedUsers user_id,
)} this.users,
@value-changed=${this._userChanged} notSelectedUsers
></ha-user-picker> )}
<ha-icon-button @value-changed=${this._userChanged}
.userId=${user_id} ></ha-user-picker>
.label=${this.hass!.localize( <ha-icon-button
"ui.components.user-picker.remove_user" .userId=${user_id}
)} .label=${this.hass!.localize(
.path=${mdiClose} "ui.components.user-picker.remove_user"
@click=${this._removeUser} )}
> .path=${mdiClose}
></ha-icon-button @click=${this._removeUser}
> >
</div> ></ha-icon-button
` >
) </div>
`
)
)} )}
<ha-user-picker <ha-user-picker
.label=${this.pickUserLabel || .label=${this.pickUserLabel ||

View File

@ -13,7 +13,7 @@ interface InvalidConfig {
type ValidKeys = "trigger" | "action" | "condition"; type ValidKeys = "trigger" | "action" | "condition";
export const validateConfig = < export const validateConfig = <
T extends Partial<{ [key in ValidKeys]: unknown }> T extends Partial<{ [key in ValidKeys]: unknown }>,
>( >(
hass: HomeAssistant, hass: HomeAssistant,
config: T config: T

View File

@ -14,7 +14,7 @@ declare global {
export type ValidUserDataKey = keyof FrontendUserData; export type ValidUserDataKey = keyof FrontendUserData;
export const fetchFrontendUserData = async < export const fetchFrontendUserData = async <
UserDataKey extends ValidUserDataKey UserDataKey extends ValidUserDataKey,
>( >(
conn: Connection, conn: Connection,
key: UserDataKey key: UserDataKey
@ -29,7 +29,7 @@ export const fetchFrontendUserData = async <
}; };
export const saveFrontendUserData = async < export const saveFrontendUserData = async <
UserDataKey extends ValidUserDataKey UserDataKey extends ValidUserDataKey,
>( >(
conn: Connection, conn: Connection,
key: UserDataKey, key: UserDataKey,
@ -42,7 +42,7 @@ export const saveFrontendUserData = async <
}); });
export const getOptimisticFrontendUserDataCollection = < export const getOptimisticFrontendUserDataCollection = <
UserDataKey extends ValidUserDataKey UserDataKey extends ValidUserDataKey,
>( >(
conn: Connection, conn: Connection,
userDataKey: UserDataKey userDataKey: UserDataKey

View File

@ -145,21 +145,20 @@ export interface DeviceSelector {
} }
export interface LegacyDeviceSelector { export interface LegacyDeviceSelector {
device: device: DeviceSelector["device"] & {
| DeviceSelector["device"] & { /**
/** * @deprecated Use filter instead
* @deprecated Use filter instead */
*/ integration?: DeviceSelectorFilter["integration"];
integration?: DeviceSelectorFilter["integration"]; /**
/** * @deprecated Use filter instead
* @deprecated Use filter instead */
*/ manufacturer?: DeviceSelectorFilter["manufacturer"];
manufacturer?: DeviceSelectorFilter["manufacturer"]; /**
/** * @deprecated Use filter instead
* @deprecated Use filter instead */
*/ model?: DeviceSelectorFilter["model"];
model?: DeviceSelectorFilter["model"]; };
};
} }
export interface DurationSelector { export interface DurationSelector {
@ -185,21 +184,20 @@ export interface EntitySelector {
} }
export interface LegacyEntitySelector { export interface LegacyEntitySelector {
entity: entity: EntitySelector["entity"] & {
| EntitySelector["entity"] & { /**
/** * @deprecated Use filter instead
* @deprecated Use filter instead */
*/ integration?: EntitySelectorFilter["integration"];
integration?: EntitySelectorFilter["integration"]; /**
/** * @deprecated Use filter instead
* @deprecated Use filter instead */
*/ domain?: EntitySelectorFilter["domain"];
domain?: EntitySelectorFilter["domain"]; /**
/** * @deprecated Use filter instead
* @deprecated Use filter instead */
*/ device_class?: EntitySelectorFilter["device_class"];
device_class?: EntitySelectorFilter["device_class"]; };
};
} }
export interface StatisticSelector { export interface StatisticSelector {

View File

@ -48,26 +48,25 @@ class StepFlowCreateEntry extends LitElement {
</p> </p>
<div class="devices"> <div class="devices">
${this.devices.map( ${this.devices.map(
(device) => (device) => html`
html` <div class="device">
<div class="device"> <div>
<div> <b>${computeDeviceName(device, this.hass)}</b><br />
<b>${computeDeviceName(device, this.hass)}</b><br /> ${!device.model && !device.manufacturer
${!device.model && !device.manufacturer ? html`&nbsp;`
? html`&nbsp;` : html`${device.model}
: html`${device.model} ${device.manufacturer
${device.manufacturer ? html`(${device.manufacturer})`
? html`(${device.manufacturer})` : ""}`}
: ""}`}
</div>
<ha-area-picker
.hass=${this.hass}
.device=${device.id}
.value=${device.area_id ?? undefined}
@value-changed=${this._areaPicked}
></ha-area-picker>
</div> </div>
` <ha-area-picker
.hass=${this.hass}
.device=${device.id}
.value=${device.area_id ?? undefined}
@value-changed=${this._areaPicked}
></ha-area-picker>
</div>
`
)} )}
</div> </div>
`} `}

View File

@ -150,22 +150,21 @@ class DialogLightColorFavorite extends LitElement {
? html` ? html`
<div class="modes"> <div class="modes">
${this._modes.map( ${this._modes.map(
(value) => (value) => html`
html` <ha-icon-button-toggle
<ha-icon-button-toggle border-only
border-only .selected=${value === this._mode}
.selected=${value === this._mode} .label=${this.hass.localize(
.label=${this.hass.localize( `ui.dialogs.more_info_control.light.color_picker.mode.${value}`
`ui.dialogs.more_info_control.light.color_picker.mode.${value}` )}
)} .mode=${value}
.mode=${value} @click=${this._modeChanged}
@click=${this._modeChanged} >
> <span
<span class="wheel ${classMap({ [value]: true })}"
class="wheel ${classMap({ [value]: true })}" ></span>
></span> </ha-icon-button-toggle>
</ha-icon-button-toggle> `
`
)} )}
</div> </div>
` `

View File

@ -415,7 +415,7 @@ class LightRgbColorPicker extends LitElement {
number, number,
number, number,
number, number,
number number,
]; ];
this._applyColor({ rgbww_color }); this._applyColor({ rgbww_color });
} else if (lightSupportsColorMode(this.stateObj!, LightColorMode.RGBW)) { } else if (lightSupportsColorMode(this.stateObj!, LightColorMode.RGBW)) {
@ -427,7 +427,7 @@ class LightRgbColorPicker extends LitElement {
number, number,
number, number,
number, number,
number number,
]; ];
this._applyColor({ rgbw_color }); this._applyColor({ rgbw_color });
} }

View File

@ -36,12 +36,13 @@ export class MoreInfoConfigurator extends LitElement {
</ha-alert>` </ha-alert>`
: ""} : ""}
${this.stateObj.attributes.fields.map( ${this.stateObj.attributes.fields.map(
(field) => html`<ha-textfield (field) =>
.label=${field.name} html`<ha-textfield
.name=${field.id} .label=${field.name}
.type=${field.type} .name=${field.id}
@change=${this._fieldChanged} .type=${field.type}
></ha-textfield>` @change=${this._fieldChanged}
></ha-textfield>`
)} )}
${this.stateObj.attributes.submit_caption ${this.stateObj.attributes.submit_caption
? html`<p class="submit"> ? html`<p class="submit">

View File

@ -299,23 +299,22 @@ class MoreInfoFan extends LitElement {
></ha-svg-icon> ></ha-svg-icon>
</ha-outlined-button> </ha-outlined-button>
${this.stateObj.attributes.preset_modes?.map( ${this.stateObj.attributes.preset_modes?.map(
(mode) => (mode) => html`
html` <ha-list-item
<ha-list-item .value=${mode}
.value=${mode} .activated=${this._presetMode === mode}
.activated=${this._presetMode === mode} >
> ${computeAttributeValueDisplay(
${computeAttributeValueDisplay( this.hass.localize,
this.hass.localize, this.stateObj!,
this.stateObj!, this.hass.locale,
this.hass.locale, this.hass.config,
this.hass.config, this.hass.entities,
this.hass.entities, "preset_mode",
"preset_mode", mode
mode )}
)} </ha-list-item>
</ha-list-item> `
`
)} )}
</ha-button-menu> </ha-button-menu>
` `

View File

@ -156,20 +156,19 @@ class MoreInfoMediaPlayer extends LitElement {
@closed=${stopPropagation} @closed=${stopPropagation}
> >
${stateObj.attributes.source_list!.map( ${stateObj.attributes.source_list!.map(
(source) => (source) => html`
html` <mwc-list-item .value=${source}
<mwc-list-item .value=${source} >${computeAttributeValueDisplay(
>${computeAttributeValueDisplay( this.hass.localize,
this.hass.localize, stateObj,
stateObj, this.hass.locale,
this.hass.locale, this.hass.config,
this.hass.config, this.hass.entities,
this.hass.entities, "source",
"source", source
source )}</mwc-list-item
)}</mwc-list-item >
> `
`
)} )}
<ha-svg-icon .path=${mdiLoginVariant} slot="icon"></ha-svg-icon> <ha-svg-icon .path=${mdiLoginVariant} slot="icon"></ha-svg-icon>
</ha-select> </ha-select>

View File

@ -108,12 +108,13 @@ export class HuiNotificationDrawer extends LitElement {
<div class="notifications"> <div class="notifications">
${notifications.length ${notifications.length
? html`${notifications.map( ? html`${notifications.map(
(notification) => html`<div class="notification"> (notification) =>
<notification-item html`<div class="notification">
.hass=${this.hass} <notification-item
.notification=${notification} .hass=${this.hass}
></notification-item> .notification=${notification}
</div>` ></notification-item>
</div>`
)} )}
${this._notifications.length > 1 ${this._notifications.length > 1
? html`<div class="notification-actions"> ? html`<div class="notification-actions">

View File

@ -158,20 +158,24 @@ export class HaVoiceCommandDialog extends LitElement {
></ha-svg-icon> ></ha-svg-icon>
</ha-button> </ha-button>
${this._pipelines?.map( ${this._pipelines?.map(
(pipeline) => html`<ha-list-item (pipeline) =>
?selected=${pipeline.id === this._pipelineId || html`<ha-list-item
(!this._pipelineId && ?selected=${pipeline.id === this._pipelineId ||
pipeline.id === this._preferredPipeline)} (!this._pipelineId &&
.pipeline=${pipeline.id} pipeline.id === this._preferredPipeline)}
@click=${this._selectPipeline} .pipeline=${pipeline.id}
.hasMeta=${pipeline.id === this._preferredPipeline} @click=${this._selectPipeline}
> .hasMeta=${pipeline.id === this._preferredPipeline}
${pipeline.name}${pipeline.id === this._preferredPipeline >
? html` ${pipeline.name}${pipeline.id === this._preferredPipeline
<ha-svg-icon slot="meta" .path=${mdiStar}></ha-svg-icon> ? html`
` <ha-svg-icon
: nothing} slot="meta"
</ha-list-item>` .path=${mdiStar}
></ha-svg-icon>
`
: nothing}
</ha-list-item>`
)} )}
${this.hass.user?.is_admin ${this.hass.user?.is_admin
? html`<li divider role="separator"></li> ? html`<li divider role="separator"></li>

View File

@ -94,26 +94,25 @@ class HassTabsSubpage extends LitElement {
} }
return shownTabs.map( return shownTabs.map(
(page) => (page) => html`
html` <a href=${page.path}>
<a href=${page.path}> <ha-tab
<ha-tab .hass=${this.hass}
.hass=${this.hass} .active=${page.path === activeTab?.path}
.active=${page.path === activeTab?.path} .narrow=${this.narrow}
.narrow=${this.narrow} .name=${page.translationKey
.name=${page.translationKey ? localizeFunc(page.translationKey)
? localizeFunc(page.translationKey) : page.name}
: page.name} >
> ${page.iconPath
${page.iconPath ? html`<ha-svg-icon
? html`<ha-svg-icon slot="icon"
slot="icon" .path=${page.iconPath}
.path=${page.iconPath} ></ha-svg-icon>`
></ha-svg-icon>` : ""}
: ""} </ha-tab>
</ha-tab> </a>
</a> `
`
); );
} }
); );

View File

@ -79,23 +79,22 @@ class PanelCalendar extends LitElement {
${this.hass.localize("ui.components.calendar.my_calendars")} ${this.hass.localize("ui.components.calendar.my_calendars")}
</div> </div>
${this._calendars.map( ${this._calendars.map(
(selCal) => (selCal) => html`
html` <div>
<div> <mwc-formfield .label=${selCal.name}>
<mwc-formfield .label=${selCal.name}> <mwc-checkbox
<mwc-checkbox style=${styleMap({
style=${styleMap({ "--mdc-theme-secondary": selCal.backgroundColor!,
"--mdc-theme-secondary": selCal.backgroundColor!, })}
})} .value=${selCal.entity_id}
.value=${selCal.entity_id} .checked=${!this._deSelectedCalendars.includes(
.checked=${!this._deSelectedCalendars.includes( selCal.entity_id
selCal.entity_id )}
)} @change=${this._handleToggle}
@change=${this._handleToggle} ></mwc-checkbox>
></mwc-checkbox> </mwc-formfield>
</mwc-formfield> </div>
</div> `
`
)} )}
</div> </div>
<ha-full-calendar <ha-full-calendar

View File

@ -28,9 +28,10 @@ interface Domain {
name: string; name: string;
} }
const rowRenderer: ComboBoxLitRenderer<Domain> = (item) => html`<mwc-list-item> const rowRenderer: ComboBoxLitRenderer<Domain> = (item) =>
<span>${item.name}</span> html`<mwc-list-item>
</mwc-list-item>`; <span>${item.name}</span>
</mwc-list-item>`;
@customElement("dialog-add-application-credential") @customElement("dialog-add-application-credential")
export class DialogAddApplicationCredential extends LitElement { export class DialogAddApplicationCredential extends LitElement {

View File

@ -283,15 +283,14 @@ class HaConfigAreaPage extends SubscribeMixin(LitElement) {
.header=${this.hass.localize("ui.panel.config.devices.caption")} .header=${this.hass.localize("ui.panel.config.devices.caption")}
>${devices.length >${devices.length
? devices.map( ? devices.map(
(device) => (device) => html`
html` <a href="/config/devices/device/${device.id}">
<a href="/config/devices/device/${device.id}"> <paper-item>
<paper-item> <paper-item-body> ${device.name} </paper-item-body>
<paper-item-body> ${device.name} </paper-item-body> <ha-icon-next></ha-icon-next>
<ha-icon-next></ha-icon-next> </paper-item>
</paper-item> </a>
</a> `
`
) )
: html` : html`
<paper-item class="no-link" <paper-item class="no-link"

View File

@ -109,64 +109,65 @@ export class HaChooseAction extends LitElement implements ActionElement {
return html` return html`
${(action.choose ? ensureArray(action.choose) : []).map( ${(action.choose ? ensureArray(action.choose) : []).map(
(option, idx) => html`<ha-card> (option, idx) =>
<ha-expansion-panel html`<ha-card>
leftChevron <ha-expansion-panel
@expanded-changed=${this._expandedChanged} leftChevron
> @expanded-changed=${this._expandedChanged}
<h3 slot="header"> >
${this.hass.localize( <h3 slot="header">
"ui.panel.config.automation.editor.actions.type.choose.option", ${this.hass.localize(
"number", "ui.panel.config.automation.editor.actions.type.choose.option",
idx + 1 "number",
)}: idx + 1
${this._getDescription(option, idx)} )}:
</h3> ${this._getDescription(option, idx)}
</h3>
<ha-icon-button <ha-icon-button
slot="icons" slot="icons"
.idx=${idx} .idx=${idx}
.disabled=${this.disabled} .disabled=${this.disabled}
@click=${this._removeOption} @click=${this._removeOption}
.label=${this.hass.localize( .label=${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.choose.remove_option" "ui.panel.config.automation.editor.actions.type.choose.remove_option"
)}
.path=${mdiDelete}
></ha-icon-button>
<div class="card-content">
<h4>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.choose.conditions"
)}:
</h4>
<ha-automation-condition
nested
.conditions=${ensureArray<string | Condition>(
option.conditions
)} )}
.reOrderMode=${this.reOrderMode} .path=${mdiDelete}
.disabled=${this.disabled} ></ha-icon-button>
.hass=${this.hass} <div class="card-content">
.idx=${idx} <h4>
@value-changed=${this._conditionChanged} ${this.hass.localize(
></ha-automation-condition> "ui.panel.config.automation.editor.actions.type.choose.conditions"
<h4> )}:
${this.hass.localize( </h4>
"ui.panel.config.automation.editor.actions.type.choose.sequence" <ha-automation-condition
)}: nested
</h4> .conditions=${ensureArray<string | Condition>(
<ha-automation-action option.conditions
nested )}
.actions=${ensureArray(option.sequence) || []} .reOrderMode=${this.reOrderMode}
.reOrderMode=${this.reOrderMode} .disabled=${this.disabled}
.disabled=${this.disabled} .hass=${this.hass}
.hass=${this.hass} .idx=${idx}
.idx=${idx} @value-changed=${this._conditionChanged}
@value-changed=${this._actionChanged} ></ha-automation-condition>
></ha-automation-action> <h4>
</div> ${this.hass.localize(
</ha-expansion-panel> "ui.panel.config.automation.editor.actions.type.choose.sequence"
</ha-card>` )}:
</h4>
<ha-automation-action
nested
.actions=${ensureArray(option.sequence) || []}
.reOrderMode=${this.reOrderMode}
.disabled=${this.disabled}
.hass=${this.hass}
.idx=${idx}
@value-changed=${this._actionChanged}
></ha-automation-action>
</div>
</ha-expansion-panel>
</ha-card>`
)} )}
<ha-button <ha-button
outlined outlined

View File

@ -212,70 +212,69 @@ class HaAutomationPicker extends LitElement {
title: "", title: "",
width: this.narrow ? undefined : "10%", width: this.narrow ? undefined : "10%",
type: "overflow-menu", type: "overflow-menu",
template: (_: string, automation: any) => template: (_: string, automation: any) => html`
html` <ha-icon-overflow-menu
<ha-icon-overflow-menu .hass=${this.hass}
.hass=${this.hass} narrow
narrow .items=${[
.items=${[ {
{ path: mdiInformationOutline,
path: mdiInformationOutline, label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.automation.editor.show_info"
"ui.panel.config.automation.editor.show_info" ),
), action: () => this._showInfo(automation),
action: () => this._showInfo(automation), },
}, {
{ path: mdiPlay,
path: mdiPlay, label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.automation.editor.run"
"ui.panel.config.automation.editor.run" ),
), action: () => this._runActions(automation),
action: () => this._runActions(automation), },
}, {
{ path: mdiTransitConnection,
path: mdiTransitConnection, label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.automation.editor.show_trace"
"ui.panel.config.automation.editor.show_trace" ),
), action: () => this._showTrace(automation),
action: () => this._showTrace(automation), },
}, {
{ divider: true,
divider: true, },
}, {
{ path: mdiContentDuplicate,
path: mdiContentDuplicate, label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.automation.picker.duplicate"
"ui.panel.config.automation.picker.duplicate" ),
), action: () => this.duplicate(automation),
action: () => this.duplicate(automation), },
}, {
{ path:
path: automation.state === "off"
automation.state === "off" ? mdiPlayCircleOutline
? mdiPlayCircleOutline : mdiStopCircleOutline,
: mdiStopCircleOutline, label:
label: automation.state === "off"
automation.state === "off" ? this.hass.localize(
? this.hass.localize( "ui.panel.config.automation.editor.enable"
"ui.panel.config.automation.editor.enable" )
) : this.hass.localize(
: this.hass.localize( "ui.panel.config.automation.editor.disable"
"ui.panel.config.automation.editor.disable" ),
), action: () => this._toggle(automation),
action: () => this._toggle(automation), },
}, {
{ label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.automation.picker.delete"
"ui.panel.config.automation.picker.delete" ),
), path: mdiDelete,
path: mdiDelete, action: () => this._deleteConfirm(automation),
action: () => this._deleteConfirm(automation), warning: true,
warning: true, },
}, ]}
]} >
> </ha-icon-overflow-menu>
</ha-icon-overflow-menu> `,
`,
}; };
return columns; return columns;
} }

View File

@ -133,110 +133,107 @@ export class ThingTalkPlaceholders extends SubscribeMixin(LitElement) {
<div> <div>
${this._error ? html` <div class="error">${this._error}</div> ` : ""} ${this._error ? html` <div class="error">${this._error}</div> ` : ""}
${Object.entries(this.placeholders).map( ${Object.entries(this.placeholders).map(
([type, placeholders]) => ([type, placeholders]) => html`
html` <h3>
<h3> ${this.hass.localize(
${this.hass.localize( `ui.panel.config.automation.editor.${type}s.name`
`ui.panel.config.automation.editor.${type}s.name` )}:
)}: </h3>
</h3> ${placeholders.map((placeholder) => {
${placeholders.map((placeholder) => { if (placeholder.fields.includes("device_id")) {
if (placeholder.fields.includes("device_id")) { const extraInfo = getPath(this._extraInfo, [
const extraInfo = getPath(this._extraInfo, [ type,
type, placeholder.index,
placeholder.index, ]);
]);
return html`
<ha-area-devices-picker
.type=${type}
.placeholder=${placeholder}
@value-changed=${this._devicePicked}
.hass=${this.hass}
.area=${extraInfo ? extraInfo.area_id : undefined}
.devices=${extraInfo && extraInfo.device_ids
? extraInfo.device_ids
: undefined}
.includeDomains=${placeholder.domains}
.includeDeviceClasses=${placeholder.device_classes}
.label=${this._getLabel(
placeholder.domains,
placeholder.device_classes
)}
></ha-area-devices-picker>
${extraInfo && extraInfo.manualEntity
? html`
<h3>
${this.hass.localize(
`ui.panel.config.automation.thingtalk.link_devices.ambiguous_entities`
)}
</h3>
${Object.keys(extraInfo.manualEntity).map(
(idx) => html`
<ha-entity-picker
id="device-entity-picker"
.type=${type}
.placeholder=${placeholder}
.index=${idx}
@change=${this._entityPicked}
.includeDomains=${placeholder.domains}
.includeDeviceClasses=${placeholder.device_classes}
.hass=${this.hass}
.label=${`${this._getLabel(
placeholder.domains,
placeholder.device_classes
)} of device ${this._getDeviceName(
getPath(this._placeholderValues, [
type,
placeholder.index,
idx,
"device_id",
])
)}`}
.entityFilter=${(entityState: HassEntity) => {
const devId =
this._placeholderValues[type][
placeholder.index
][idx].device_id;
return this._deviceEntityLookup[
devId
].includes(entityState.entity_id);
}}
></ha-entity-picker>
`
)}
`
: ""}
`;
}
if (placeholder.fields.includes("entity_id")) {
return html`
<ha-entity-picker
.type=${type}
.placeholder=${placeholder}
@change=${this._entityPicked}
.includeDomains=${placeholder.domains}
.includeDeviceClasses=${placeholder.device_classes}
.hass=${this.hass}
.label=${this._getLabel(
placeholder.domains,
placeholder.device_classes
)}
></ha-entity-picker>
`;
}
return html` return html`
<div class="error"> <ha-area-devices-picker
${this.hass.localize( .type=${type}
`ui.panel.config.automation.thingtalk.link_devices.unknown_placeholder` .placeholder=${placeholder}
)}<br /> @value-changed=${this._devicePicked}
${placeholder.domains}<br /> .hass=${this.hass}
${placeholder.fields.map( .area=${extraInfo ? extraInfo.area_id : undefined}
(field) => html` ${field}<br /> ` .devices=${extraInfo && extraInfo.device_ids
? extraInfo.device_ids
: undefined}
.includeDomains=${placeholder.domains}
.includeDeviceClasses=${placeholder.device_classes}
.label=${this._getLabel(
placeholder.domains,
placeholder.device_classes
)} )}
</div> ></ha-area-devices-picker>
${extraInfo && extraInfo.manualEntity
? html`
<h3>
${this.hass.localize(
`ui.panel.config.automation.thingtalk.link_devices.ambiguous_entities`
)}
</h3>
${Object.keys(extraInfo.manualEntity).map(
(idx) => html`
<ha-entity-picker
id="device-entity-picker"
.type=${type}
.placeholder=${placeholder}
.index=${idx}
@change=${this._entityPicked}
.includeDomains=${placeholder.domains}
.includeDeviceClasses=${placeholder.device_classes}
.hass=${this.hass}
.label=${`${this._getLabel(
placeholder.domains,
placeholder.device_classes
)} of device ${this._getDeviceName(
getPath(this._placeholderValues, [
type,
placeholder.index,
idx,
"device_id",
])
)}`}
.entityFilter=${(entityState: HassEntity) => {
const devId =
this._placeholderValues[type][
placeholder.index
][idx].device_id;
return this._deviceEntityLookup[
devId
].includes(entityState.entity_id);
}}
></ha-entity-picker>
`
)}
`
: ""}
`; `;
})} }
` if (placeholder.fields.includes("entity_id")) {
return html`
<ha-entity-picker
.type=${type}
.placeholder=${placeholder}
@change=${this._entityPicked}
.includeDomains=${placeholder.domains}
.includeDeviceClasses=${placeholder.device_classes}
.hass=${this.hass}
.label=${this._getLabel(
placeholder.domains,
placeholder.device_classes
)}
></ha-entity-picker>
`;
}
return html`
<div class="error">
${this.hass.localize(
`ui.panel.config.automation.thingtalk.link_devices.unknown_placeholder`
)}<br />
${placeholder.domains}<br />
${placeholder.fields.map((field) => html` ${field}<br /> `)}
</div>
`;
})}
`
)} )}
</div> </div>
<mwc-button @click=${this.skip} slot="secondaryAction"> <mwc-button @click=${this.skip} slot="secondaryAction">

View File

@ -125,11 +125,10 @@ class HaBlueprintOverview extends LitElement {
direction: "asc", direction: "asc",
grows: true, grows: true,
template: narrow template: narrow
? (name, entity: any) => ? (name, entity: any) => html`
html` ${name}<br />
${name}<br /> <div class="secondary">${entity.path}</div>
<div class="secondary">${entity.path}</div> `
`
: undefined, : undefined,
}, },
type: { type: {

View File

@ -181,9 +181,8 @@ class HaConfigSystemNavigation extends LitElement {
const hardwareInfo: HardwareInfo = await this.hass.callWS({ const hardwareInfo: HardwareInfo = await this.hass.callWS({
type: "hardware/info", type: "hardware/info",
}); });
this._boardName = hardwareInfo?.hardware.find( this._boardName = hardwareInfo?.hardware.find((hw) => hw.board !== null)
(hw) => hw.board !== null ?.name;
)?.name;
} else if (isHassioLoaded) { } else if (isHassioLoaded) {
const osData: HassioHassOSInfo = await fetchHassioHassOsInfo(this.hass); const osData: HassioHassOSInfo = await fetchHassioHassOsInfo(this.hass);
if (osData.board) { if (osData.board) {

View File

@ -20,7 +20,7 @@ declare global {
} }
export abstract class HaDeviceAutomationCard< export abstract class HaDeviceAutomationCard<
T extends DeviceAutomation T extends DeviceAutomation,
> extends LitElement { > extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@ -76,20 +76,19 @@ export abstract class HaDeviceAutomationCard<
<div class="content"> <div class="content">
<ha-chip-set> <ha-chip-set>
${automations.map( ${automations.map(
(automation, idx) => (automation, idx) => html`
html` <ha-chip
<ha-chip .index=${idx}
.index=${idx} @click=${this._handleAutomationClicked}
@click=${this._handleAutomationClicked} class=${automation.metadata?.secondary ? "secondary" : ""}
class=${automation.metadata?.secondary ? "secondary" : ""} >
> ${this._localizeDeviceAutomation(
${this._localizeDeviceAutomation( this.hass,
this.hass, this.entityReg!,
this.entityReg!, automation
automation )}
)} </ha-chip>
</ha-chip> `
`
)} )}
</ha-chip-set> </ha-chip-set>
${!this._showSecondary && automations.length < this.automations.length ${!this._showSecondary && automations.length < this.automations.length

View File

@ -376,32 +376,30 @@ export class HaConfigDevicePage extends LitElement {
const firstDeviceAction = actions.shift(); const firstDeviceAction = actions.shift();
if (device.disabled_by) { if (device.disabled_by) {
deviceInfo.push( deviceInfo.push(html`
html` <ha-alert alert-type="warning">
<ha-alert alert-type="warning"> ${this.hass.localize(
${this.hass.localize( "ui.panel.config.devices.enabled_cause",
"ui.panel.config.devices.enabled_cause", "type",
"type", this.hass.localize(
this.hass.localize( `ui.panel.config.devices.type.${device.entry_type || "device"}`
`ui.panel.config.devices.type.${device.entry_type || "device"}` ),
), "cause",
"cause", this.hass.localize(
this.hass.localize( `ui.panel.config.devices.disabled_by.${device.disabled_by}`
`ui.panel.config.devices.disabled_by.${device.disabled_by}` )
) )}
)} </ha-alert>
</ha-alert> ${device.disabled_by === "user"
${device.disabled_by === "user" ? html`
? html` <div class="card-actions" slot="actions">
<div class="card-actions" slot="actions"> <mwc-button unelevated @click=${this._enableDevice}>
<mwc-button unelevated @click=${this._enableDevice}> ${this.hass.localize("ui.common.enable")}
${this.hass.localize("ui.common.enable")} </mwc-button>
</mwc-button> </div>
</div> `
` : ""}
: ""} `);
`
);
} }
this._renderIntegrationInfo(device, integrations, deviceInfo); this._renderIntegrationInfo(device, integrations, deviceInfo);
@ -751,12 +749,11 @@ export class HaConfigDevicePage extends LitElement {
? html` ? html`
<div> <div>
${this._deviceAlerts.map( ${this._deviceAlerts.map(
(alert) => (alert) => html`
html` <ha-alert .alertType=${alert.level}>
<ha-alert .alertType=${alert.level}> ${alert.text}
${alert.text} </ha-alert>
</ha-alert> `
`
)} )}
</div> </div>
` `

View File

@ -76,13 +76,12 @@ export class EnergyBatterySettings extends LitElement {
> >
</p> </p>
${batteryValidation.map( ${batteryValidation.map(
(result) => (result) => html`
html` <ha-energy-validation-result
<ha-energy-validation-result .hass=${this.hass}
.hass=${this.hass} .issues=${result}
.issues=${result} ></ha-energy-validation-result>
></ha-energy-validation-result> `
`
)} )}
<h3> <h3>

View File

@ -68,13 +68,12 @@ export class EnergyDeviceSettings extends LitElement {
> >
</p> </p>
${this.validationResult?.device_consumption.map( ${this.validationResult?.device_consumption.map(
(result) => (result) => html`
html` <ha-energy-validation-result
<ha-energy-validation-result .hass=${this.hass}
.hass=${this.hass} .issues=${result}
.issues=${result} ></ha-energy-validation-result>
></ha-energy-validation-result> `
`
)} )}
<h3> <h3>
${this.hass.localize( ${this.hass.localize(

View File

@ -74,13 +74,12 @@ export class EnergyGasSettings extends LitElement {
> >
</p> </p>
${gasValidation.map( ${gasValidation.map(
(result) => (result) => html`
html` <ha-energy-validation-result
<ha-energy-validation-result .hass=${this.hass}
.hass=${this.hass} .issues=${result}
.issues=${result} ></ha-energy-validation-result>
></ha-energy-validation-result> `
`
)} )}
<h3> <h3>
${this.hass.localize("ui.panel.config.energy.gas.gas_consumption")} ${this.hass.localize("ui.panel.config.energy.gas.gas_consumption")}

View File

@ -79,13 +79,12 @@ export class EnergySolarSettings extends LitElement {
> >
</p> </p>
${solarValidation.map( ${solarValidation.map(
(result) => (result) => html`
html` <ha-energy-validation-result
<ha-energy-validation-result .hass=${this.hass}
.hass=${this.hass} .issues=${result}
.issues=${result} ></ha-energy-validation-result>
></ha-energy-validation-result> `
`
)} )}
<h3> <h3>

View File

@ -75,13 +75,12 @@ export class EnergyWaterSettings extends LitElement {
> >
</p> </p>
${waterValidation.map( ${waterValidation.map(
(result) => (result) => html`
html` <ha-energy-validation-result
<ha-energy-validation-result .hass=${this.hass}
.hass=${this.hass} .issues=${result}
.issues=${result} ></ha-energy-validation-result>
></ha-energy-validation-result> `
`
)} )}
<h3> <h3>
${this.hass.localize( ${this.hass.localize(

View File

@ -139,31 +139,32 @@ export class DialogEnergySolarSettings
${this._forecast ${this._forecast
? html`<div class="forecast-options"> ? html`<div class="forecast-options">
${this._configEntries?.map( ${this._configEntries?.map(
(entry) => html`<ha-formfield (entry) =>
.label=${html`<div html`<ha-formfield
style="display: flex; align-items: center;" .label=${html`<div
style="display: flex; align-items: center;"
>
<img
alt=""
referrerpolicy="no-referrer"
style="height: 24px; margin-right: 16px;"
src=${brandsUrl({
domain: entry.domain,
type: "icon",
darkOptimized: this.hass.themes?.darkMode,
})}
/>${entry.title}
</div>`}
> >
<img <ha-checkbox
alt="" .entry=${entry}
referrerpolicy="no-referrer" @change=${this._forecastCheckChanged}
style="height: 24px; margin-right: 16px;" .checked=${this._source?.config_entry_solar_forecast?.includes(
src=${brandsUrl({ entry.entry_id
domain: entry.domain, )}
type: "icon", >
darkOptimized: this.hass.themes?.darkMode, </ha-checkbox>
})} </ha-formfield>`
/>${entry.title}
</div>`}
>
<ha-checkbox
.entry=${entry}
@change=${this._forecastCheckChanged}
.checked=${this._source?.config_entry_solar_forecast?.includes(
entry.entry_id
)}
>
</ha-checkbox>
</ha-formfield>`
)} )}
<mwc-button @click=${this._addForecast}> <mwc-button @click=${this._addForecast}>
${this.hass.localize( ${this.hass.localize(

View File

@ -892,11 +892,9 @@ export class EntityRegistrySettingsEditor extends LitElement {
"ui.dialogs.entity_registry.editor.use_device_area" "ui.dialogs.entity_registry.editor.use_device_area"
)} )}
${this.hass.devices[this.entry.device_id].area_id ${this.hass.devices[this.entry.device_id].area_id
? `(${ ? `(${this.hass.areas[
this.hass.areas[ this.hass.devices[this.entry.device_id].area_id!
this.hass.devices[this.entry.device_id].area_id! ]?.name})`
]?.name
})`
: ""}</span : ""}</span
> >
<span slot="description" <span slot="description"

View File

@ -201,15 +201,14 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
direction: "asc", direction: "asc",
grows: true, grows: true,
template: narrow template: narrow
? (name, entity: EntityRow) => ? (name, entity: EntityRow) => html`
html` ${name}<br />
${name}<br /> <div class="secondary">
<div class="secondary"> ${entity.entity_id} |
${entity.entity_id} | ${this.hass.localize(`component.${entity.platform}.title`) ||
${this.hass.localize(`component.${entity.platform}.title`) || entity.platform}
entity.platform} </div>
</div> `
`
: undefined, : undefined,
}, },
entity_id: { entity_id: {

View File

@ -110,51 +110,50 @@ class DialogHardwareAvailable extends LitElement implements HassDialog {
</search-input> </search-input>
</div> </div>
${devices.map( ${devices.map(
(device) => (device) => html`
html` <ha-expansion-panel
<ha-expansion-panel .header=${device.name}
.header=${device.name} .secondary=${device.by_id || undefined}
.secondary=${device.by_id || undefined} outlined
outlined >
> <div class="device-property">
<div class="device-property"> <span>
<span> ${this.hass.localize(
${this.hass.localize( "ui.panel.config.hardware.available_hardware.subsystem"
"ui.panel.config.hardware.available_hardware.subsystem" )}:
)}: </span>
</span> <span>${device.subsystem}</span>
<span>${device.subsystem}</span> </div>
</div> <div class="device-property">
<div class="device-property"> <span>
<span> ${this.hass.localize(
${this.hass.localize( "ui.panel.config.hardware.available_hardware.device_path"
"ui.panel.config.hardware.available_hardware.device_path" )}:
)}: </span>
</span> <code>${device.dev_path}</code>
<code>${device.dev_path}</code> </div>
</div> ${device.by_id
${device.by_id ? html`
? html` <div class="device-property">
<div class="device-property"> <span>
<span> ${this.hass.localize(
${this.hass.localize( "ui.panel.config.hardware.available_hardware.id"
"ui.panel.config.hardware.available_hardware.id" )}:
)}: </span>
</span> <code>${device.by_id}</code>
<code>${device.by_id}</code> </div>
</div> `
` : ""}
: ""} <div class="attributes">
<div class="attributes"> <span>
<span> ${this.hass.localize(
${this.hass.localize( "ui.panel.config.hardware.available_hardware.attributes"
"ui.panel.config.hardware.available_hardware.attributes" )}:
)}: </span>
</span> <pre>${dump(device.attributes, { indent: 2 })}</pre>
<pre>${dump(device.attributes, { indent: 2 })}</pre> </div>
</div> </ha-expansion-panel>
</ha-expansion-panel> `
`
)} )}
</ha-dialog> </ha-dialog>
`; `;

View File

@ -53,10 +53,11 @@ class HaCounterForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -31,10 +31,11 @@ class HaInputBooleanForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -31,10 +31,11 @@ class HaInputButtonForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -45,10 +45,11 @@ class HaInputDateTimeForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -60,10 +60,11 @@ class HaInputNumberForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -43,10 +43,11 @@ class HaInputSelectForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -50,10 +50,11 @@ class HaInputTextForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -98,10 +98,11 @@ class HaScheduleForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -39,10 +39,11 @@ class HaTimerForm extends LitElement {
} }
public focus() { public focus() {
this.updateComplete.then(() => this.updateComplete.then(
( () =>
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement (
)?.focus() this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
)?.focus()
); );
} }

View File

@ -96,13 +96,12 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
filterable: true, filterable: true,
grows: true, grows: true,
direction: "asc", direction: "asc",
template: (name, item: any) => template: (name, item: any) => html`
html` ${name}
${name} ${narrow
${narrow ? html` <div class="secondary">${item.entity_id}</div> `
? html` <div class="secondary">${item.entity_id}</div> ` : ""}
: ""} `,
`,
}, },
}; };
if (!narrow) { if (!narrow) {

View File

@ -410,22 +410,23 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
</h1> </h1>
<mwc-list> <mwc-list>
${discoveryFlows.map( ${discoveryFlows.map(
(flow) => html`<ha-list-item (flow) =>
hasMeta html`<ha-list-item
class="discovered" hasMeta
noninteractive class="discovered"
> noninteractive
${flow.localized_title} >
<ha-button ${flow.localized_title}
slot="meta" <ha-button
unelevated slot="meta"
.flow=${flow} unelevated
@click=${this._continueFlow} .flow=${flow}
.label=${this.hass.localize( @click=${this._continueFlow}
"ui.panel.config.integrations.configure" .label=${this.hass.localize(
)} "ui.panel.config.integrations.configure"
></ha-button> )}
</ha-list-item>` ></ha-button>
</ha-list-item>`
)} )}
</mwc-list> </mwc-list>
</ha-card>` </ha-card>`

View File

@ -150,7 +150,7 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
): [ ): [
[string, ConfigEntryExtended[]][], [string, ConfigEntryExtended[]][],
ConfigEntryExtended[], ConfigEntryExtended[],
ConfigEntryExtended[] ConfigEntryExtended[],
] => { ] => {
let filteredConfigEntries: ConfigEntryExtended[]; let filteredConfigEntries: ConfigEntryExtended[];
const ignored: ConfigEntryExtended[] = []; const ignored: ConfigEntryExtended[] = [];

View File

@ -44,29 +44,30 @@ class HaDomainIntegrations extends LitElement {
${this.hass.localize("ui.panel.config.integrations.discovered")} ${this.hass.localize("ui.panel.config.integrations.discovered")}
</h3> </h3>
${this.flowsInProgress.map( ${this.flowsInProgress.map(
(flow) => html`<mwc-list-item (flow) =>
graphic="medium" html`<mwc-list-item
.flow=${flow} graphic="medium"
@request-selected=${this._flowInProgressPicked} .flow=${flow}
hasMeta @request-selected=${this._flowInProgressPicked}
> hasMeta
<img
alt=""
slot="graphic"
loading="lazy"
src=${brandsUrl({
domain: flow.handler,
type: "icon",
useFallback: true,
darkOptimized: this.hass.themes?.darkMode,
})}
referrerpolicy="no-referrer"
/>
<span
>${localizeConfigFlowTitle(this.hass.localize, flow)}</span
> >
<ha-icon-next slot="meta"></ha-icon-next> <img
</mwc-list-item>` alt=""
slot="graphic"
loading="lazy"
src=${brandsUrl({
domain: flow.handler,
type: "icon",
useFallback: true,
darkOptimized: this.hass.themes?.darkMode,
})}
referrerpolicy="no-referrer"
/>
<span
>${localizeConfigFlowTitle(this.hass.localize, flow)}</span
>
<ha-icon-next slot="meta"></ha-icon-next>
</mwc-list-item>`
)} )}
<li divider role="separator"></li> <li divider role="separator"></li>
${this.integration && ${this.integration &&

View File

@ -223,25 +223,26 @@ class ZHAConfigDashboard extends LitElement {
</ha-card> </ha-card>
${this._configuration ${this._configuration
? Object.entries(this._configuration.schemas).map( ? Object.entries(this._configuration.schemas).map(
([section, schema]) => html`<ha-card ([section, schema]) =>
header=${this.hass.localize( html`<ha-card
`component.zha.config_panel.${section}.title` header=${this.hass.localize(
)} `component.zha.config_panel.${section}.title`
> )}
<div class="card-content"> >
<ha-form <div class="card-content">
.hass=${this.hass} <ha-form
.schema=${schema} .hass=${this.hass}
.data=${this._configuration!.data[section]} .schema=${schema}
@value-changed=${this._dataChanged} .data=${this._configuration!.data[section]}
.section=${section} @value-changed=${this._dataChanged}
.computeLabel=${this._computeLabelCallback( .section=${section}
this.hass.localize, .computeLabel=${this._computeLabelCallback(
section this.hass.localize,
)} section
></ha-form> )}
</div> ></ha-form>
</ha-card>` </div>
</ha-card>`
) )
: ""} : ""}
<ha-card> <ha-card>

View File

@ -94,8 +94,9 @@ export class ZHAGroupsDashboard extends LitElement {
title: this.hass.localize("ui.panel.config.zha.groups.group_id"), title: this.hass.localize("ui.panel.config.zha.groups.group_id"),
type: "numeric", type: "numeric",
width: "15%", width: "15%",
template: (groupId: number) => template: (groupId: number) => html`
html` ${formatAsPaddedHex(groupId)} `, ${formatAsPaddedHex(groupId)}
`,
sortable: true, sortable: true,
}, },
members: { members: {

View File

@ -228,27 +228,28 @@ class DialogZWaveJSAddNode extends LitElement {
.sort() .sort()
.reverse() .reverse()
.map( .map(
(securityClass) => html`<ha-formfield (securityClass) =>
.label=${html`<b html`<ha-formfield
>${this.hass.localize( .label=${html`<b
`ui.panel.config.zwave_js.security_classes.${SecurityClass[securityClass]}.title` >${this.hass.localize(
)}</b `ui.panel.config.zwave_js.security_classes.${SecurityClass[securityClass]}.title`
> )}</b
<div class="secondary"> >
${this.hass.localize( <div class="secondary">
`ui.panel.config.zwave_js.security_classes.${SecurityClass[securityClass]}.description` ${this.hass.localize(
)} `ui.panel.config.zwave_js.security_classes.${SecurityClass[securityClass]}.description`
</div>`} )}
> </div>`}
<ha-checkbox
@change=${this._handleSecurityClassChange}
.value=${securityClass}
.checked=${this._securityClasses.includes(
securityClass
)}
> >
</ha-checkbox> <ha-checkbox
</ha-formfield>` @change=${this._handleSecurityClassChange}
.value=${securityClass}
.checked=${this._securityClasses.includes(
securityClass
)}
>
</ha-checkbox>
</ha-formfield>`
)} )}
</div> </div>
<mwc-button <mwc-button

View File

@ -364,7 +364,7 @@ class DialogZWaveJSNodeStatistics extends LitElement {
const workingRoutesValueMap: [ const workingRoutesValueMap: [
string, string,
WorkingRouteStatistics | null | undefined WorkingRouteStatistics | null | undefined,
][] = [ ][] = [
["lwr", this._nodeStatistics?.lwr], ["lwr", this._nodeStatistics?.lwr],
["nlwr", this._nodeStatistics?.nlwr], ["nlwr", this._nodeStatistics?.nlwr],

View File

@ -179,32 +179,34 @@ class ZWaveJSNodeConfig extends SubscribeMixin(LitElement) {
item.endpoint.toString() item.endpoint.toString()
) )
).map( ).map(
([endpoint, configParamEntries]) => html`<div class="content"> ([endpoint, configParamEntries]) =>
<h3> html`<div class="content">
${this.hass.localize( <h3>
"ui.panel.config.zwave_js.node_config.endpoint", ${this.hass.localize(
"endpoint", "ui.panel.config.zwave_js.node_config.endpoint",
endpoint "endpoint",
)} endpoint
</h3>
<ha-card>
${configParamEntries
.sort(([_, paramA], [__, paramB]) =>
paramA.property !== paramB.property
? paramA.property - paramB.property
: paramA.property_key! - paramB.property_key!
)
.map(
([id, item]) => html` <ha-settings-row
class="config-item"
.configId=${id}
.narrow=${this.narrow}
>
${this._generateConfigBox(id, item)}
</ha-settings-row>`
)} )}
</ha-card> </h3>
</div>` <ha-card>
${configParamEntries
.sort(([_, paramA], [__, paramB]) =>
paramA.property !== paramB.property
? paramA.property - paramB.property
: paramA.property_key! - paramB.property_key!
)
.map(
([id, item]) =>
html` <ha-settings-row
class="config-item"
.configId=${id}
.narrow=${this.narrow}
>
${this._generateConfigBox(id, item)}
</ha-settings-row>`
)}
</ha-card>
</div>`
)} )}
</ha-config-section> </ha-config-section>
</hass-tabs-subpage> </hass-tabs-subpage>

View File

@ -123,12 +123,11 @@ export class HaConfigLovelaceDashboards extends LitElement {
sortable: true, sortable: true,
filterable: true, filterable: true,
width: "20%", width: "20%",
template: (mode) => template: (mode) => html`
html` ${this.hass.localize(
${this.hass.localize( `ui.panel.config.lovelace.dashboards.conf_mode.${mode}`
`ui.panel.config.lovelace.dashboards.conf_mode.${mode}` ) || mode}
) || mode} `,
`,
}; };
if (dashboards.some((dashboard) => dashboard.filename)) { if (dashboards.some((dashboard) => dashboard.filename)) {
columns.filename = { columns.filename = {

View File

@ -58,12 +58,11 @@ export class HaConfigLovelaceRescources extends LitElement {
sortable: true, sortable: true,
filterable: true, filterable: true,
width: "30%", width: "30%",
template: (type) => template: (type) => html`
html` ${this.hass.localize(
${this.hass.localize( `ui.panel.config.lovelace.resources.types.${type}`
`ui.panel.config.lovelace.resources.types.${type}` ) || type}
) || type} `,
`,
}, },
}) })
); );

View File

@ -139,25 +139,24 @@ export class HassioNetwork extends LitElement {
${this._accessPoints.accesspoints ${this._accessPoints.accesspoints
.filter((ap) => ap.ssid) .filter((ap) => ap.ssid)
.map( .map(
(ap) => (ap) => html`
html` <mwc-list-item
<mwc-list-item twoline
twoline @click=${this._selectAP}
@click=${this._selectAP} .activated=${ap.ssid ===
.activated=${ap.ssid === this._wifiConfiguration?.ssid}
this._wifiConfiguration?.ssid} .ap=${ap}
.ap=${ap} >
> <span>${ap.ssid}</span>
<span>${ap.ssid}</span> <span slot="secondary">
<span slot="secondary"> ${ap.mac} -
${ap.mac} - ${this.hass.localize(
${this.hass.localize( "ui.panel.config.network.supervisor.signal_strength"
"ui.panel.config.network.supervisor.signal_strength" )}:
)}: ${ap.signal}
${ap.signal} </span>
</span> </mwc-list-item>
</mwc-list-item> `
`
)} )}
</mwc-list> </mwc-list>
` `

View File

@ -305,13 +305,11 @@ class DialogSystemInformation extends LitElement {
const sections: TemplateResult[] = []; const sections: TemplateResult[] = [];
if (!this._systemInfo) { if (!this._systemInfo) {
sections.push( sections.push(html`
html` <div class="loading-container">
<div class="loading-container"> <ha-circular-progress active></ha-circular-progress>
<ha-circular-progress active></ha-circular-progress> </div>
</div> `);
`
);
} else { } else {
const domains = Object.keys(this._systemInfo).sort(sortKeys); const domains = Object.keys(this._systemInfo).sort(sortKeys);
for (const domain of domains) { for (const domain of domains) {
@ -371,24 +369,22 @@ class DialogSystemInformation extends LitElement {
`); `);
} }
if (domain !== "homeassistant") { if (domain !== "homeassistant") {
sections.push( sections.push(html`
html` <div class="card-header">
<div class="card-header"> <h3>${domainToName(this.hass.localize, domain)}</h3>
<h3>${domainToName(this.hass.localize, domain)}</h3> ${!domainInfo.manage_url
${!domainInfo.manage_url ? ""
? "" : html`
: html` <a class="manage" href=${domainInfo.manage_url}>
<a class="manage" href=${domainInfo.manage_url}> <mwc-button>
<mwc-button> ${this.hass.localize(
${this.hass.localize( "ui.panel.config.info.system_health.manage"
"ui.panel.config.info.system_health.manage" )}
)} </mwc-button>
</mwc-button> </a>
</a> `}
`} </div>
</div> `);
`
);
} }
sections.push(html` sections.push(html`
<table> <table>

View File

@ -90,8 +90,9 @@ class HaSceneDashboard extends LitElement {
"ui.panel.config.scene.picker.headers.state" "ui.panel.config.scene.picker.headers.state"
), ),
type: "icon", type: "icon",
template: (_, scene) => template: (_, scene) => html`
html` <ha-state-icon .state=${scene}></ha-state-icon> `, <ha-state-icon .state=${scene}></ha-state-icon>
`,
}, },
name: { name: {
title: this.hass.localize( title: this.hass.localize(
@ -151,50 +152,49 @@ class HaSceneDashboard extends LitElement {
title: "", title: "",
width: "72px", width: "72px",
type: "overflow-menu", type: "overflow-menu",
template: (_: string, scene: any) => template: (_: string, scene: any) => html`
html` <ha-icon-overflow-menu
<ha-icon-overflow-menu .hass=${this.hass}
.hass=${this.hass} narrow
narrow .items=${[
.items=${[ {
{ path: mdiInformationOutline,
path: mdiInformationOutline, label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.scene.picker.show_info"
"ui.panel.config.scene.picker.show_info" ),
), action: () => this._showInfo(scene),
action: () => this._showInfo(scene), },
}, {
{ path: mdiPlay,
path: mdiPlay, label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.scene.picker.activate"
"ui.panel.config.scene.picker.activate" ),
), action: () => this._activateScene(scene),
action: () => this._activateScene(scene), },
}, {
{ divider: true,
divider: true, },
}, {
{ path: mdiContentDuplicate,
path: mdiContentDuplicate, label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.scene.picker.duplicate"
"ui.panel.config.scene.picker.duplicate" ),
), action: () => this._duplicate(scene),
action: () => this._duplicate(scene), disabled: !scene.attributes.id,
disabled: !scene.attributes.id, },
}, {
{ label: this.hass.localize(
label: this.hass.localize( "ui.panel.config.scene.picker.delete"
"ui.panel.config.scene.picker.delete" ),
), path: mdiDelete,
path: mdiDelete, action: () => this._deleteConfirm(scene),
action: () => this._deleteConfirm(scene), warning: scene.attributes.id,
warning: scene.attributes.id, disabled: !scene.attributes.id,
disabled: !scene.attributes.id, },
}, ]}
]} >
> </ha-icon-overflow-menu>
</ha-icon-overflow-menu> `,
`,
}; };
return columns; return columns;

View File

@ -324,43 +324,42 @@ export class HaSceneEditor extends SubscribeMixin(
</div> </div>
${devices.map( ${devices.map(
(device) => (device) => html`
html` <ha-card outlined>
<ha-card outlined> <h1 class="card-header">
<h1 class="card-header"> ${device.name}
${device.name} <ha-icon-button
<ha-icon-button .path=${mdiDelete}
.path=${mdiDelete} .label=${this.hass.localize(
.label=${this.hass.localize( "ui.panel.config.scene.editor.devices.delete"
"ui.panel.config.scene.editor.devices.delete" )}
)} .device=${device.id}
.device=${device.id} @click=${this._deleteDevice}
@click=${this._deleteDevice} ></ha-icon-button>
></ha-icon-button> </h1>
</h1> ${device.entities.map((entityId) => {
${device.entities.map((entityId) => { const entityStateObj = this.hass.states[entityId];
const entityStateObj = this.hass.states[entityId]; if (!entityStateObj) {
if (!entityStateObj) { return nothing;
return nothing; }
} return html`
return html` <paper-icon-item
<paper-icon-item .entityId=${entityId}
.entityId=${entityId} @click=${this._showMoreInfo}
@click=${this._showMoreInfo} class="device-entity"
class="device-entity" >
> <state-badge
<state-badge .stateObj=${entityStateObj}
.stateObj=${entityStateObj} slot="item-icon"
slot="item-icon" ></state-badge>
></state-badge> <paper-item-body>
<paper-item-body> ${computeStateName(entityStateObj)}
${computeStateName(entityStateObj)} </paper-item-body>
</paper-item-body> </paper-icon-item>
</paper-icon-item> `;
`; })}
})} </ha-card>
</ha-card> `
`
)} )}
<ha-card <ha-card

Some files were not shown because too many files have changed in this diff Show More