Compare commits

..

1 Commits

Author SHA1 Message Date
Bram Kragten
e3be190b36 Add no device option to device filter 2024-04-24 12:56:24 +02:00
23 changed files with 288 additions and 663 deletions

View File

@@ -10,7 +10,6 @@ import {
import { HomeAssistantAppEl } from "../../src/layouts/home-assistant";
import { HomeAssistant } from "../../src/types";
import { selectedDemoConfig } from "./configs/demo-configs";
import { mockAreaRegistry } from "./stubs/area_registry";
import { mockAuth } from "./stubs/auth";
import { mockConfigEntries } from "./stubs/config_entries";
import { mockEnergy } from "./stubs/energy";
@@ -24,10 +23,10 @@ import { mockLovelace } from "./stubs/lovelace";
import { mockMediaPlayer } from "./stubs/media_player";
import { mockPersistentNotification } from "./stubs/persistent_notification";
import { mockRecorder } from "./stubs/recorder";
import { mockTodo } from "./stubs/todo";
import { mockSensor } from "./stubs/sensor";
import { mockSystemLog } from "./stubs/system_log";
import { mockTemplate } from "./stubs/template";
import { mockTodo } from "./stubs/todo";
import { mockTranslations } from "./stubs/translations";
@customElement("ha-demo")
@@ -63,7 +62,6 @@ export class HaDemo extends HomeAssistantAppEl {
mockEnergy(hass);
mockPersistentNotification(hass);
mockConfigEntries(hass);
mockAreaRegistry(hass);
mockEntityRegistry(hass, [
{
config_entry_id: "co2signal",

View File

@@ -151,7 +151,7 @@
},
"devDependencies": {
"@babel/core": "7.24.4",
"@babel/helper-define-polyfill-provider": "0.6.2",
"@babel/helper-define-polyfill-provider": "0.6.1",
"@babel/plugin-proposal-decorators": "7.24.1",
"@babel/plugin-transform-runtime": "7.24.3",
"@babel/preset-env": "7.24.4",
@@ -175,7 +175,7 @@
"@types/glob": "8.1.0",
"@types/html-minifier-terser": "7.0.2",
"@types/js-yaml": "4.0.9",
"@types/leaflet": "1.9.12",
"@types/leaflet": "1.9.11",
"@types/leaflet-draw": "1.0.11",
"@types/luxon": "3.4.2",
"@types/mocha": "10.0.6",
@@ -185,8 +185,8 @@
"@types/tar": "6.1.13",
"@types/ua-parser-js": "0.7.39",
"@types/webspeechapi": "0.0.29",
"@typescript-eslint/eslint-plugin": "7.7.1",
"@typescript-eslint/parser": "7.7.1",
"@typescript-eslint/eslint-plugin": "7.7.0",
"@typescript-eslint/parser": "7.7.0",
"@web/dev-server": "0.1.38",
"@web/dev-server-rollup": "0.4.1",
"babel-loader": "9.1.3",

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20240426.0"
version = "20240424.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"

View File

@@ -1,4 +1,4 @@
import { mdiArrowDown, mdiArrowUp, mdiChevronUp } from "@mdi/js";
import { mdiArrowDown, mdiArrowUp, mdiChevronDown } from "@mdi/js";
import deepClone from "deep-clone-simple";
import {
CSSResultGroup,
@@ -578,7 +578,7 @@ export class HaDataTable extends LitElement {
@click=${this._collapseGroup}
>
<ha-icon-button
.path=${mdiChevronUp}
.path=${mdiChevronDown}
class=${this._collapsedGroups.includes(groupName)
? "collapsed"
: ""}

View File

@@ -20,6 +20,8 @@ import "./ha-check-list-item";
import "./ha-expansion-panel";
import "./search-input-outlined";
export const FILTER_NO_DEVICE = "__NO_DEVICE__";
@customElement("ha-filter-devices")
export class HaFilterDevices extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -32,6 +34,9 @@ export class HaFilterDevices extends LitElement {
@property({ type: Boolean }) public narrow = false;
@property({ type: Boolean, attribute: "no-device-option" })
public noDeviceOption = false;
@state() private _shouldRender = false;
@state() private _filter?: string;
@@ -69,11 +74,12 @@ export class HaFilterDevices extends LitElement {
@value-changed=${this._handleSearchChange}
>
</search-input-outlined>
<mwc-list class="ha-scrollbar" multi>
<mwc-list class="ha-scrollbar">
<lit-virtualizer
.items=${this._devices(
this.hass.devices,
this._filter || "",
this.noDeviceOption,
this.value
)}
.keyFunction=${this._keyFunction}
@@ -137,9 +143,13 @@ export class HaFilterDevices extends LitElement {
}
private _devices = memoizeOne(
(devices: HomeAssistant["devices"], filter: string, _value) => {
const values = Object.values(devices);
return values
(
devices: HomeAssistant["devices"],
filter: string,
noDeviceOption: boolean,
_value
) => {
const values = Object.values(devices)
.filter(
(device) =>
!filter ||
@@ -152,6 +162,28 @@ export class HaFilterDevices extends LitElement {
this.hass.locale.language
)
);
if (noDeviceOption) {
values.unshift({
id: FILTER_NO_DEVICE,
name: this.hass.localize("ui.panel.config.devices.no_device"),
area_id: null,
configuration_url: null,
config_entries: [],
connections: [],
disabled_by: null,
entry_type: null,
identifiers: [],
manufacturer: null,
model: null,
name_by_user: null,
sw_version: null,
hw_version: null,
via_device_id: null,
serial_number: null,
labels: [],
});
}
return values;
}
);
@@ -171,7 +203,7 @@ export class HaFilterDevices extends LitElement {
for (const deviceId of this.value) {
value.push(deviceId);
if (this.type) {
if (this.type && deviceId !== FILTER_NO_DEVICE) {
relatedPromises.push(findRelated(this.hass, "device", deviceId));
}
}

View File

@@ -1,198 +0,0 @@
import { mdiFilterVariantRemove } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
import memoizeOne from "memoize-one";
import { fireEvent } from "../common/dom/fire_event";
import { stringCompare } from "../common/string/compare";
import { domainToName } from "../data/integration";
import { haStyleScrollbar } from "../resources/styles";
import type { HomeAssistant } from "../types";
import "./ha-domain-icon";
import "./search-input-outlined";
import { computeDomain } from "../common/entity/compute_domain";
@customElement("ha-filter-domains")
export class HaFilterDomains extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public value?: string[];
@property({ type: Boolean }) public narrow = false;
@property({ type: Boolean, reflect: true }) public expanded = false;
@state() private _shouldRender = false;
@state() private _filter?: string;
protected render() {
return html`
<ha-expansion-panel
leftChevron
.expanded=${this.expanded}
@expanded-will-change=${this._expandedWillChange}
@expanded-changed=${this._expandedChanged}
>
<div slot="header" class="header">
${this.hass.localize(
"ui.panel.config.entities.picker.headers.domain"
)}
${this.value?.length
? html`<div class="badge">${this.value?.length}</div>
<ha-icon-button
.path=${mdiFilterVariantRemove}
@click=${this._clearFilter}
></ha-icon-button>`
: nothing}
</div>
${this._shouldRender
? html`<search-input-outlined
.hass=${this.hass}
.filter=${this._filter}
@value-changed=${this._handleSearchChange}
>
</search-input-outlined>
<mwc-list
class="ha-scrollbar"
@click=${this._handleItemClick}
multi
>
${repeat(
this._domains(this.hass.states, this._filter),
(i) => i,
(domain) =>
html`<ha-check-list-item
.value=${domain}
.selected=${(this.value || []).includes(domain)}
graphic="icon"
>
<ha-domain-icon
slot="graphic"
.hass=${this.hass}
.domain=${domain}
brandFallback
></ha-domain-icon>
${domainToName(this.hass.localize, domain)}
</ha-check-list-item>`
)}
</mwc-list> `
: nothing}
</ha-expansion-panel>
`;
}
private _domains = memoizeOne((states, filter) => {
const domains = new Set<string>();
Object.keys(states).forEach((entityId) => {
domains.add(computeDomain(entityId));
});
return Array.from(domains)
.filter((domain) => !filter || domain.toLowerCase().includes(filter))
.sort((a, b) => stringCompare(a, b, this.hass.locale.language));
});
protected updated(changed) {
if (changed.has("expanded") && this.expanded) {
setTimeout(() => {
if (!this.expanded) return;
this.renderRoot.querySelector("mwc-list")!.style.height =
`${this.clientHeight - 49 - 32}px`; // 32px is the height of the search input
}, 300);
}
}
private _expandedWillChange(ev) {
this._shouldRender = ev.detail.expanded;
}
private _expandedChanged(ev) {
this.expanded = ev.detail.expanded;
}
private _handleItemClick(ev) {
const listItem = ev.target.closest("ha-check-list-item");
const value = listItem?.value;
if (!value) {
return;
}
if (this.value?.includes(value)) {
this.value = this.value?.filter((val) => val !== value);
} else {
this.value = [...(this.value || []), value];
}
listItem.selected = this.value.includes(value);
fireEvent(this, "data-table-filter-changed", {
value: this.value,
items: undefined,
});
}
private _clearFilter(ev) {
ev.preventDefault();
this.value = undefined;
fireEvent(this, "data-table-filter-changed", {
value: undefined,
items: undefined,
});
}
private _handleSearchChange(ev: CustomEvent) {
this._filter = ev.detail.value.toLowerCase();
}
static get styles(): CSSResultGroup {
return [
haStyleScrollbar,
css`
:host {
border-bottom: 1px solid var(--divider-color);
}
:host([expanded]) {
flex: 1;
height: 0;
}
ha-expansion-panel {
--ha-card-border-radius: 0;
--expansion-panel-content-padding: 0;
}
.header {
display: flex;
align-items: center;
}
.header ha-icon-button {
margin-inline-start: auto;
margin-inline-end: 8px;
}
.badge {
display: inline-block;
margin-left: 8px;
margin-inline-start: 8px;
margin-inline-end: 0;
min-width: 16px;
box-sizing: border-box;
border-radius: 50%;
font-weight: 400;
font-size: 11px;
background-color: var(--primary-color);
line-height: 16px;
text-align: center;
padding: 0px 2px;
color: var(--text-primary-color);
}
search-input-outlined {
display: block;
padding: 0 8px;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-filter-domains": HaFilterDomains;
}
}

View File

@@ -71,7 +71,7 @@ export class HaFilterEntities extends LitElement {
@value-changed=${this._handleSearchChange}
>
</search-input-outlined>
<mwc-list class="ha-scrollbar" multi>
<mwc-list class="ha-scrollbar">
<lit-virtualizer
.items=${this._entities(
this.hass.states,

View File

@@ -55,11 +55,7 @@ export class HaFilterIntegrations extends LitElement {
@value-changed=${this._handleSearchChange}
>
</search-input-outlined>
<mwc-list
class="ha-scrollbar"
@click=${this._handleItemClick}
multi
>
<mwc-list class="ha-scrollbar" @click=${this._handleItemClick}>
${repeat(
this._integrations(this._manifests, this._filter, this.value),
(i) => i.domain,

View File

@@ -71,10 +71,6 @@ export const computeInitialHaFormData = (
if (selector.country?.countries?.length) {
data[field.name] = selector.country.countries[0];
}
} else if ("language" in selector) {
if (selector.language?.languages?.length) {
data[field.name] = selector.language.languages[0];
}
} else if ("duration" in selector) {
data[field.name] = {
hours: 0,
@@ -97,9 +93,7 @@ export const computeInitialHaFormData = (
) {
data[field.name] = {};
} else {
throw new Error(
`Selector ${Object.keys(selector)[0]} not supported in initial form data`
);
throw new Error("Selector not supported in initial form data");
}
}
});

View File

@@ -1,29 +1,13 @@
import { FormfieldBase } from "@material/mwc-formfield/mwc-formfield-base";
import { styles } from "@material/mwc-formfield/mwc-formfield.css";
import { css, html } from "lit";
import { css } from "lit";
import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { fireEvent } from "../common/dom/fire_event";
@customElement("ha-formfield")
export class HaFormfield extends FormfieldBase {
@property({ type: Boolean, reflect: true }) public disabled = false;
protected override render() {
const classes = {
"mdc-form-field--align-end": this.alignEnd,
"mdc-form-field--space-between": this.spaceBetween,
"mdc-form-field--nowrap": this.nowrap,
};
return html` <div class="mdc-form-field ${classMap(classes)}">
<slot></slot>
<label class="mdc-label" @click=${this._labelClick}
><slot name="label">${this.label}</slot></label
>
</div>`;
}
protected _labelClick() {
const input = this.input as HTMLInputElement | undefined;
if (!input) return;
@@ -55,9 +39,6 @@ export class HaFormfield extends FormfieldBase {
margin-inline-end: 10px;
margin-inline-start: inline;
}
.mdc-form-field {
align-items: var(--ha-formfield-align-items, center);
}
.mdc-form-field > label {
direction: var(--direction);
margin-inline-start: 0;

View File

@@ -19,7 +19,7 @@ import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event";
import type { LeafletModuleType } from "../../common/dom/setup-leaflet-map";
import type { HomeAssistant, ThemeMode } from "../../types";
import type { HomeAssistant } from "../../types";
import "../ha-input-helper-text";
import "./ha-map";
import type { HaMap } from "./ha-map";
@@ -61,8 +61,7 @@ export class HaLocationsEditor extends LitElement {
@property({ type: Number }) public zoom = 16;
@property({ attribute: "theme-mode", type: String })
public themeMode: ThemeMode = "auto";
@property({ type: Boolean }) public darkMode = false;
@state() private _locationMarkers?: Record<string, Marker | Circle>;
@@ -134,7 +133,7 @@ export class HaLocationsEditor extends LitElement {
.layers=${this._getLayers(this._circles, this._locationMarkers)}
.zoom=${this.zoom}
.autoFit=${this.autoFit}
.themeMode=${this.themeMode}
?forceDarkMode=${this.darkMode}
></ha-map>
${this.helper
? html`<ha-input-helper-text>${this.helper}</ha-input-helper-text>`

View File

@@ -1,32 +1,32 @@
import { isToday } from "date-fns";
import type {
Circle,
CircleMarker,
LatLngExpression,
LatLngTuple,
LatLngExpression,
Layer,
Map,
Marker,
Polyline,
} from "leaflet";
import { CSSResultGroup, PropertyValues, ReactiveElement, css } from "lit";
import { isToday } from "date-fns";
import { css, CSSResultGroup, PropertyValues, ReactiveElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { formatDateTime } from "../../common/datetime/format_date_time";
import {
formatTimeWeekday,
formatTimeWithSeconds,
} from "../../common/datetime/format_time";
import {
LeafletModuleType,
setupLeafletMap,
} from "../../common/dom/setup-leaflet-map";
import {
formatTimeWithSeconds,
formatTimeWeekday,
} from "../../common/datetime/format_time";
import { formatDateTime } from "../../common/datetime/format_date_time";
import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { computeStateName } from "../../common/entity/compute_state_name";
import { loadPolyfillIfNeeded } from "../../resources/resize-observer.polyfill";
import { HomeAssistant, ThemeMode } from "../../types";
import { isTouch } from "../../util/is_touch";
import { HomeAssistant } from "../../types";
import "../ha-icon-button";
import "./ha-entity-marker";
import { isTouch } from "../../util/is_touch";
const getEntityId = (entity: string | HaMapEntity): string =>
typeof entity === "string" ? entity : entity.entity_id;
@@ -69,8 +69,9 @@ export class HaMap extends ReactiveElement {
@property({ type: Boolean }) public fitZones = false;
@property({ attribute: "theme-mode", type: String })
public themeMode: ThemeMode = "auto";
@property({ type: Boolean }) public forceDarkMode = false;
@property({ type: Boolean }) public forceLightMode = false;
@property({ type: Number }) public zoom = 14;
@@ -155,7 +156,8 @@ export class HaMap extends ReactiveElement {
}
if (
!changedProps.has("themeMode") &&
!changedProps.has("forceDarkMode") &&
!changedProps.has("forceLightMode") &&
(!changedProps.has("hass") ||
(oldHass && oldHass.themes?.darkMode === this.hass.themes?.darkMode))
) {
@@ -164,18 +166,14 @@ export class HaMap extends ReactiveElement {
this._updateMapStyle();
}
private get _darkMode() {
return (
this.themeMode === "dark" ||
(this.themeMode === "auto" && Boolean(this.hass.themes.darkMode))
);
}
private _updateMapStyle(): void {
const darkMode =
!this.forceLightMode &&
(this.forceDarkMode || (this.hass.themes.darkMode ?? false));
const map = this.renderRoot.querySelector("#map");
map!.classList.toggle("dark", this._darkMode);
map!.classList.toggle("forced-dark", this.themeMode === "dark");
map!.classList.toggle("forced-light", this.themeMode === "light");
map!.classList.toggle("dark", darkMode);
map!.classList.toggle("forced-dark", this.forceDarkMode);
map!.classList.toggle("forced-light", this.forceLightMode);
}
private async _loadMap(): Promise<void> {
@@ -405,7 +403,13 @@ export class HaMap extends ReactiveElement {
"--dark-primary-color"
);
const className = this._darkMode ? "dark" : "light";
const className = this.forceLightMode
? "light"
: this.forceDarkMode
? "dark"
: this.hass.themes.darkMode
? "dark"
: "light";
for (const entity of this.entities) {
const stateObj = hass.states[getEntityId(entity)];

View File

@@ -16,23 +16,21 @@ class MoreInfoCounter extends LitElement {
return nothing;
}
const disabled = isUnavailableState(this.stateObj.state);
const disabled = isUnavailableState(this.stateObj!.state);
return html`
<div class="actions">
<mwc-button
.action=${"increment"}
@click=${this._handleActionClick}
.disabled=${disabled ||
Number(this.stateObj.state) === this.stateObj.attributes.maximum}
.disabled=${disabled}
>
${this.hass!.localize("ui.card.counter.actions.increment")}
</mwc-button>
<mwc-button
.action=${"decrement"}
@click=${this._handleActionClick}
.disabled=${disabled ||
Number(this.stateObj.state) === this.stateObj.attributes.minimum}
.disabled=${disabled}
>
${this.hass!.localize("ui.card.counter.actions.decrement")}
</mwc-button>

View File

@@ -41,7 +41,7 @@ import type { HomeAssistant } from "../types";
import { onBoardingStyles } from "./styles";
const AMSTERDAM: [number, number] = [52.3731339, 4.8903147];
const darkMql = matchMedia("(prefers-color-scheme: dark)");
const mql = matchMedia("(prefers-color-scheme: dark)");
const LOCATION_MARKER_ID = "location";
@customElement("onboarding-location")
@@ -199,7 +199,7 @@ class OnboardingLocation extends LitElement {
this._highlightedMarker
)}
zoom="14"
.themeMode=${darkMql.matches ? "dark" : "light"}
.darkMode=${mql.matches}
.disabled=${this._working}
@location-updated=${this._locationChanged}
@marker-clicked=${this._markerClicked}

View File

@@ -97,7 +97,7 @@ export class HaManualAutomationEditor extends LitElement {
<ha-automation-trigger
role="region"
aria-labelledby="triggers-heading"
.triggers=${this.config.trigger || []}
.triggers=${this.config.trigger}
.path=${["trigger"]}
@value-changed=${this._triggerChanged}
@item-moved=${this._itemMoved}

View File

@@ -1,19 +1,16 @@
import { mdiContentCopy, mdiEye, mdiEyeOff, mdiHelpCircle } from "@mdi/js";
import { mdiContentCopy, mdiHelpCircle } from "@mdi/js";
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
import { copyToClipboard } from "../../../../common/util/copy-clipboard";
import "../../../../components/ha-alert";
import "../../../../components/ha-button";
import "../../../../components/ha-card";
import "../../../../components/ha-expansion-panel";
import "../../../../components/ha-formfield";
import "../../../../components/ha-radio";
import "../../../../components/ha-settings-row";
import "../../../../components/ha-switch";
// eslint-disable-next-line
import { formatDate } from "../../../../common/datetime/format_date";
import type { HaRadio } from "../../../../components/ha-radio";
import type { HaSwitch } from "../../../../components/ha-switch";
import {
CloudStatusLoggedIn,
@@ -23,8 +20,8 @@ import {
} from "../../../../data/cloud";
import type { HomeAssistant } from "../../../../types";
import { showToast } from "../../../../util/toast";
import { showAlertDialog } from "../../../lovelace/custom-card-helpers";
import { showCloudCertificateDialog } from "../dialog-cloud-certificate/show-dialog-cloud-certificate";
import { showAlertDialog } from "../../../lovelace/custom-card-helpers";
@customElement("cloud-remote-pref")
export class CloudRemotePref extends LitElement {
@@ -32,8 +29,6 @@ export class CloudRemotePref extends LitElement {
@property({ attribute: false }) public cloudStatus?: CloudStatusLoggedIn;
@state() private _unmaskedUrl = false;
protected render() {
if (!this.cloudStatus) {
return nothing;
@@ -114,180 +109,35 @@ export class CloudRemotePref extends LitElement {
)}
></ha-alert>
`
: strict_connection === "drop_connection"
? html`<ha-alert
alert-type="warning"
.title=${this.hass.localize(
`ui.panel.config.cloud.account.remote.drop_connection_warning_title`
)}
>${this.hass.localize(
`ui.panel.config.cloud.account.remote.drop_connection_warning`
)}</ha-alert
>`
: nothing}
<p>
${this.hass.localize("ui.panel.config.cloud.account.remote.info")}
</p>
${remote_connected
? nothing
: html`
<p>
${this.hass.localize(
"ui.panel.config.cloud.account.remote.info_instance_will_be_available"
)}
</p>
`}
<div class="url-container">
<div class="textfield-container">
<ha-textfield
.value=${this._unmaskedUrl
? `https://${remote_domain}`
: "https://•••••••••••••••••.ui.nabu.casa"}
readonly
.suffix=${
// reserve some space for the icon.
html`<div style="width: 24px"></div>`
}
></ha-textfield>
<ha-icon-button
class="toggle-unmasked-url"
toggles
.label=${this.hass.localize(
`ui.panel.config.cloud.account.remote.${this._unmaskedUrl ? "hide" : "show"}_url`
)}
@click=${this._toggleUnmaskedUrl}
.path=${this._unmaskedUrl ? mdiEyeOff : mdiEye}
></ha-icon-button>
</div>
<ha-button
.url=${`https://${remote_domain}`}
@click=${this._copyURL}
unelevated
>
<ha-svg-icon slot="icon" .path=${mdiContentCopy}></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.cloud.account.remote.copy_link"
)}
</ha-button>
</div>
: ""}
${this.hass.localize("ui.panel.config.cloud.account.remote.info")}
${this.hass.localize(
`ui.panel.config.cloud.account.remote.${
remote_connected
? "instance_is_available"
: "instance_will_be_available"
}`
)}
<a
href="https://${remote_domain}"
target="_blank"
class="break-word"
rel="noreferrer"
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.nabu_casa_url"
)}</a
>.
<ha-svg-icon
.url=${`https://${remote_domain}`}
@click=${this._copyURL}
.path=${mdiContentCopy}
></ha-svg-icon>
<ha-expansion-panel
outlined
.header=${this.hass.localize(
"ui.panel.config.cloud.account.remote.security_options"
"ui.panel.config.cloud.account.remote.advanced_options"
)}
>
<ha-settings-row>
<span slot="heading">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection"
)}
</span>
<span slot="description">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_secondary"
)}
</span>
</ha-settings-row>
<div class="strict-connection-container">
<ha-formfield>
<ha-radio
name="strict-connection-mode"
value="disabled"
.checked=${strict_connection === "disabled"}
@change=${this._strictConnectionModeChanged}
></ha-radio>
<div slot="label">
<div class="primary">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_option_disabled"
)}
</div>
<div class="secondary">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_option_disabled_secondary"
)}
</div>
</div>
</ha-formfield>
<ha-formfield>
<ha-radio
name="strict-connection-mode"
value="guard_page"
.checked=${strict_connection === "guard_page"}
@change=${this._strictConnectionModeChanged}
></ha-radio>
<div slot="label">
<div class="primary">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_option_guard_page"
)}
</div>
<div class="secondary">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_option_guard_page_secondary"
)}
<br /><br />
⚠️
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_option_guard_page_warning"
)}
</div>
</div>
</ha-formfield>
<ha-formfield>
<ha-radio
name="strict-connection-mode"
value="drop_connection"
.checked=${strict_connection === "drop_connection"}
@change=${this._strictConnectionModeChanged}
></ha-radio>
<div slot="label">
<div class="primary">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_option_drop_connection"
)}
</div>
<div class="secondary">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_option_drop_connection_secondary"
)}
<br /><br />
⚠️
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_option_drop_connection_warning"
)}
</div>
</div>
</ha-formfield>
</div>
${strict_connection !== "disabled"
? html`
<ha-settings-row>
<span slot="heading"
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_link"
)}</span
>
<span slot="description"
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_link_secondary"
)}</span
>
<ha-button @click=${this._createLoginUrl}
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_create_link"
)}</ha-button
>
</ha-settings-row>
`
: nothing}
<hr />
<ha-settings-row>
<span slot="heading"
>${this.hass.localize(
@@ -304,7 +154,61 @@ export class CloudRemotePref extends LitElement {
@change=${this._toggleAllowRemoteEnabledChanged}
></ha-switch>
</ha-settings-row>
<hr />
<ha-settings-row>
<span slot="heading"
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection"
)}</span
>
<span slot="description"
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_secondary"
)}</span
>
<ha-select
.label=${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_mode"
)}
@selected=${this._setStrictConnectionMode}
naturalMenuWidth
.value=${strict_connection}
>
<ha-list-item value="disabled">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_modes.disabled"
)}
</ha-list-item>
<ha-list-item value="guard_page">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_modes.guard_page"
)}
</ha-list-item>
<ha-list-item value="drop_connection">
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_modes.drop_connection"
)}
</ha-list-item>
</ha-select>
</ha-settings-row>
${strict_connection !== "disabled"
? html` <ha-settings-row>
<span slot="heading"
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_link"
)}</span
>
<span slot="description"
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_link_secondary"
)}</span
>
<ha-button @click=${this._createLoginUrl}
>${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_create_link"
)}</ha-button
>
</ha-settings-row>`
: nothing}
<ha-settings-row>
<span slot="heading"
>${this.hass.localize(
@@ -345,10 +249,6 @@ export class CloudRemotePref extends LitElement {
});
}
private _toggleUnmaskedUrl(): void {
this._unmaskedUrl = !this._unmaskedUrl;
}
private async _toggleChanged(ev) {
const toggle = ev.target as HaSwitch;
@@ -379,21 +279,15 @@ export class CloudRemotePref extends LitElement {
}
}
private async _strictConnectionModeChanged(ev) {
const toggle = ev.target as HaRadio;
if (ev.target.value === this.cloudStatus?.prefs.strict_connection) {
return;
}
private async _setStrictConnectionMode(ev) {
const mode = ev.target.value;
try {
await updateCloudPref(this.hass, {
strict_connection: ev.target.value,
strict_connection: mode,
});
fireEvent(this, "ha-refresh-cloud-status");
} catch (err: any) {
alert(err.message);
toggle.checked = !toggle.checked;
}
}
@@ -422,22 +316,17 @@ export class CloudRemotePref extends LitElement {
text: html`${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_link_created_message"
)}
<div
style="display: flex; align-items: center; gap: 8px; margin-top: 8px;"
<pre>${result.response.url}</pre>
<ha-button
.url=${result.response.url}
@click=${this._copyURL}
unelevated
>
<ha-textfield .value=${result.response.url} readonly></ha-textfield>
<ha-button
style="flex-basis: 180px;"
.url=${result.response.url}
@click=${this._copyURL}
unelevated
>
<ha-svg-icon slot="icon" .path=${mdiContentCopy}></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.cloud.account.remote.copy_link"
)}
</ha-button>
</div>`,
<ha-svg-icon slot="icon" .path=${mdiContentCopy}></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.cloud.account.remote.strict_connection_copy_link"
)}
</ha-button>`,
});
} catch (err: any) {
showAlertDialog(this, { text: err.message });
@@ -454,8 +343,8 @@ export class CloudRemotePref extends LitElement {
}
.header-actions {
position: absolute;
right: 16px;
inset-inline-end: 16px;
right: 24px;
inset-inline-end: 24px;
inset-inline-start: initial;
top: 24px;
display: flex;
@@ -489,70 +378,16 @@ export class CloudRemotePref extends LitElement {
.card-actions a {
text-decoration: none;
}
ha-expansion-panel {
margin-top: 16px;
}
ha-settings-row {
padding: 0;
}
ha-expansion-panel {
--expansion-panel-content-padding: 0 16px;
--expansion-panel-summary-padding: 0 16px;
}
ha-alert {
display: block;
margin-bottom: 16px;
}
.url-container {
display: flex;
align-items: center;
gap: 8px;
margin-top: 8px;
}
.textfield-container {
position: relative;
flex: 1;
}
.textfield-container ha-textfield {
display: block;
}
.toggle-unmasked-url {
position: absolute;
top: 8px;
right: 8px;
inset-inline-start: initial;
inset-inline-end: 8px;
--mdc-icon-button-size: 40px;
--mdc-icon-size: 20px;
ha-svg-icon {
--mdc-icon-size: 18px;
color: var(--secondary-text-color);
direction: var(--direction);
cursor: pointer;
}
ha-formfield {
margin-left: -12px;
margin-inline-start: -12px;
--ha-formfield-align-items: start;
margin-top: 8px;
}
.strict-connection-container {
gap: 16px;
display: flex;
flex-direction: column;
}
.strict-connection-container ha-formfield {
--ha-formfield-align-items: start;
}
.strict-connection-container .primary {
font-size: 14px;
margin-top: 12px;
}
.strict-connection-container .secondary {
color: var(--secondary-text-color);
font-size: 12px;
}
hr {
border: none;
height: 1px;
background-color: var(--divider-color);
margin: 8px 0;
ha-expansion-panel {
margin-top: 8px;
}
`;
}

View File

@@ -52,8 +52,6 @@ import "../../../components/data-table/ha-data-table-labels";
import "../../../components/ha-alert";
import "../../../components/ha-button-menu";
import "../../../components/ha-check-list-item";
import "../../../components/ha-filter-devices";
import "../../../components/ha-filter-domains";
import "../../../components/ha-filter-floor-areas";
import "../../../components/ha-filter-integrations";
import "../../../components/ha-filter-labels";
@@ -98,6 +96,7 @@ import { configSections } from "../ha-panel-config";
import "../integrations/ha-integration-overflow-menu";
import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
import { FILTER_NO_DEVICE } from "../../../components/ha-filter-devices";
export interface StateEntity
extends Omit<EntityRegistryEntry, "id" | "unique_id"> {
@@ -444,17 +443,17 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
entryIds.includes(entity.config_entry_id))
);
filter.value!.forEach((domain) => filteredDomains.add(domain));
} else if (key === "ha-filter-domains" && filter.value?.length) {
filteredEntities = filteredEntities.filter((entity) =>
filter.value?.includes(computeDomain(entity.entity_id))
);
} else if (key === "ha-filter-labels" && filter.value?.length) {
filteredEntities = filteredEntities.filter((entity) =>
entity.labels.some((lbl) => filter.value!.includes(lbl))
);
} else if (filter.items) {
filteredEntities = filteredEntities.filter((entity) =>
filter.items!.has(entity.entity_id)
filteredEntities = filteredEntities.filter(
(entity) =>
filter.items!.has(entity.entity_id) ||
(key === "ha-filter-devices" &&
filter.value?.includes(FILTER_NO_DEVICE) &&
!entity.device_id)
);
}
});
@@ -786,16 +785,8 @@ ${
.expanded=${this._expandedFilter === "ha-filter-devices"}
.narrow=${this.narrow}
@expanded-changed=${this._filterExpanded}
no-device-option
></ha-filter-devices>
<ha-filter-domains
.hass=${this.hass}
.value=${this._filters["ha-filter-domains"]?.value}
@data-table-filter-changed=${this._filterChanged}
slot="filter-pane"
.expanded=${this._expandedFilter === "ha-filter-domains"}
.narrow=${this.narrow}
@expanded-changed=${this._filterExpanded}
></ha-filter-domains>
<ha-filter-integrations
.hass=${this.hass}
.value=${this._filters["ha-filter-integrations"]?.value}

View File

@@ -47,7 +47,6 @@ class DialogZHAReconfigureDevice extends LitElement {
public showDialog(params: ZHAReconfigureDeviceDialogParams): void {
this._params = params;
this._clusterConfigurationStatuses = new Map();
this._stages = undefined;
}

View File

@@ -424,7 +424,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
? {
physics: {
barnesHut: {
springConstant: 0,
springConstant: 0.05,
avoidOverlap: 10,
damping: 0.09,
},

View File

@@ -122,7 +122,7 @@ export class HaManualScriptEditor extends LitElement {
<ha-automation-action
role="region"
aria-labelledby="sequence-heading"
.actions=${this.config.sequence || []}
.actions=${this.config.sequence}
.path=${["sequence"]}
@value-changed=${this._sequenceChanged}
@item-moved=${this._itemMoved}

View File

@@ -159,9 +159,6 @@ class HuiMapCard extends LitElement implements LovelaceCard {
? false
: this.hass.themes.darkMode;
const themeMode =
this._config.theme_mode || (this._config.dark_mode ? "dark" : "auto");
return html`
<ha-card id="card" .header=${this._config.title}>
<div id="root">
@@ -172,7 +169,9 @@ class HuiMapCard extends LitElement implements LovelaceCard {
.paths=${this._getHistoryPaths(this._config, this._stateHistory)}
.autoFit=${this._config.auto_fit || false}
.fitZones=${this._config.fit_zones}
.themeMode=${themeMode}
?forceDarkMode=${this._config.theme_mode === "dark" ||
this._config.dark_mode}
?forceLightMode=${this._config.theme_mode === "light"}
interactiveZones
renderPassive
></ha-map>

View File

@@ -3821,42 +3821,38 @@
}
},
"remote": {
"title": "Remote access",
"title": "Remote control",
"connected": "Connected",
"not_connected": "Not connected",
"reconnecting": "Not connected. Trying to reconnect.",
"access_is_being_prepared": "Remote access is being prepared. We will notify you when it's ready.",
"access_is_being_prepared": "Remote control is being prepared. We will notify you when it's ready.",
"cerificate_loading": "Your certificate is loading.",
"cerificate_loaded": "Your certificate is loaded, waiting for validation.",
"cerificate_error": "There was an error generating the certificate, check your logs.",
"info": "Home Assistant Cloud provides a secure remote access to your instance while away from home. For more information on remote access and these settings visit our security documentation.",
"info_instance_will_be_available": "Your instance will be available at your Nabu Casa URL.",
"info": "Home Assistant Cloud provides a secure remote connection to your instance while away from home.",
"instance_is_available": "Your instance is available at your",
"instance_will_be_available": "Your instance will be available at your",
"link_learn_how_it_works": "Learn how it works",
"show_url": "Show full URL",
"hide_url": "Hide URL",
"copy_link": "Copy link",
"security_options": "Security options",
"strict_connection": "Remote login access",
"strict_connection_secondary": "Choose what happens when new devices visit your remote access link.",
"strict_connection_option_disabled": "Show login page",
"strict_connection_option_disabled_secondary": "Any new device visiting your remote access link are presented with a login page.",
"strict_connection_option_guard_page": "Block remote logins",
"strict_connection_option_guard_page_secondary": "New devices must log in with a temporary access link. Devices accessing the link that are not logged in will be presented with a page explaining the restrictions.",
"strict_connection_option_guard_page_warning": "This prevents outsiders from trying to log in to your system but also your own devices if they have not logged in previously.",
"strict_connection_option_drop_connection": "Block remote logins and show nothing",
"strict_connection_option_drop_connection_secondary": "This is the same as the above setting but instead provides a blank page for additional security.",
"strict_connection_option_drop_connection_warning": "This prevents outsiders from snooping the remote web address and trying to log in, but it may appear as if there is no system running when users try to access it.",
"external_activation": "Allow external activation of remote access",
"external_activation_secondary": "If you disable remote access on this page, having this setting enabled allows you to reactivate it remotely via your Nabu Casa account.",
"drop_connection_warning_title": "Remote log in has been deactivated",
"drop_connection_warning": "The below security options may make it appear the system is not running.",
"strict_connection_link": "Provide temporary login access",
"strict_connection_link_secondary": "This provides a link for new devices to login for the next hour.",
"nabu_casa_url": "Nabu Casa URL",
"advanced_options": "Advanced options",
"external_activation": "Allow external activation of remote control",
"external_activation_secondary": "Allows you to turn on remote control from your Nabu Casa account page, even if you're outside your local network",
"strict_connection": "Restrict access to logged in users",
"strict_connection_secondary": "When a user is not logged in to your Home Assistant instance, they will not be able to access your instance remotely",
"strict_connection_mode": "Mode",
"strict_connection_modes": {
"disabled": "Disabled",
"guard_page": "Guard page",
"drop_connection": "Drop connection"
},
"strict_connection_link": "Create login link",
"strict_connection_link_secondary": "You can create a link that will give temporary access to the login page.",
"strict_connection_create_link": "Create link",
"strict_connection_link_created_message": "Give this link to the person you want to give remote access to the login page of your Home Assistant instance.",
"certificate_info": "Certificate information",
"certificate_expire": "Certificate renewal at {date}",
"more_info": "More details"
"strict_connection_copy_link": "Copy link",
"certificate_info": "Certificate info",
"certificate_expire": "Will be renewed at {date}",
"more_info": "More info"
},
"alexa": {
"title": "Alexa",
@@ -3945,6 +3941,7 @@
"name": "Name",
"update": "Update",
"no_devices": "No devices",
"no_device": "No device",
"enabled_label": "Enable {type}",
"enabled_cause": "The {type} is disabled by {cause}.",
"disabled_by": {

124
yarn.lock
View File

@@ -160,9 +160,9 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-define-polyfill-provider@npm:0.6.2, @babel/helper-define-polyfill-provider@npm:^0.6.1":
version: 0.6.2
resolution: "@babel/helper-define-polyfill-provider@npm:0.6.2"
"@babel/helper-define-polyfill-provider@npm:0.6.1, @babel/helper-define-polyfill-provider@npm:^0.6.1":
version: 0.6.1
resolution: "@babel/helper-define-polyfill-provider@npm:0.6.1"
dependencies:
"@babel/helper-compilation-targets": "npm:^7.22.6"
"@babel/helper-plugin-utils": "npm:^7.22.5"
@@ -171,7 +171,7 @@ __metadata:
resolve: "npm:^1.14.2"
peerDependencies:
"@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0
checksum: 10/bb32ec12024d3f16e70641bc125d2534a97edbfdabbc9f69001ec9c4ce46f877c7a224c566aa6c8c510c3b0def2e43dc4433bf6a40896ba5ce0cef4ea5ccbcff
checksum: 10/316e7c0f05d2ae233d5fbb622c6339436da8d2b2047be866b64a16e6996c078a23b4adfebbdb33bc6a9882326a6cc20b95daa79a5e0edc92e9730e36d45fa523
languageName: node
linkType: hard
@@ -4302,12 +4302,12 @@ __metadata:
languageName: node
linkType: hard
"@types/leaflet@npm:*, @types/leaflet@npm:1.9.12":
version: 1.9.12
resolution: "@types/leaflet@npm:1.9.12"
"@types/leaflet@npm:*, @types/leaflet@npm:1.9.11":
version: 1.9.11
resolution: "@types/leaflet@npm:1.9.11"
dependencies:
"@types/geojson": "npm:*"
checksum: 10/ff6dce2f613b97bdc3ceb929e6eeaaa8bef8bbafdf9758935b1d679cbaf76360e366080d77e42da58e41aac146434c5d18c70ec919d37e01e0592f0a4f2e967e
checksum: 10/a7f3936b83f1007fa74f65eee7a905e582966c3218d3a45ad1c713445038e69cdefeb668c8f0cb70bc293e77d3d801b299a90bc2fd33e52ff90fd93f342108a2
languageName: node
linkType: hard
@@ -4574,15 +4574,15 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/eslint-plugin@npm:7.7.1":
version: 7.7.1
resolution: "@typescript-eslint/eslint-plugin@npm:7.7.1"
"@typescript-eslint/eslint-plugin@npm:7.7.0":
version: 7.7.0
resolution: "@typescript-eslint/eslint-plugin@npm:7.7.0"
dependencies:
"@eslint-community/regexpp": "npm:^4.10.0"
"@typescript-eslint/scope-manager": "npm:7.7.1"
"@typescript-eslint/type-utils": "npm:7.7.1"
"@typescript-eslint/utils": "npm:7.7.1"
"@typescript-eslint/visitor-keys": "npm:7.7.1"
"@typescript-eslint/scope-manager": "npm:7.7.0"
"@typescript-eslint/type-utils": "npm:7.7.0"
"@typescript-eslint/utils": "npm:7.7.0"
"@typescript-eslint/visitor-keys": "npm:7.7.0"
debug: "npm:^4.3.4"
graphemer: "npm:^1.4.0"
ignore: "npm:^5.3.1"
@@ -4595,44 +4595,44 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/54064fe466edcebece50cf4cfc4cb18753bcba7da0e3f0db29bf628586716b14945cadf01529ebc3d823e35bc62debf21aa636ae1f5e4fa92670dce65b3dec8c
checksum: 10/9e6b6fbb9920581813c01daaa2f89419c3476e42823755c0627f4491640cfaffaebeb0592231ed4f318eefadfcdd4560b77b2903d66ab4e0c8df746a7037a603
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:7.7.1":
version: 7.7.1
resolution: "@typescript-eslint/parser@npm:7.7.1"
"@typescript-eslint/parser@npm:7.7.0":
version: 7.7.0
resolution: "@typescript-eslint/parser@npm:7.7.0"
dependencies:
"@typescript-eslint/scope-manager": "npm:7.7.1"
"@typescript-eslint/types": "npm:7.7.1"
"@typescript-eslint/typescript-estree": "npm:7.7.1"
"@typescript-eslint/visitor-keys": "npm:7.7.1"
"@typescript-eslint/scope-manager": "npm:7.7.0"
"@typescript-eslint/types": "npm:7.7.0"
"@typescript-eslint/typescript-estree": "npm:7.7.0"
"@typescript-eslint/visitor-keys": "npm:7.7.0"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^8.56.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/39cd5c686e9f7e86da669fc3622b203e1025f162d42c4f45373e827c659b8823535fe4ea62ccb5e672ef999f8491d74c8c5c4c497367c884672fc835497ea180
checksum: 10/9f8c53ca29af09cd366e37420410319c8f69e9f4a676513ecd91f5e6d822b9935b6a8ad7ec931d604fc4a0ecd93d51063d0c93227f78f2380196c8a7fa6970d1
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:7.7.1":
version: 7.7.1
resolution: "@typescript-eslint/scope-manager@npm:7.7.1"
"@typescript-eslint/scope-manager@npm:7.7.0":
version: 7.7.0
resolution: "@typescript-eslint/scope-manager@npm:7.7.0"
dependencies:
"@typescript-eslint/types": "npm:7.7.1"
"@typescript-eslint/visitor-keys": "npm:7.7.1"
checksum: 10/7823cd15e7205d2c0d9e69432717c385b2ecd7559d5edba79113c2e97c6c5e8ca3dae9343a734bc740be97e096bfcb9dfb81a3da697f9fbf5600a56a42cf70e9
"@typescript-eslint/types": "npm:7.7.0"
"@typescript-eslint/visitor-keys": "npm:7.7.0"
checksum: 10/c8890aaf99b57543774e50549c5b178c13695b21a6b30c65292268137fe5e6856cc0e050c118b47b5835dd8a48c96e042fc75891a7f6093a0b94b6b3b251afd9
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:7.7.1":
version: 7.7.1
resolution: "@typescript-eslint/type-utils@npm:7.7.1"
"@typescript-eslint/type-utils@npm:7.7.0":
version: 7.7.0
resolution: "@typescript-eslint/type-utils@npm:7.7.0"
dependencies:
"@typescript-eslint/typescript-estree": "npm:7.7.1"
"@typescript-eslint/utils": "npm:7.7.1"
"@typescript-eslint/typescript-estree": "npm:7.7.0"
"@typescript-eslint/utils": "npm:7.7.0"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.3.0"
peerDependencies:
@@ -4640,23 +4640,23 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/c64dfd3e535741270012d289d1327e487df877adfa8a9920b1f8d6616f3b7159ef8ee1d6b62e866b6a5c64d675c5008e87f4ea20b5fc032e95f197a749d38ae6
checksum: 10/a3f5358b4b7046458ea573607f3d6ea7f48e16524390b24c9360bdf8b03cc89fc6eb5da31b3e541e7f1e5f6958194ecaad5b644ca9b0d90c9a7b182f345451aa
languageName: node
linkType: hard
"@typescript-eslint/types@npm:7.7.1":
version: 7.7.1
resolution: "@typescript-eslint/types@npm:7.7.1"
checksum: 10/a1ecbaf3b8a5243394d421644f2b3eb164feea645e36dd07f1afb5008598201f19c7988141fc162c647f380dda7cf571017c0eabbbc4c5432b0143383853e134
"@typescript-eslint/types@npm:7.7.0":
version: 7.7.0
resolution: "@typescript-eslint/types@npm:7.7.0"
checksum: 10/d54ff9eeea168188fcbf1c8efe42892d1646ead801ea0a0f1312c80cfb74ee5dd61a145bc982919fb396683fb4578f98f7ad90e5d466d7aa1ca593e4338e1a2e
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:7.7.1":
version: 7.7.1
resolution: "@typescript-eslint/typescript-estree@npm:7.7.1"
"@typescript-eslint/typescript-estree@npm:7.7.0":
version: 7.7.0
resolution: "@typescript-eslint/typescript-estree@npm:7.7.0"
dependencies:
"@typescript-eslint/types": "npm:7.7.1"
"@typescript-eslint/visitor-keys": "npm:7.7.1"
"@typescript-eslint/types": "npm:7.7.0"
"@typescript-eslint/visitor-keys": "npm:7.7.0"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
@@ -4666,34 +4666,34 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/df5fe6c573b15e8058b88d1535eeca11115118adc54225f511d2762d74e2d453205ba27e63f6666cb5f3dc73d639208a183fb05db1f75063b115d52b1fae3e20
checksum: 10/40af26b3edb07af439f99728aa149bbc8668dae4a700a128abaf98d7f9bc0d5d31f8027aa1d13d6a55b22c20738d7cab84a3046a56417a2551de58671b39dbdf
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:7.7.1":
version: 7.7.1
resolution: "@typescript-eslint/utils@npm:7.7.1"
"@typescript-eslint/utils@npm:7.7.0":
version: 7.7.0
resolution: "@typescript-eslint/utils@npm:7.7.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0"
"@types/json-schema": "npm:^7.0.15"
"@types/semver": "npm:^7.5.8"
"@typescript-eslint/scope-manager": "npm:7.7.1"
"@typescript-eslint/types": "npm:7.7.1"
"@typescript-eslint/typescript-estree": "npm:7.7.1"
"@typescript-eslint/scope-manager": "npm:7.7.0"
"@typescript-eslint/types": "npm:7.7.0"
"@typescript-eslint/typescript-estree": "npm:7.7.0"
semver: "npm:^7.6.0"
peerDependencies:
eslint: ^8.56.0
checksum: 10/5a352c3a849300b5d676bf5f451418a2fb0cd3ab515f3733521ad03cf047849c52c76f6e5d2406e08f6d0dbad3a4708b490f909c91a1a9e3d73060a750b3bca2
checksum: 10/4223233ee022460a74f389302b50779537dfbb3bd414486dca356d2628a08d5b2c4c6002bae3bdffad92b368569024faf25faee9be739340d9459c23549a866f
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:7.7.1":
version: 7.7.1
resolution: "@typescript-eslint/visitor-keys@npm:7.7.1"
"@typescript-eslint/visitor-keys@npm:7.7.0":
version: 7.7.0
resolution: "@typescript-eslint/visitor-keys@npm:7.7.0"
dependencies:
"@typescript-eslint/types": "npm:7.7.1"
"@typescript-eslint/types": "npm:7.7.0"
eslint-visitor-keys: "npm:^3.4.3"
checksum: 10/dcc5748b10bb1b169516b33e87b6d86b562e25725a95e5ac515cb197589d9667aaa7cfffa93234095a73c80addb6dd88e2a9ab01d2be0c274254b5be1ca4057a
checksum: 10/9f03591ab60b0b164f6bb222b5d5ae75f73fbe7f264be9318f770be9dc5dff8138d34701928940ffc18924058ae80754a738a1e623912a297d57a8a59cdfb41d
languageName: node
linkType: hard
@@ -9556,7 +9556,7 @@ __metadata:
resolution: "home-assistant-frontend@workspace:."
dependencies:
"@babel/core": "npm:7.24.4"
"@babel/helper-define-polyfill-provider": "npm:0.6.2"
"@babel/helper-define-polyfill-provider": "npm:0.6.1"
"@babel/plugin-proposal-decorators": "npm:7.24.1"
"@babel/plugin-transform-runtime": "npm:7.24.3"
"@babel/preset-env": "npm:7.24.4"
@@ -9644,7 +9644,7 @@ __metadata:
"@types/glob": "npm:8.1.0"
"@types/html-minifier-terser": "npm:7.0.2"
"@types/js-yaml": "npm:4.0.9"
"@types/leaflet": "npm:1.9.12"
"@types/leaflet": "npm:1.9.11"
"@types/leaflet-draw": "npm:1.0.11"
"@types/luxon": "npm:3.4.2"
"@types/mocha": "npm:10.0.6"
@@ -9654,8 +9654,8 @@ __metadata:
"@types/tar": "npm:6.1.13"
"@types/ua-parser-js": "npm:0.7.39"
"@types/webspeechapi": "npm:0.0.29"
"@typescript-eslint/eslint-plugin": "npm:7.7.1"
"@typescript-eslint/parser": "npm:7.7.1"
"@typescript-eslint/eslint-plugin": "npm:7.7.0"
"@typescript-eslint/parser": "npm:7.7.0"
"@vaadin/combo-box": "npm:24.3.11"
"@vaadin/vaadin-themable-mixin": "npm:24.3.11"
"@vibrant/color": "npm:3.2.1-alpha.1"