mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
20240202.0Merge branch 'dev' into rc
This commit is contained in:
commit
696717dd90
10
package.json
10
package.json
@ -109,7 +109,7 @@
|
||||
"element-internals-polyfill": "1.3.10",
|
||||
"fuse.js": "7.0.0",
|
||||
"google-timezones-json": "1.2.0",
|
||||
"hls.js": "1.5.2",
|
||||
"hls.js": "1.5.3",
|
||||
"home-assistant-js-websocket": "9.1.0",
|
||||
"idb-keyval": "6.2.1",
|
||||
"intl-messageformat": "10.5.11",
|
||||
@ -183,8 +183,8 @@
|
||||
"@types/tar": "6.1.11",
|
||||
"@types/ua-parser-js": "0.7.39",
|
||||
"@types/webspeechapi": "0.0.29",
|
||||
"@typescript-eslint/eslint-plugin": "6.19.1",
|
||||
"@typescript-eslint/parser": "6.19.1",
|
||||
"@typescript-eslint/eslint-plugin": "6.20.0",
|
||||
"@typescript-eslint/parser": "6.20.0",
|
||||
"@web/dev-server": "0.1.38",
|
||||
"@web/dev-server-rollup": "0.4.1",
|
||||
"babel-loader": "9.1.3",
|
||||
@ -199,7 +199,7 @@
|
||||
"eslint-plugin-disable": "2.0.3",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-lit": "1.11.0",
|
||||
"eslint-plugin-lit-a11y": "4.1.1",
|
||||
"eslint-plugin-lit-a11y": "4.1.2",
|
||||
"eslint-plugin-unused-imports": "3.0.0",
|
||||
"eslint-plugin-wc": "2.0.4",
|
||||
"fancy-log": "2.0.0",
|
||||
@ -212,7 +212,7 @@
|
||||
"gulp-rename": "2.0.0",
|
||||
"gulp-zopfli-green": "6.0.1",
|
||||
"html-minifier-terser": "7.2.0",
|
||||
"husky": "9.0.6",
|
||||
"husky": "9.0.7",
|
||||
"instant-mocha": "1.5.2",
|
||||
"jszip": "3.10.1",
|
||||
"lint-staged": "15.2.0",
|
||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "home-assistant-frontend"
|
||||
version = "20240131.0"
|
||||
version = "20240202.0"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "The Home Assistant frontend"
|
||||
readme = "README.md"
|
||||
|
@ -38,4 +38,8 @@ export function setDirectionStyles(direction: string, element: LitElement) {
|
||||
"--margin-title",
|
||||
direction === "ltr" ? "var(--margin-title-ltr)" : "var(--margin-title-rtl)"
|
||||
);
|
||||
element.style.setProperty(
|
||||
"--scale-direction",
|
||||
direction === "ltr" ? "1" : "-1"
|
||||
);
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { clamp } from "../../common/number/clamp";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { debounce } from "../../common/util/debounce";
|
||||
|
||||
@ -212,12 +211,10 @@ export class HaChartBase extends LitElement {
|
||||
height: `${
|
||||
this.height ?? this._chartHeight ?? this.clientWidth / 2
|
||||
}px`,
|
||||
"padding-left": `${
|
||||
computeRTL(this.hass) ? 0 : this._paddingYAxisInternal
|
||||
}px`,
|
||||
"padding-right": `${
|
||||
computeRTL(this.hass) ? this._paddingYAxisInternal : 0
|
||||
}px`,
|
||||
"padding-left": `${this._paddingYAxisInternal}`,
|
||||
"padding-right": 0,
|
||||
"padding-inline-start": `${this._paddingYAxisInternal}`,
|
||||
"padding-inline-end": 0,
|
||||
})}
|
||||
>
|
||||
<canvas></canvas>
|
||||
@ -433,14 +430,6 @@ export class HaChartBase extends LitElement {
|
||||
.chartTooltip .bullet {
|
||||
align-self: baseline;
|
||||
}
|
||||
:host([rtl]) .chartLegend .bullet,
|
||||
:host([rtl]) .chartTooltip .bullet {
|
||||
margin-right: inherit;
|
||||
margin-left: 6px;
|
||||
margin-inline-end: inherit;
|
||||
margin-inline-start: 6px;
|
||||
direction: var(--direction);
|
||||
}
|
||||
.chartTooltip {
|
||||
padding: 8px;
|
||||
font-size: 90%;
|
||||
@ -449,12 +438,13 @@ export class HaChartBase extends LitElement {
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
z-index: 1;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
width: 200px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:host([rtl]) .chartTooltip {
|
||||
direction: rtl;
|
||||
direction: var(--direction);
|
||||
}
|
||||
.chartLegend ul,
|
||||
.chartTooltip ul {
|
||||
|
@ -220,7 +220,12 @@ export class StateHistoryChartLine extends LitElement {
|
||||
// @ts-expect-error
|
||||
locale: numberFormatToLocale(this.hass.locale),
|
||||
onClick: (e: any) => {
|
||||
if (!this.clickForMoreInfo) {
|
||||
if (
|
||||
!this.clickForMoreInfo ||
|
||||
!(e.native instanceof MouseEvent) ||
|
||||
(e.native instanceof PointerEvent &&
|
||||
e.native.pointerType !== "mouse")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,11 @@ export class StateHistoryChartTimeline extends LitElement {
|
||||
// @ts-expect-error
|
||||
locale: numberFormatToLocale(this.hass.locale),
|
||||
onClick: (e: any) => {
|
||||
if (!this.clickForMoreInfo) {
|
||||
if (
|
||||
!this.clickForMoreInfo ||
|
||||
!(e.native instanceof MouseEvent) ||
|
||||
(e.native instanceof PointerEvent && e.native.pointerType !== "mouse")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -688,15 +688,12 @@ export class HaDataTable extends LitElement {
|
||||
padding-left: 16px;
|
||||
/* @noflip */
|
||||
padding-right: 0;
|
||||
/* @noflip */
|
||||
padding-inline-start: 16px;
|
||||
/* @noflip */
|
||||
padding-inline-end: initial;
|
||||
width: 60px;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__header-cell--checkbox,
|
||||
:host([dir="rtl"]) .mdc-data-table__cell--checkbox {
|
||||
/* @noflip */
|
||||
padding-left: 0;
|
||||
/* @noflip */
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.mdc-data-table__table {
|
||||
height: 100%;
|
||||
@ -723,11 +720,7 @@ export class HaDataTable extends LitElement {
|
||||
}
|
||||
|
||||
.mdc-data-table__cell--numeric {
|
||||
text-align: right;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__cell--numeric {
|
||||
/* @noflip */
|
||||
text-align: left;
|
||||
text-align: var(--float-end);
|
||||
}
|
||||
|
||||
.mdc-data-table__cell--icon {
|
||||
@ -753,15 +746,7 @@ export class HaDataTable extends LitElement {
|
||||
.mdc-data-table__header-cell.sortable.mdc-data-table__header-cell--icon:not(
|
||||
.not-sorted
|
||||
) {
|
||||
text-align: left;
|
||||
}
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell.sortable.mdc-data-table__header-cell--icon:hover,
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell.sortable.mdc-data-table__header-cell--icon:not(
|
||||
.not-sorted
|
||||
) {
|
||||
text-align: right;
|
||||
text-align: var(--float-start);
|
||||
}
|
||||
|
||||
.mdc-data-table__cell--icon:first-child img,
|
||||
@ -771,27 +756,14 @@ export class HaDataTable extends LitElement {
|
||||
.mdc-data-table__cell--icon:first-child ha-domain-icon,
|
||||
.mdc-data-table__cell--icon:first-child ha-service-icon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__cell--icon:first-child ha-icon,
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__cell--icon:first-child
|
||||
ha-state-icon,
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__cell--icon:first-child
|
||||
ha-svg-icon
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__cell--icon:first-child
|
||||
img {
|
||||
margin-left: auto;
|
||||
margin-right: 8px;
|
||||
margin-inline-start: 8px;
|
||||
margin-inline-end: initial;
|
||||
}
|
||||
|
||||
.mdc-data-table__cell--icon:first-child state-badge {
|
||||
margin-right: -8px;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__cell--icon:first-child state-badge {
|
||||
margin-right: auto;
|
||||
margin-left: -8px;
|
||||
margin-inline-end: -8px;
|
||||
margin-inline-start: initial;
|
||||
}
|
||||
|
||||
.mdc-data-table__cell--overflow-menu,
|
||||
@ -824,15 +796,8 @@ export class HaDataTable extends LitElement {
|
||||
.mdc-data-table__header-cell--icon-button:first-child,
|
||||
.mdc-data-table__cell--icon-button:first-child {
|
||||
padding-left: 16px;
|
||||
}
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell--overflow-menu:first-child,
|
||||
:host([dir="rtl"]) .mdc-data-table__cell--overflow-menu:first-child,
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell--overflow-menu:first-child,
|
||||
:host([dir="rtl"]) .mdc-data-table__cell--overflow-menu:first-child {
|
||||
padding-left: 8px;
|
||||
padding-right: 16px;
|
||||
padding-inline-start: 16px;
|
||||
padding-inline-end: initial; // 8px?
|
||||
}
|
||||
|
||||
.mdc-data-table__cell--overflow-menu:last-child,
|
||||
@ -840,14 +805,8 @@ export class HaDataTable extends LitElement {
|
||||
.mdc-data-table__header-cell--icon-button:last-child,
|
||||
.mdc-data-table__cell--icon-button:last-child {
|
||||
padding-right: 16px;
|
||||
}
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell--overflow-menu:last-child,
|
||||
:host([dir="rtl"]) .mdc-data-table__cell--overflow-menu:last-child,
|
||||
:host([dir="rtl"]) .mdc-data-table__header-cell--icon-button:last-child,
|
||||
:host([dir="rtl"]) .mdc-data-table__cell--icon-button:last-child {
|
||||
padding-right: 8px;
|
||||
padding-left: 16px;
|
||||
padding-inline-end: 16px;
|
||||
padding-inline-start: initial; // 8px?
|
||||
}
|
||||
.mdc-data-table__cell--overflow-menu,
|
||||
.mdc-data-table__header-cell--overflow-menu {
|
||||
@ -867,28 +826,15 @@ export class HaDataTable extends LitElement {
|
||||
letter-spacing: 0.0071428571em;
|
||||
text-decoration: inherit;
|
||||
text-transform: inherit;
|
||||
text-align: left;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__header-cell {
|
||||
/* @noflip */
|
||||
text-align: right;
|
||||
text-align: var(--float-start);
|
||||
}
|
||||
|
||||
.mdc-data-table__header-cell--numeric {
|
||||
text-align: right;
|
||||
text-align: var(--float-end);
|
||||
}
|
||||
.mdc-data-table__header-cell--numeric.sortable:hover,
|
||||
.mdc-data-table__header-cell--numeric.sortable:not(.not-sorted) {
|
||||
text-align: left;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__header-cell--numeric {
|
||||
/* @noflip */
|
||||
text-align: left;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__header-cell--numeric.sortable:hover,
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell--numeric.sortable:not(.not-sorted) {
|
||||
text-align: right;
|
||||
text-align: var(--float-start);
|
||||
}
|
||||
|
||||
/* custom from here */
|
||||
@ -909,20 +855,15 @@ export class HaDataTable extends LitElement {
|
||||
.mdc-data-table__header-cell span {
|
||||
position: relative;
|
||||
left: 0px;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__header-cell span {
|
||||
left: auto;
|
||||
right: 0px;
|
||||
inset-inline-start: 0px;
|
||||
inset-inline-end: initial;
|
||||
}
|
||||
|
||||
.mdc-data-table__header-cell.sortable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.mdc-data-table__header-cell > * {
|
||||
transition: left 0.2s ease;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__header-cell > * {
|
||||
transition: right 0.2s ease;
|
||||
transition: var(--float-start) 0.2s ease;
|
||||
}
|
||||
.mdc-data-table__header-cell ha-svg-icon {
|
||||
top: -3px;
|
||||
@ -930,35 +871,20 @@ export class HaDataTable extends LitElement {
|
||||
}
|
||||
.mdc-data-table__header-cell.not-sorted ha-svg-icon {
|
||||
left: -20px;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-data-table__header-cell.not-sorted ha-svg-icon {
|
||||
right: -20px;
|
||||
inset-inline-start: -20px;
|
||||
inset-inline-end: initial;
|
||||
}
|
||||
.mdc-data-table__header-cell.sortable:not(.not-sorted) span,
|
||||
.mdc-data-table__header-cell.sortable.not-sorted:hover span {
|
||||
left: 24px;
|
||||
}
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell.sortable:not(.not-sorted)
|
||||
span,
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell.sortable.not-sorted:hover
|
||||
span {
|
||||
left: auto;
|
||||
right: 24px;
|
||||
inset-inline-start: 24px;
|
||||
inset-inline-end: initial;
|
||||
}
|
||||
.mdc-data-table__header-cell.sortable:not(.not-sorted) ha-svg-icon,
|
||||
.mdc-data-table__header-cell.sortable:hover.not-sorted ha-svg-icon {
|
||||
left: 12px;
|
||||
}
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell.sortable:not(.not-sorted)
|
||||
ha-svg-icon,
|
||||
:host([dir="rtl"])
|
||||
.mdc-data-table__header-cell.sortable:hover.not-sorted
|
||||
ha-svg-icon {
|
||||
left: auto;
|
||||
right: 12px;
|
||||
inset-inline-start: 12px;
|
||||
inset-inline-end: initial;
|
||||
}
|
||||
.table-header {
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
@ -966,6 +892,8 @@ export class HaDataTable extends LitElement {
|
||||
search-input {
|
||||
display: block;
|
||||
flex: 1;
|
||||
--mdc-text-field-fill-color: var(--sidebar-background-color);
|
||||
--mdc-text-field-idle-line-color: transparent;
|
||||
}
|
||||
slot[name="header"] {
|
||||
display: block;
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
localizeWeekdays,
|
||||
localizeMonths,
|
||||
} from "../common/datetime/localize_date";
|
||||
import { mainWindow } from "../common/dom/get_main_window";
|
||||
|
||||
// Set the current date to the left picker instead of the right picker because the right is hidden
|
||||
const CustomDateRangePicker = Vue.extend({
|
||||
@ -157,7 +158,7 @@ class DateRangePickerElement extends WrappedElement {
|
||||
min-width: initial !important;
|
||||
max-height: var(--date-range-picker-max-height);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
.daterangepicker:before {
|
||||
display: none;
|
||||
}
|
||||
@ -267,15 +268,37 @@ class DateRangePickerElement extends WrappedElement {
|
||||
.calendar-table {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.daterangepicker.ltr {
|
||||
.calendar-time {
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
}
|
||||
.daterangepicker.ltr {
|
||||
direction: var(--direction);
|
||||
text-align: var(--float-start);
|
||||
}
|
||||
.vue-daterange-picker{
|
||||
min-width: unset !important;
|
||||
display: block !important;
|
||||
}
|
||||
`;
|
||||
if (mainWindow.document.dir === "rtl") {
|
||||
style.innerHTML += `
|
||||
.daterangepicker .calendar-table .next span {
|
||||
transform: rotate(135deg);
|
||||
-webkit-transform: rotate(135deg);
|
||||
}
|
||||
.daterangepicker .calendar-table .prev span {
|
||||
transform: rotate(-45deg);
|
||||
-webkit-transform: rotate(-45deg);
|
||||
}
|
||||
.daterangepicker td.start-date {
|
||||
border-radius: 0 50% 50% 0;
|
||||
}
|
||||
.daterangepicker td.end-date {
|
||||
border-radius: 50% 0 0 50%;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
const shadowRoot = this.shadowRoot!;
|
||||
shadowRoot.appendChild(style);
|
||||
// Stop click events from reaching the document, otherwise it will close the picker immediately.
|
||||
|
@ -3,7 +3,6 @@ import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import "../ha-relative-time";
|
||||
import "./state-badge";
|
||||
@ -16,9 +15,6 @@ class StateInfo extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public inDialog = false;
|
||||
|
||||
// property used only in CSS
|
||||
@property({ type: Boolean, reflect: true }) public rtl = false;
|
||||
|
||||
@property() public color?: string;
|
||||
|
||||
protected render() {
|
||||
@ -79,18 +75,6 @@ class StateInfo extends LitElement {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
protected updated(changedProps) {
|
||||
super.updated(changedProps);
|
||||
if (!changedProps.has("hass")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.locale !== this.hass.locale) {
|
||||
this.rtl = computeRTL(this.hass);
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
:host {
|
||||
@ -106,17 +90,14 @@ class StateInfo extends LitElement {
|
||||
|
||||
.info {
|
||||
margin-left: 8px;
|
||||
margin-inline-start: 8px;
|
||||
margin-inline-end: initial;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
:host([rtl]) .info {
|
||||
margin-right: 8px;
|
||||
margin-left: 0;
|
||||
text-align: right;
|
||||
text-align: var(--float-start);
|
||||
}
|
||||
|
||||
.name {
|
||||
|
@ -69,6 +69,7 @@ export class HaButtonToggleGroup extends LitElement {
|
||||
display: flex;
|
||||
--mdc-icon-button-size: var(--button-toggle-size, 36px);
|
||||
--mdc-icon-size: var(--button-toggle-icon-size, 20px);
|
||||
direction: ltr;
|
||||
}
|
||||
mwc-button {
|
||||
--mdc-shape-small: 0;
|
||||
@ -119,19 +120,6 @@ export class HaButtonToggleGroup extends LitElement {
|
||||
--mdc-shape-small: 4px;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
:host([dir="rtl"]) ha-icon-button:first-child,
|
||||
:host([dir="rtl"]) mwc-button:first-child {
|
||||
border-radius: 0 4px 4px 0;
|
||||
border-right-width: 1px;
|
||||
--mdc-shape-small: 0 4px 4px 0;
|
||||
--mdc-button-outline-width: 1px;
|
||||
}
|
||||
:host([dir="rtl"]) ha-icon-button:last-child,
|
||||
:host([dir="rtl"]) mwc-button:last-child {
|
||||
--mdc-shape-small: 4px 0 0 4px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import { firstWeekdayIndex } from "../common/datetime/first_weekday";
|
||||
import { formatDate } from "../common/datetime/format_date";
|
||||
import { formatDateTime } from "../common/datetime/format_date_time";
|
||||
import { useAmPm } from "../common/datetime/use_am_pm";
|
||||
import { computeRTLDirection } from "../common/util/compute_rtl";
|
||||
import { HomeAssistant } from "../types";
|
||||
import "./date-range-picker";
|
||||
import "./ha-icon-button";
|
||||
@ -65,8 +64,6 @@ export class HaDateRangePicker extends LitElement {
|
||||
|
||||
@state() private _hour24format = false;
|
||||
|
||||
@state() private _rtlDirection = "ltr";
|
||||
|
||||
@property({ type: Boolean }) public extendedPresets = false;
|
||||
|
||||
@property() public openingDirection?: "right" | "left" | "center" | "inline";
|
||||
@ -236,7 +233,6 @@ export class HaDateRangePicker extends LitElement {
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.locale !== this.hass.locale) {
|
||||
this._hour24format = !useAmPm(this.hass.locale);
|
||||
this._rtlDirection = computeRTLDirection(this.hass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -306,11 +302,7 @@ export class HaDateRangePicker extends LitElement {
|
||||
></ha-icon-button>`}
|
||||
</div>
|
||||
${this.ranges !== false && (this.ranges || this._ranges)
|
||||
? html`<div
|
||||
slot="ranges"
|
||||
class="date-range-ranges"
|
||||
.dir=${this._rtlDirection}
|
||||
>
|
||||
? html`<div slot="ranges" class="date-range-ranges">
|
||||
<mwc-list @action=${this._setDateRange} activatable>
|
||||
${Object.keys(this.ranges || this._ranges!).map(
|
||||
(name) => html`<mwc-list-item>${name}</mwc-list-item>`
|
||||
|
@ -3,6 +3,7 @@ import { styles } from "@material/mwc-drawer/mwc-drawer.css";
|
||||
import { css, PropertyValues } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { mainWindow } from "../common/dom/get_main_window";
|
||||
|
||||
const blockingElements = (document as any).$blockingElements;
|
||||
|
||||
@ -12,6 +13,8 @@ export class HaDrawer extends DrawerBase {
|
||||
|
||||
private _mc?: HammerManager;
|
||||
|
||||
private _rtlStyle?: HTMLElement;
|
||||
|
||||
protected createAdapter() {
|
||||
return {
|
||||
...super.createAdapter(),
|
||||
@ -31,8 +34,26 @@ export class HaDrawer extends DrawerBase {
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
super.updated(changedProps);
|
||||
if (changedProps.has("direction")) {
|
||||
this.mdcRoot.dir = this.direction;
|
||||
if (mainWindow.document.dir === "rtl") {
|
||||
this._rtlStyle = document.createElement("style");
|
||||
this._rtlStyle.innerHTML = `
|
||||
.mdc-drawer--animate {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
.mdc-drawer--opening {
|
||||
transform: translateX(0);
|
||||
}
|
||||
.mdc-drawer--closing {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
`;
|
||||
|
||||
this.shadowRoot!.appendChild(this._rtlStyle);
|
||||
} else if (this._rtlStyle) {
|
||||
this.shadowRoot!.removeChild(this._rtlStyle);
|
||||
}
|
||||
}
|
||||
|
||||
if (changedProps.has("open") && this.open && this.type === "modal") {
|
||||
this._setupSwipe();
|
||||
} else if (this._mc) {
|
||||
@ -66,6 +87,8 @@ export class HaDrawer extends DrawerBase {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
border-color: var(--divider-color, rgba(0, 0, 0, 0.12));
|
||||
inset-inline-start: 0 !important;
|
||||
inset-inline-end: initial !important;
|
||||
}
|
||||
.mdc-drawer.mdc-drawer--modal.mdc-drawer--open {
|
||||
z-index: 200;
|
||||
|
@ -38,7 +38,6 @@ import { storage } from "../common/decorators/storage";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { toggleAttribute } from "../common/dom/toggle_attribute";
|
||||
import { stringCompare } from "../common/string/compare";
|
||||
import { computeRTL } from "../common/util/compute_rtl";
|
||||
import { throttle } from "../common/util/throttle";
|
||||
import { ActionHandlerDetail } from "../data/lovelace/action_handler";
|
||||
import {
|
||||
@ -307,16 +306,12 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.locale !== this.hass.locale) {
|
||||
toggleAttribute(this, "rtl", computeRTL(this.hass));
|
||||
}
|
||||
|
||||
this._calculateCounts();
|
||||
|
||||
if (!SUPPORT_SCROLL_IF_NEEDED) {
|
||||
return;
|
||||
}
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.panelUrl !== this.hass.panelUrl) {
|
||||
const selectedEl = this.shadowRoot!.querySelector(".iron-selected");
|
||||
if (selectedEl) {
|
||||
@ -851,29 +846,22 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
font-size: 20px;
|
||||
align-items: center;
|
||||
padding-left: calc(4px + env(safe-area-inset-left));
|
||||
}
|
||||
:host([rtl]) .menu {
|
||||
padding-left: 4px;
|
||||
padding-right: calc(4px + env(safe-area-inset-right));
|
||||
padding-inline-start: calc(4px + env(safe-area-inset-left));
|
||||
padding-inline-end: initial;
|
||||
}
|
||||
:host([expanded]) .menu {
|
||||
width: calc(256px + env(safe-area-inset-left));
|
||||
}
|
||||
:host([rtl][expanded]) .menu {
|
||||
width: calc(256px + env(safe-area-inset-right));
|
||||
}
|
||||
.menu ha-icon-button {
|
||||
color: var(--sidebar-icon-color);
|
||||
}
|
||||
.title {
|
||||
margin-left: 19px;
|
||||
margin-inline-start: 19px;
|
||||
margin-inline-end: initial;
|
||||
width: 100%;
|
||||
display: none;
|
||||
}
|
||||
:host([rtl]) .title {
|
||||
margin-left: 0;
|
||||
margin-right: 19px;
|
||||
}
|
||||
:host([narrow]) .title {
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
@ -904,11 +892,8 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
overflow-x: hidden;
|
||||
background: none;
|
||||
margin-left: env(safe-area-inset-left);
|
||||
}
|
||||
|
||||
:host([rtl]) paper-listbox {
|
||||
margin-left: initial;
|
||||
margin-right: env(safe-area-inset-right);
|
||||
margin-inline-start: env(safe-area-inset-left);
|
||||
margin-inline-end: initial;
|
||||
}
|
||||
|
||||
a {
|
||||
@ -925,6 +910,8 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
box-sizing: border-box;
|
||||
margin: 4px;
|
||||
padding-left: 12px;
|
||||
padding-inline-start: 12px;
|
||||
padding-inline-end: initial;
|
||||
border-radius: 4px;
|
||||
--paper-item-min-height: 40px;
|
||||
width: 48px;
|
||||
@ -932,10 +919,6 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
:host([expanded]) paper-icon-item {
|
||||
width: 248px;
|
||||
}
|
||||
:host([rtl]) paper-icon-item {
|
||||
padding-left: auto;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
ha-icon[slot="item-icon"],
|
||||
ha-svg-icon[slot="item-icon"] {
|
||||
@ -1010,11 +993,8 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
.configuration-container {
|
||||
display: flex;
|
||||
margin-left: env(safe-area-inset-left);
|
||||
}
|
||||
:host([rtl]) .notifications-container,
|
||||
:host([rtl]) .configuration-container {
|
||||
margin-left: initial;
|
||||
margin-right: env(safe-area-inset-right);
|
||||
margin-inline-start: env(safe-area-inset-left);
|
||||
margin-inline-end: initial;
|
||||
}
|
||||
.notifications {
|
||||
cursor: pointer;
|
||||
@ -1025,23 +1005,18 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
.profile {
|
||||
margin-left: env(safe-area-inset-left);
|
||||
}
|
||||
:host([rtl]) .profile {
|
||||
margin-left: initial;
|
||||
margin-right: env(safe-area-inset-right);
|
||||
margin-inline-start: env(safe-area-inset-left);
|
||||
margin-inline-end: initial;
|
||||
}
|
||||
.profile paper-icon-item {
|
||||
padding-left: 4px;
|
||||
}
|
||||
:host([rtl]) .profile paper-icon-item {
|
||||
padding-left: auto;
|
||||
padding-right: 4px;
|
||||
margin-inline-start: 4px;
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
.profile .item-text {
|
||||
margin-left: 8px;
|
||||
}
|
||||
:host([rtl]) .profile .item-text {
|
||||
margin-right: 8px;
|
||||
margin-inline-start: 8px;
|
||||
margin-inline-end: initial;
|
||||
}
|
||||
|
||||
.notification-badge,
|
||||
@ -1106,9 +1081,9 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
:host([rtl]) .menu ha-icon-button {
|
||||
-webkit-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
.menu ha-icon-button {
|
||||
-webkit-transform: scaleX(var(--scale-direction));
|
||||
transform: scaleX(var(--scale-direction));
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@ -2,9 +2,15 @@ import { customElement } from "lit/decorators";
|
||||
import "element-internals-polyfill";
|
||||
import { MdSlider } from "@material/web/slider/slider";
|
||||
import { CSSResult, css } from "lit";
|
||||
import { mainWindow } from "../common/dom/get_main_window";
|
||||
|
||||
@customElement("ha-slider")
|
||||
export class HaSlider extends MdSlider {
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.dir = mainWindow.document.dir;
|
||||
}
|
||||
|
||||
static override styles: CSSResult[] = [
|
||||
...MdSlider.styles,
|
||||
css`
|
||||
|
@ -39,6 +39,12 @@ export class HaSortable extends LitElement {
|
||||
@property({ type: String, attribute: "group" })
|
||||
public group?: string;
|
||||
|
||||
@property({ type: Number, attribute: "swap-threshold" })
|
||||
public swapThreshold?: number;
|
||||
|
||||
@property({ type: Boolean, attribute: "invert-swap" })
|
||||
public invertSwap?: boolean;
|
||||
|
||||
protected updated(changedProperties: PropertyValues<this>) {
|
||||
if (changedProperties.has("disabled")) {
|
||||
if (this.disabled) {
|
||||
@ -81,7 +87,7 @@ export class HaSortable extends LitElement {
|
||||
}
|
||||
|
||||
.sortable-ghost {
|
||||
border: 2px solid var(--primary-color);
|
||||
box-shadow: 0 0 0 2px var(--primary-color);
|
||||
background: rgba(var(--rgb-primary-color), 0.25);
|
||||
border-radius: 4px;
|
||||
opacity: 0.4;
|
||||
@ -108,7 +114,7 @@ export class HaSortable extends LitElement {
|
||||
|
||||
const options: SortableInstance.Options = {
|
||||
animation: 150,
|
||||
swapThreshold: 0.75,
|
||||
swapThreshold: 1,
|
||||
onChoose: this._handleChoose,
|
||||
onEnd: this._handleEnd,
|
||||
};
|
||||
@ -116,6 +122,13 @@ export class HaSortable extends LitElement {
|
||||
if (this.draggableSelector) {
|
||||
options.draggable = this.draggableSelector;
|
||||
}
|
||||
|
||||
if (this.swapThreshold !== undefined) {
|
||||
options.swapThreshold = this.swapThreshold;
|
||||
}
|
||||
if (this.invertSwap !== undefined) {
|
||||
options.invertSwap = this.invertSwap;
|
||||
}
|
||||
if (this.handleSelector) {
|
||||
options.handle = this.handleSelector;
|
||||
}
|
||||
|
@ -3,18 +3,11 @@ import { styles as textfieldStyles } from "@material/mwc-textfield/mwc-textfield
|
||||
import { styles as textareaStyles } from "@material/mwc-textarea/mwc-textarea.css";
|
||||
import { css, PropertyValues } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { mainWindow } from "../common/dom/get_main_window";
|
||||
|
||||
@customElement("ha-textarea")
|
||||
export class HaTextArea extends TextAreaBase {
|
||||
@property({ type: Boolean, reflect: true }) autogrow = false;
|
||||
|
||||
firstUpdated() {
|
||||
super.firstUpdated();
|
||||
|
||||
this.setAttribute("dir", mainWindow.document.dir);
|
||||
}
|
||||
|
||||
updated(changedProperties: PropertyValues) {
|
||||
super.updated(changedProperties);
|
||||
if (this.autogrow && changedProperties.has("value")) {
|
||||
@ -54,9 +47,10 @@ export class HaTextArea extends TextAreaBase {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
:host([dir="rtl"]) .mdc-floating-label {
|
||||
right: 16px;
|
||||
left: initial;
|
||||
.mdc-floating-label {
|
||||
inset-inline-start: 16px !important;
|
||||
inset-inline-end: initial !important;
|
||||
transform-origin: var(--float-start) top;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@ -8,12 +8,18 @@ import type {
|
||||
Marker,
|
||||
Polyline,
|
||||
} from "leaflet";
|
||||
import { isToday } from "date-fns";
|
||||
import { css, CSSResultGroup, PropertyValues, ReactiveElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
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";
|
||||
@ -27,12 +33,14 @@ const getEntityId = (entity: string | HaMapEntity): string =>
|
||||
|
||||
export interface HaMapPathPoint {
|
||||
point: LatLngTuple;
|
||||
tooltip: string;
|
||||
timestamp: Date;
|
||||
}
|
||||
export interface HaMapPaths {
|
||||
points: HaMapPathPoint[];
|
||||
color?: string;
|
||||
name?: string;
|
||||
gradualOpacity?: number;
|
||||
fullDatetime?: boolean;
|
||||
}
|
||||
|
||||
export interface HaMapEntity {
|
||||
@ -242,6 +250,30 @@ export class HaMap extends ReactiveElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _computePathTooltip(path: HaMapPaths, point: HaMapPathPoint): string {
|
||||
let formattedTime: string;
|
||||
if (path.fullDatetime) {
|
||||
formattedTime = formatDateTime(
|
||||
point.timestamp,
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
);
|
||||
} else if (isToday(point.timestamp)) {
|
||||
formattedTime = formatTimeWithSeconds(
|
||||
point.timestamp,
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
);
|
||||
} else {
|
||||
formattedTime = formatTimeWeekday(
|
||||
point.timestamp,
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
);
|
||||
}
|
||||
return `${path.name}<br>${formattedTime}`;
|
||||
}
|
||||
|
||||
private _drawPaths(): void {
|
||||
const hass = this.hass;
|
||||
const map = this.leafletMap;
|
||||
@ -289,7 +321,10 @@ export class HaMap extends ReactiveElement {
|
||||
fillOpacity: opacity,
|
||||
interactive: true,
|
||||
})
|
||||
.bindTooltip(path.points[pointIndex].tooltip, { direction: "top" })
|
||||
.bindTooltip(
|
||||
this._computePathTooltip(path, path.points[pointIndex]),
|
||||
{ direction: "top" }
|
||||
)
|
||||
);
|
||||
|
||||
// DRAW line between this and next point
|
||||
@ -319,7 +354,10 @@ export class HaMap extends ReactiveElement {
|
||||
fillOpacity: opacity,
|
||||
interactive: true,
|
||||
})
|
||||
.bindTooltip(path.points[pointIndex].tooltip, { direction: "top" })
|
||||
.bindTooltip(
|
||||
this._computePathTooltip(path, path.points[pointIndex]),
|
||||
{ direction: "top" }
|
||||
)
|
||||
);
|
||||
}
|
||||
this._mapPaths.forEach((marker) => map.addLayer(marker));
|
||||
@ -556,6 +594,7 @@ export class HaMap extends ReactiveElement {
|
||||
color: white !important;
|
||||
border-radius: 4px;
|
||||
box-shadow: none !important;
|
||||
text-align: center;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import { classMap } from "lit/directives/class-map";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { until } from "lit/directives/until";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { computeRTLDirection } from "../../common/util/compute_rtl";
|
||||
import { debounce } from "../../common/util/debounce";
|
||||
import { isUnavailableState } from "../../data/entity";
|
||||
import type { MediaPlayerItem } from "../../data/media-player";
|
||||
@ -539,7 +538,6 @@ export class HaMediaPlayerBrowse extends LitElement {
|
||||
.graphic=${mediaClass.show_list_images
|
||||
? "medium"
|
||||
: "avatar"}
|
||||
dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<span class="title">
|
||||
${this.hass.localize(
|
||||
@ -637,7 +635,6 @@ export class HaMediaPlayerBrowse extends LitElement {
|
||||
@click=${this._childClicked}
|
||||
.item=${child}
|
||||
.graphic=${mediaClass.show_list_images ? "medium" : "avatar"}
|
||||
dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
${backgroundImage === "none" && !child.can_play
|
||||
? html`<ha-svg-icon
|
||||
@ -1198,10 +1195,8 @@ export class HaMediaPlayerBrowse extends LitElement {
|
||||
|
||||
mwc-list-item .title {
|
||||
margin-left: 16px;
|
||||
}
|
||||
mwc-list-item[dir="rtl"] .title {
|
||||
margin-right: 16px;
|
||||
margin-left: 0;
|
||||
margin-inline-start: 16px;
|
||||
margin-inline-end: initial;
|
||||
}
|
||||
|
||||
/* ============= Narrow ============= */
|
||||
@ -1332,6 +1327,10 @@ export class HaMediaPlayerBrowse extends LitElement {
|
||||
lit-virtualizer.not_shown {
|
||||
height: calc(100% - 36px);
|
||||
}
|
||||
|
||||
ha-browse-media-tts {
|
||||
direction: var(--direction);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@ -8,30 +8,41 @@ import {
|
||||
EntityRegistryDisplayEntry,
|
||||
EntityRegistryEntry,
|
||||
} from "./entity_registry";
|
||||
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
||||
|
||||
const resources: Record<IconCategory, any> = {
|
||||
const resources: {
|
||||
entity: Record<string, Promise<PlatformIcons>>;
|
||||
entity_component: {
|
||||
domains?: string[];
|
||||
resources?: Promise<Record<string, ComponentIcons>>;
|
||||
};
|
||||
services: {
|
||||
all?: Promise<Record<string, ServiceIcons>>;
|
||||
domains: { [domain: string]: ServiceIcons | Promise<ServiceIcons> };
|
||||
};
|
||||
} = {
|
||||
entity: {},
|
||||
entity_component: undefined,
|
||||
services: {},
|
||||
entity_component: {},
|
||||
services: { domains: {} },
|
||||
};
|
||||
|
||||
interface IconResources {
|
||||
resources: Record<string, string | Record<string, string>>;
|
||||
interface IconResources<
|
||||
T extends ComponentIcons | PlatformIcons | ServiceIcons,
|
||||
> {
|
||||
resources: Record<string, T>;
|
||||
}
|
||||
|
||||
interface PlatformIcons {
|
||||
[domain: string]: {
|
||||
[translation_key: string]: {
|
||||
state: Record<string, string>;
|
||||
state_attributes: Record<
|
||||
string,
|
||||
{
|
||||
state: Record<string, string>;
|
||||
default: string;
|
||||
}
|
||||
>;
|
||||
default: string;
|
||||
};
|
||||
[translation_key: string]: {
|
||||
state: Record<string, string>;
|
||||
state_attributes: Record<
|
||||
string,
|
||||
{
|
||||
state: Record<string, string>;
|
||||
default: string;
|
||||
}
|
||||
>;
|
||||
default: string;
|
||||
};
|
||||
}
|
||||
|
||||
@ -55,12 +66,18 @@ interface ServiceIcons {
|
||||
|
||||
export type IconCategory = "entity" | "entity_component" | "services";
|
||||
|
||||
export const getHassIcons = async (
|
||||
type CategoryType = {
|
||||
entity: PlatformIcons;
|
||||
entity_component: ComponentIcons;
|
||||
services: ServiceIcons;
|
||||
};
|
||||
|
||||
export const getHassIcons = async <T extends IconCategory>(
|
||||
hass: HomeAssistant,
|
||||
category: IconCategory,
|
||||
category: T,
|
||||
integration?: string
|
||||
): Promise<IconResources> =>
|
||||
hass.callWS<{ resources: Record<string, string> }>({
|
||||
) =>
|
||||
hass.callWS<IconResources<CategoryType[T]>>({
|
||||
type: "frontend/get_icons",
|
||||
category,
|
||||
integration,
|
||||
@ -70,14 +87,17 @@ export const getPlatformIcons = async (
|
||||
hass: HomeAssistant,
|
||||
integration: string,
|
||||
force = false
|
||||
): Promise<PlatformIcons> => {
|
||||
): Promise<PlatformIcons | undefined> => {
|
||||
if (!force && integration in resources.entity) {
|
||||
return resources.entity[integration];
|
||||
}
|
||||
const result = getHassIcons(hass, "entity", integration);
|
||||
resources.entity[integration] = result.then(
|
||||
if (!isComponentLoaded(hass, integration)) {
|
||||
return undefined;
|
||||
}
|
||||
const result = getHassIcons(hass, "entity", integration).then(
|
||||
(res) => res?.resources[integration]
|
||||
);
|
||||
resources.entity[integration] = result;
|
||||
return resources.entity[integration];
|
||||
};
|
||||
|
||||
@ -85,45 +105,59 @@ export const getComponentIcons = async (
|
||||
hass: HomeAssistant,
|
||||
domain: string,
|
||||
force = false
|
||||
): Promise<ComponentIcons> => {
|
||||
if (!force && resources.entity_component) {
|
||||
return resources.entity_component.then((res) => res[domain]);
|
||||
): Promise<ComponentIcons | undefined> => {
|
||||
if (
|
||||
!force &&
|
||||
resources.entity_component.resources &&
|
||||
resources.entity_component.domains?.includes(domain)
|
||||
) {
|
||||
return resources.entity_component.resources.then((res) => res[domain]);
|
||||
}
|
||||
resources.entity_component = getHassIcons(hass, "entity_component").then(
|
||||
(result) => result.resources
|
||||
);
|
||||
return resources.entity_component.then((res) => res[domain]);
|
||||
if (!isComponentLoaded(hass, domain)) {
|
||||
return undefined;
|
||||
}
|
||||
resources.entity_component.domains = [...hass.config.components];
|
||||
resources.entity_component.resources = getHassIcons(
|
||||
hass,
|
||||
"entity_component"
|
||||
).then((result) => result.resources);
|
||||
return resources.entity_component.resources.then((res) => res[domain]);
|
||||
};
|
||||
|
||||
export const getServiceIcons = async (
|
||||
hass: HomeAssistant,
|
||||
domain?: string,
|
||||
force = false
|
||||
): Promise<ServiceIcons> => {
|
||||
): Promise<ServiceIcons | Record<string, ServiceIcons> | undefined> => {
|
||||
if (!domain) {
|
||||
if (!force && resources.services.all) {
|
||||
return resources.services.all;
|
||||
}
|
||||
resources.services.all = getHassIcons(hass, "services", domain).then(
|
||||
(res) => {
|
||||
resources.services = res.resources;
|
||||
resources.services.domains = res.resources;
|
||||
return res?.resources;
|
||||
}
|
||||
);
|
||||
return resources.services.all;
|
||||
}
|
||||
if (!force && domain && domain in resources.services) {
|
||||
return resources.services[domain];
|
||||
if (!force && domain in resources.services.domains) {
|
||||
return resources.services.domains[domain];
|
||||
}
|
||||
if (resources.services.all && !force) {
|
||||
await resources.services.all;
|
||||
if (domain in resources.services) {
|
||||
return resources.services[domain];
|
||||
if (domain in resources.services.domains) {
|
||||
return resources.services.domains[domain];
|
||||
}
|
||||
}
|
||||
if (!isComponentLoaded(hass, domain)) {
|
||||
return undefined;
|
||||
}
|
||||
const result = getHassIcons(hass, "services", domain);
|
||||
resources.services[domain] = result.then((res) => res?.resources[domain]);
|
||||
return resources.services[domain];
|
||||
resources.services.domains[domain] = result.then(
|
||||
(res) => res?.resources[domain]
|
||||
);
|
||||
return resources.services.domains[domain];
|
||||
};
|
||||
|
||||
export const entityIcon = async (
|
||||
@ -238,7 +272,7 @@ export const serviceIcon = async (
|
||||
const serviceName = computeObjectId(service);
|
||||
const serviceIcons = await getServiceIcons(hass, domain);
|
||||
if (serviceIcons) {
|
||||
icon = serviceIcons[serviceName];
|
||||
icon = serviceIcons[serviceName] as string;
|
||||
}
|
||||
if (!icon) {
|
||||
icon = await domainIcon(hass, domain);
|
||||
|
@ -2,7 +2,6 @@ import "@material/mwc-button/mwc-button";
|
||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { computeRTLDirection } from "../../common/util/compute_rtl";
|
||||
import "../../components/ha-dialog";
|
||||
import "../../components/ha-formfield";
|
||||
import "../../components/ha-switch";
|
||||
@ -82,7 +81,6 @@ class DialogConfigEntrySystemOptions extends LitElement {
|
||||
}
|
||||
)}
|
||||
</p>`}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${!this._disableNewEntities}
|
||||
@ -109,7 +107,6 @@ class DialogConfigEntrySystemOptions extends LitElement {
|
||||
}
|
||||
)}
|
||||
</p>`}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${!this._disablePolling}
|
||||
|
@ -14,7 +14,6 @@ import { customElement, property } from "lit/decorators";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
import { stateActive } from "../../../common/entity/state_active";
|
||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import "../../../components/ha-icon-button";
|
||||
import "../../../components/ha-select";
|
||||
import "../../../components/ha-slider";
|
||||
@ -131,7 +130,6 @@ class MoreInfoMediaPlayer extends LitElement {
|
||||
<ha-slider
|
||||
labeled
|
||||
id="input"
|
||||
.dir=${computeRTLDirection(this.hass!)}
|
||||
.value=${Number(stateObj.attributes.volume_level) * 100}
|
||||
@change=${this._selectedValueChanged}
|
||||
></ha-slider>
|
||||
|
@ -1,15 +1,6 @@
|
||||
import {
|
||||
css,
|
||||
CSSResultGroup,
|
||||
html,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit";
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, eventOptions, property } from "lit/decorators";
|
||||
import { restoreScroll } from "../common/decorators/restore-scroll";
|
||||
import { toggleAttribute } from "../common/dom/toggle_attribute";
|
||||
import { computeRTL } from "../common/util/compute_rtl";
|
||||
import "../components/ha-icon-button-arrow-prev";
|
||||
import "../components/ha-menu-button";
|
||||
import { HomeAssistant } from "../types";
|
||||
@ -34,17 +25,6 @@ class HassSubpage extends LitElement {
|
||||
// @ts-ignore
|
||||
@restoreScroll(".content") private _savedScrollPos?: number;
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
super.willUpdate(changedProps);
|
||||
if (!changedProps.has("hass")) {
|
||||
return;
|
||||
}
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.locale !== this.hass.locale) {
|
||||
toggleAttribute(this, "rtl", computeRTL(this.hass));
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div class="toolbar">
|
||||
@ -160,6 +140,9 @@ class HassSubpage extends LitElement {
|
||||
#fab {
|
||||
position: absolute;
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
inset-inline-end: calc(16px + env(safe-area-inset-right));
|
||||
inset-inline-start: initial;
|
||||
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
z-index: 1;
|
||||
}
|
||||
@ -169,15 +152,8 @@ class HassSubpage extends LitElement {
|
||||
#fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
:host([rtl]) #fab {
|
||||
right: auto;
|
||||
left: calc(16px + env(safe-area-inset-left));
|
||||
}
|
||||
:host([rtl][is-wide]) #fab {
|
||||
bottom: 24px;
|
||||
left: 24px;
|
||||
right: auto;
|
||||
inset-inline-end: 24px;
|
||||
inset-inline-start: initial;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@ -4,7 +4,6 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { LocalizeFunc } from "../common/translations/localize";
|
||||
import { computeRTLDirection } from "../common/util/compute_rtl";
|
||||
import "../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
@ -244,7 +243,6 @@ export class HaTabsSubpageDataTable extends LitElement {
|
||||
.selectable=${this.selectable}
|
||||
.hasFab=${this.hasFab}
|
||||
.id=${this.id}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.clickable=${this.clickable}
|
||||
.appendRow=${this.appendRow}
|
||||
>
|
||||
|
@ -13,7 +13,6 @@ import memoizeOne from "memoize-one";
|
||||
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
||||
import { restoreScroll } from "../common/decorators/restore-scroll";
|
||||
import { LocalizeFunc } from "../common/translations/localize";
|
||||
import { computeRTL } from "../common/util/compute_rtl";
|
||||
import "../components/ha-icon-button-arrow-prev";
|
||||
import "../components/ha-menu-button";
|
||||
import "../components/ha-svg-icon";
|
||||
@ -58,8 +57,6 @@ class HassTabsSubpage extends LitElement {
|
||||
@property({ type: Boolean, reflect: true, attribute: "is-wide" })
|
||||
public isWide = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public rtl = false;
|
||||
|
||||
@state() private _activeTab?: PageNavigation;
|
||||
|
||||
// @ts-ignore
|
||||
@ -123,14 +120,6 @@ class HassTabsSubpage extends LitElement {
|
||||
`${this.route.prefix}${this.route.path}`.includes(tab.path)
|
||||
);
|
||||
}
|
||||
if (changedProperties.has("hass")) {
|
||||
const oldHass = changedProperties.get("hass") as
|
||||
| HomeAssistant
|
||||
| undefined;
|
||||
if (!oldHass || oldHass.language !== this.hass.language) {
|
||||
this.rtl = computeRTL(this.hass);
|
||||
}
|
||||
}
|
||||
super.willUpdate(changedProperties);
|
||||
}
|
||||
|
||||
@ -334,6 +323,8 @@ class HassTabsSubpage extends LitElement {
|
||||
#fab {
|
||||
position: fixed;
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
inset-inline-end: calc(16px + env(safe-area-inset-right));
|
||||
inset-inline-start: initial;
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
z-index: 1;
|
||||
}
|
||||
@ -343,15 +334,8 @@ class HassTabsSubpage extends LitElement {
|
||||
#fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
:host([rtl]) #fab {
|
||||
right: auto;
|
||||
left: calc(16px + env(safe-area-inset-left));
|
||||
}
|
||||
:host([rtl][is-wide]) #fab {
|
||||
bottom: 24px;
|
||||
left: 24px;
|
||||
right: auto;
|
||||
inset-inline-end: 24px;
|
||||
inset-inline-start: initial;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@ -11,7 +11,6 @@ import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent, HASSDomEvent } from "../common/dom/fire_event";
|
||||
import { listenMediaQuery } from "../common/dom/media_query";
|
||||
import { toggleAttribute } from "../common/dom/toggle_attribute";
|
||||
import { computeRTLDirection } from "../common/util/compute_rtl";
|
||||
import "../components/ha-drawer";
|
||||
import { showNotificationDrawer } from "../dialogs/notifications/show-notification-drawer";
|
||||
import type { HomeAssistant, Route } from "../types";
|
||||
@ -62,7 +61,6 @@ export class HomeAssistantMain extends LitElement {
|
||||
<ha-drawer
|
||||
.type=${sidebarNarrow ? "modal" : ""}
|
||||
.open=${sidebarNarrow ? this._drawerOpen : undefined}
|
||||
.direction=${computeRTLDirection(this.hass)}
|
||||
@MDCDrawer:closed=${this._drawerClosed}
|
||||
>
|
||||
<ha-sidebar
|
||||
|
@ -28,7 +28,6 @@ import { useAmPm } from "../../common/datetime/use_am_pm";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { supportsFeature } from "../../common/entity/supports-feature";
|
||||
import { LocalizeFunc } from "../../common/translations/localize";
|
||||
import { computeRTLDirection } from "../../common/util/compute_rtl";
|
||||
import "../../components/ha-button-toggle-group";
|
||||
import "../../components/ha-fab";
|
||||
import "../../components/ha-icon-button-next";
|
||||
@ -169,7 +168,6 @@ export class HAFullCalendar extends LitElement {
|
||||
.buttons=${viewToggleButtons}
|
||||
.active=${this._activeView}
|
||||
@value-changed=${this._handleView}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
></ha-button-toggle-group>
|
||||
`
|
||||
: html`
|
||||
@ -203,7 +201,6 @@ export class HAFullCalendar extends LitElement {
|
||||
.buttons=${viewToggleButtons}
|
||||
.active=${this._activeView}
|
||||
@value-changed=${this._handleView}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
></ha-button-toggle-group>
|
||||
</div>
|
||||
`}
|
||||
@ -503,6 +500,8 @@ export class HAFullCalendar extends LitElement {
|
||||
position: absolute;
|
||||
bottom: 32px;
|
||||
right: 32px;
|
||||
inset-inline-end: 32px;
|
||||
inset-inline-start: initial;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,7 @@ export default class HaAutomationAction extends LitElement {
|
||||
@item-moved=${this._actionMoved}
|
||||
group="actions"
|
||||
.path=${this.path}
|
||||
invert-swap
|
||||
>
|
||||
<div class="actions">
|
||||
${repeat(
|
||||
@ -266,22 +267,32 @@ export default class HaAutomationAction extends LitElement {
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
.actions {
|
||||
padding: 16px;
|
||||
margin: -16px -16px 0px -16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.actions:not(:has(ha-automation-action-row)) {
|
||||
margin: -16px;
|
||||
}
|
||||
.sortable-ghost {
|
||||
background: none;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
}
|
||||
.sortable-drag {
|
||||
background: none;
|
||||
}
|
||||
ha-automation-action-row {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
scroll-margin-top: 48px;
|
||||
}
|
||||
ha-svg-icon {
|
||||
height: 20px;
|
||||
}
|
||||
ha-alert {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.handle {
|
||||
padding: 12px 4px;
|
||||
padding: 12px;
|
||||
cursor: move; /* fallback if grab cursor is unsupported */
|
||||
cursor: grab;
|
||||
}
|
||||
|
@ -125,6 +125,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
||||
.disabled=${!this._showReorder || this.disabled}
|
||||
group="choose-options"
|
||||
.path=${[...(this.path ?? []), "choose"]}
|
||||
invert-swap
|
||||
>
|
||||
<div class="options">
|
||||
${repeat(
|
||||
@ -296,7 +297,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
||||
)}:
|
||||
</h2>
|
||||
<ha-automation-action
|
||||
.path=${[...(this.path ?? []), "choose", "default"]}
|
||||
.path=${[...(this.path ?? []), "default"]}
|
||||
.actions=${ensureArray(action.default) || []}
|
||||
.disabled=${this.disabled}
|
||||
@value-changed=${this._defaultChanged}
|
||||
@ -502,8 +503,22 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.option {
|
||||
margin: 0 0 16px 0;
|
||||
.options {
|
||||
padding: 16px;
|
||||
margin: -16px -16px 0px -16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.options:not(:has(.option)) {
|
||||
margin: -16px;
|
||||
}
|
||||
.sortable-ghost {
|
||||
background: none;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
}
|
||||
.sortable-drag {
|
||||
background: none;
|
||||
}
|
||||
.add-card mwc-button {
|
||||
display: block;
|
||||
@ -539,7 +554,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
|
||||
padding: 0 16px 16px 16px;
|
||||
}
|
||||
.handle {
|
||||
padding: 12px 4px;
|
||||
padding: 12px;
|
||||
cursor: move; /* fallback if grab cursor is unsupported */
|
||||
cursor: grab;
|
||||
}
|
||||
|
@ -121,6 +121,7 @@ export default class HaAutomationCondition extends LitElement {
|
||||
@item-moved=${this._conditionMoved}
|
||||
group="conditions"
|
||||
.path=${this.path}
|
||||
invert-swap
|
||||
>
|
||||
<div class="conditions">
|
||||
${repeat(
|
||||
@ -291,22 +292,32 @@ export default class HaAutomationCondition extends LitElement {
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
.conditions {
|
||||
padding: 16px;
|
||||
margin: -16px -16px 0px -16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.conditions:not(:has(ha-automation-condition-row)) {
|
||||
margin: -16px;
|
||||
}
|
||||
.sortable-ghost {
|
||||
background: none;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
}
|
||||
.sortable-drag {
|
||||
background: none;
|
||||
}
|
||||
ha-automation-condition-row {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
scroll-margin-top: 48px;
|
||||
}
|
||||
ha-svg-icon {
|
||||
height: 20px;
|
||||
}
|
||||
ha-alert {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.handle {
|
||||
padding: 12px 4px;
|
||||
padding: 12px;
|
||||
cursor: move; /* fallback if grab cursor is unsupported */
|
||||
cursor: grab;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import "@material/mwc-button";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import {
|
||||
mdiCheck,
|
||||
mdiContentDuplicate,
|
||||
@ -35,6 +34,7 @@ import "../../../components/ha-fab";
|
||||
import "../../../components/ha-icon-button";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import "../../../components/ha-yaml-editor";
|
||||
import "../../../components/ha-list-item";
|
||||
import {
|
||||
AutomationConfig,
|
||||
AutomationEntity,
|
||||
@ -150,7 +150,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
|
||||
<mwc-list-item
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
.disabled=${!stateObj}
|
||||
@click=${this._showInfo}
|
||||
@ -160,20 +160,20 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
slot="graphic"
|
||||
.path=${mdiInformationOutline}
|
||||
></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
|
||||
<mwc-list-item
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
.disabled=${!stateObj}
|
||||
@click=${this._runActions}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.automation.editor.run")}
|
||||
<ha-svg-icon slot="graphic" .path=${mdiPlay}></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
|
||||
${stateObj && this._config && this.narrow
|
||||
? html`<a href="/config/automation/trace/${this._config.id}">
|
||||
<mwc-list-item graphic="icon">
|
||||
<ha-list-item graphic="icon">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.show_trace"
|
||||
)}
|
||||
@ -181,22 +181,22 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
slot="graphic"
|
||||
.path=${mdiTransitConnection}
|
||||
></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
</a>`
|
||||
: ""}
|
||||
|
||||
<mwc-list-item
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@click=${this._promptAutomationAlias}
|
||||
.disabled=${!this.automationId || this._mode === "yaml"}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.automation.editor.rename")}
|
||||
<ha-svg-icon slot="graphic" .path=${mdiRenameBox}></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
|
||||
${this._config && !("use_blueprint" in this._config)
|
||||
? html`
|
||||
<mwc-list-item
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@click=${this._promptAutomationMode}
|
||||
.disabled=${this._readOnly || this._mode === "yaml"}
|
||||
@ -208,11 +208,11 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
slot="graphic"
|
||||
.path=${mdiDebugStepOver}
|
||||
></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
`
|
||||
: ""}
|
||||
|
||||
<mwc-list-item
|
||||
<ha-list-item
|
||||
.disabled=${!this._readOnly && !this.automationId}
|
||||
graphic="icon"
|
||||
@click=${this._duplicate}
|
||||
@ -226,11 +226,11 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
slot="graphic"
|
||||
.path=${mdiContentDuplicate}
|
||||
></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
|
||||
<li divider role="separator"></li>
|
||||
|
||||
<mwc-list-item graphic="icon" @click=${this._switchUiMode}>
|
||||
<ha-list-item graphic="icon" @click=${this._switchUiMode}>
|
||||
${this.hass.localize("ui.panel.config.automation.editor.edit_ui")}
|
||||
${this._mode === "gui"
|
||||
? html`<ha-svg-icon
|
||||
@ -239,8 +239,8 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
.path=${mdiCheck}
|
||||
></ha-svg-icon>`
|
||||
: ``}
|
||||
</mwc-list-item>
|
||||
<mwc-list-item graphic="icon" @click=${this._switchYamlMode}>
|
||||
</ha-list-item>
|
||||
<ha-list-item graphic="icon" @click=${this._switchYamlMode}>
|
||||
${this.hass.localize("ui.panel.config.automation.editor.edit_yaml")}
|
||||
${this._mode === "yaml"
|
||||
? html`<ha-svg-icon
|
||||
@ -249,11 +249,11 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
.path=${mdiCheck}
|
||||
></ha-svg-icon>`
|
||||
: ``}
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
|
||||
<li divider role="separator"></li>
|
||||
|
||||
<mwc-list-item
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
.disabled=${!stateObj}
|
||||
@click=${this._toggle}
|
||||
@ -267,9 +267,9 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
? mdiPlayCircleOutline
|
||||
: mdiStopCircleOutline}
|
||||
></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
|
||||
<mwc-list-item
|
||||
<ha-list-item
|
||||
.disabled=${!this.automationId}
|
||||
class=${classMap({ warning: Boolean(this.automationId) })}
|
||||
graphic="icon"
|
||||
@ -282,7 +282,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
.path=${mdiDelete}
|
||||
>
|
||||
</ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
</ha-button-menu>
|
||||
|
||||
${this._config
|
||||
|
@ -78,6 +78,7 @@ export default class HaAutomationTrigger extends LitElement {
|
||||
@item-moved=${this._triggerMoved}
|
||||
group="triggers"
|
||||
.path=${this.path}
|
||||
invert-swap
|
||||
>
|
||||
<div class="triggers">
|
||||
${repeat(
|
||||
@ -240,22 +241,32 @@ export default class HaAutomationTrigger extends LitElement {
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
.triggers {
|
||||
padding: 16px;
|
||||
margin: -16px -16px 0px -16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.triggers:not(:has(ha-automation-trigger-row)) {
|
||||
margin: -16px;
|
||||
}
|
||||
.sortable-ghost {
|
||||
background: none;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
}
|
||||
.sortable-drag {
|
||||
background: none;
|
||||
}
|
||||
ha-automation-trigger-row {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
scroll-margin-top: 48px;
|
||||
}
|
||||
ha-svg-icon {
|
||||
height: 20px;
|
||||
}
|
||||
ha-alert {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
border-radius: var(--ha-card-border-radius, 16px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.handle {
|
||||
padding: 12px 4px;
|
||||
padding: 12px;
|
||||
cursor: move; /* fallback if grab cursor is unsupported */
|
||||
cursor: grab;
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import "@material/mwc-button";
|
||||
import { css, html, LitElement, PropertyValues } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { formatDateTime } from "../../../../common/datetime/format_date_time";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||
import { debounce } from "../../../../common/util/debounce";
|
||||
import "../../../../components/ha-alert";
|
||||
import "../../../../components/ha-card";
|
||||
@ -37,8 +36,6 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _subscription?: SubscriptionInfo;
|
||||
|
||||
@state() private _rtlDirection: "rtl" | "ltr" = "rtl";
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<hass-subpage
|
||||
@ -172,13 +169,11 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
|
||||
<cloud-remote-pref
|
||||
.hass=${this.hass}
|
||||
.cloudStatus=${this.cloudStatus}
|
||||
dir=${this._rtlDirection}
|
||||
></cloud-remote-pref>
|
||||
|
||||
<cloud-tts-pref
|
||||
.hass=${this.hass}
|
||||
.cloudStatus=${this.cloudStatus}
|
||||
dir=${this._rtlDirection}
|
||||
></cloud-tts-pref>
|
||||
|
||||
<ha-tip .hass=${this.hass}>
|
||||
@ -193,7 +188,6 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.cloudStatus=${this.cloudStatus}
|
||||
dir=${this._rtlDirection}
|
||||
></cloud-webhooks>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
@ -205,15 +199,6 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
|
||||
this._fetchSubscriptionInfo();
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
if (changedProps.has("hass")) {
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.locale !== this.hass.locale) {
|
||||
this._rtlDirection = computeRTLDirection(this.hass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override hassSubscribe() {
|
||||
const googleCheck = debounce(
|
||||
() => {
|
||||
@ -272,10 +257,6 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
|
||||
fireEvent(this, "ha-refresh-cloud-status");
|
||||
}
|
||||
|
||||
_computeRTLDirection(hass) {
|
||||
return computeRTLDirection(hass);
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
haStyle,
|
||||
|
@ -179,14 +179,12 @@ export class CloudRemotePref extends LitElement {
|
||||
.header-actions {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
inset-inline-end: 24px;
|
||||
inset-inline-start: initial;
|
||||
top: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
:host([dir="rtl"]) .header-actions {
|
||||
right: auto;
|
||||
left: 24px;
|
||||
}
|
||||
.header-actions .icon-link {
|
||||
margin-top: -16px;
|
||||
margin-right: 8px;
|
||||
|
@ -177,12 +177,10 @@ export class CloudTTSPref extends LitElement {
|
||||
.example {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
inset-inline-end: 16px;
|
||||
inset-inline-start: initial;
|
||||
top: 16px;
|
||||
}
|
||||
:host([dir="rtl"]) .example {
|
||||
right: auto;
|
||||
left: 24px;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
} from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { computeStateName } from "../../../../../../common/entity/compute_state_name";
|
||||
import { computeRTLDirection } from "../../../../../../common/util/compute_rtl";
|
||||
import "../../../../../../components/ha-dialog";
|
||||
import "../../../../../../components/ha-formfield";
|
||||
import "../../../../../../components/ha-switch";
|
||||
@ -51,8 +50,6 @@ class DialogMQTTDeviceDebugInfo extends LitElement {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const dir = computeRTLDirection(this.hass!);
|
||||
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
@ -72,7 +69,6 @@ class DialogMQTTDeviceDebugInfo extends LitElement {
|
||||
.label=${this.hass!.localize(
|
||||
"ui.dialogs.mqtt_device_debug_info.deserialize"
|
||||
)}
|
||||
.dir=${dir}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${this._showDeserialized}
|
||||
@ -87,7 +83,6 @@ class DialogMQTTDeviceDebugInfo extends LitElement {
|
||||
.label=${this.hass!.localize(
|
||||
"ui.dialogs.mqtt_device_debug_info.show_as_yaml"
|
||||
)}
|
||||
.dir=${dir}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${this._showAsYaml}
|
||||
|
@ -20,7 +20,6 @@ import {
|
||||
} from "../../../common/integrations/protocolIntegrationPicked";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { LocalizeFunc } from "../../../common/translations/localize";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import {
|
||||
DataTableColumnContainer,
|
||||
RowClickedEvent,
|
||||
@ -488,7 +487,6 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
.label=${this.hass.localize("ui.panel.config.devices.add_device")}
|
||||
extended
|
||||
@click=${this._addDevice}
|
||||
?rtl=${computeRTL(this.hass)}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
|
@ -35,7 +35,6 @@ import {
|
||||
} from "../../../common/integrations/protocolIntegrationPicked";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { LocalizeFunc } from "../../../common/translations/localize";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
RowClickedEvent,
|
||||
@ -680,7 +679,6 @@ export class HaConfigEntities extends LitElement {
|
||||
extended
|
||||
@click=${this._addDevice}
|
||||
slot="fab"
|
||||
?rtl=${computeRTL(this.hass)}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>`
|
||||
|
@ -1,5 +1,5 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import { mdiClose } from "@mdi/js";
|
||||
import { mdiDelete } from "@mdi/js";
|
||||
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||
@ -70,7 +70,7 @@ class DialogMatterManageFabrics extends LitElement {
|
||||
@click=${this._removeFabric}
|
||||
slot="meta"
|
||||
.fabric=${fabric}
|
||||
.path=${mdiClose}
|
||||
.path=${mdiDelete}
|
||||
></ha-icon-button>
|
||||
</ha-list-item>`
|
||||
)}
|
||||
|
@ -48,6 +48,11 @@ class DialogMatterOpenCommissioningWindow extends LitElement {
|
||||
>
|
||||
${this._commissionParams
|
||||
? html`
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.matter.open_commissioning_window.success"
|
||||
)}
|
||||
</p>
|
||||
<div class="flex-container">
|
||||
<ha-svg-icon
|
||||
.path=${mdiCheckCircle}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { computeRTLDirection } from "../../../../../common/util/compute_rtl";
|
||||
import "../../../../../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
@ -82,7 +81,6 @@ export class ZHAClustersDataTable extends LitElement {
|
||||
.id=${"cluster_id"}
|
||||
selectable
|
||||
auto-height
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.searchLabel=${this.hass.localize("ui.components.data-table.search")}
|
||||
.noDataText=${this.hass.localize("ui.components.data-table.no-data")}
|
||||
></ha-data-table>
|
||||
|
@ -19,7 +19,6 @@ import {
|
||||
ConfigEntry,
|
||||
getConfigEntries,
|
||||
} from "../../../../../data/config_entries";
|
||||
import { computeRTL } from "../../../../../common/util/compute_rtl";
|
||||
import "../../../../../components/ha-card";
|
||||
import "../../../../../components/ha-fab";
|
||||
import "../../../../../components/ha-icon-button";
|
||||
@ -259,7 +258,6 @@ class ZHAConfigDashboard extends LitElement {
|
||||
<ha-fab
|
||||
.label=${this.hass.localize("ui.panel.config.zha.add_device")}
|
||||
extended
|
||||
?rtl=${computeRTL(this.hass)}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { computeRTLDirection } from "../../../../../common/util/compute_rtl";
|
||||
import "../../../../../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
@ -142,7 +141,6 @@ export class ZHADeviceEndpointDataTable extends LitElement {
|
||||
.data=${this._deviceEndpoints(this.deviceEndpoints)}
|
||||
.selectable=${this.selectable}
|
||||
auto-height
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.searchLabel=${this.hass.localize("ui.components.data-table.search")}
|
||||
.noDataText=${this.hass.localize("ui.components.data-table.no-data")}
|
||||
></ha-data-table>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { html, LitElement, PropertyValues, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { computeRTLDirection } from "../../../../../common/util/compute_rtl";
|
||||
import "../../../../../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
@ -128,7 +127,6 @@ class ZHADeviceNeighbors extends LitElement {
|
||||
.columns=${this._columns(this.narrow)}
|
||||
.data=${this._deviceNeighbors(this.device, this._devices)}
|
||||
auto-height
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.searchLabel=${this.hass.localize(
|
||||
"ui.components.data-table.search"
|
||||
)}
|
||||
|
@ -18,7 +18,6 @@ import {
|
||||
} from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { computeRTL } from "../../../../../common/util/compute_rtl";
|
||||
import "../../../../../components/ha-card";
|
||||
import "../../../../../components/ha-expansion-panel";
|
||||
import "../../../../../components/ha-fab";
|
||||
@ -472,7 +471,6 @@ class ZWaveJSConfigDashboard extends SubscribeMixin(LitElement) {
|
||||
"ui.panel.config.zwave_js.common.add_node"
|
||||
)}
|
||||
extended
|
||||
?rtl=${computeRTL(this.hass)}
|
||||
@click=${this._addNodeClicked}
|
||||
.disabled=${this._status !== "connected" ||
|
||||
(this._network?.controller.inclusion_state !== InclusionState.Idle &&
|
||||
|
@ -26,7 +26,6 @@ import { relativeTime } from "../../../common/datetime/relative_time";
|
||||
import { HASSDomEvent, fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import {
|
||||
DataTableColumnContainer,
|
||||
RowClickedEvent,
|
||||
@ -308,7 +307,6 @@ class HaScriptPicker extends LitElement {
|
||||
"ui.panel.config.script.picker.add_script"
|
||||
)}
|
||||
extended
|
||||
?rtl=${computeRTL(this.hass)}
|
||||
@click=${this._createNew}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
nothing,
|
||||
} from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import "../../../components/ha-circular-progress";
|
||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||
import "../../../components/ha-formfield";
|
||||
@ -161,7 +160,6 @@ export class DialogAddUser extends LitElement {
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.users.editor.local_only"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${this._localOnly}
|
||||
@ -173,7 +171,6 @@ export class DialogAddUser extends LitElement {
|
||||
<div class="row">
|
||||
<ha-formfield
|
||||
.label=${this.hass.localize("ui.panel.config.users.editor.admin")}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${this._isAdmin}
|
||||
|
@ -3,7 +3,6 @@ import "@material/mwc-button";
|
||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||
import "../../../components/ha-formfield";
|
||||
import "../../../components/ha-help-tooltip";
|
||||
@ -99,7 +98,6 @@ class DialogUserDetail extends LitElement {
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.users.editor.local_only"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.disabled=${user.system_generated}
|
||||
@ -114,7 +112,6 @@ class DialogUserDetail extends LitElement {
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.users.editor.admin"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.disabled=${user.system_generated || user.is_owner}
|
||||
@ -137,7 +134,6 @@ class DialogUserDetail extends LitElement {
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.users.editor.active"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.disabled=${user.system_generated || user.is_owner}
|
||||
|
@ -225,14 +225,12 @@ export class AssistPref extends LitElement {
|
||||
.header-actions {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
inset-inline-end: 0px;
|
||||
inset-inline-start: initial;
|
||||
top: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
:host([dir="rtl"]) .header-actions {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
.header-actions .icon-link {
|
||||
margin-top: -16px;
|
||||
margin-right: 8px;
|
||||
|
@ -258,14 +258,12 @@ export class CloudAlexaPref extends LitElement {
|
||||
.header-actions {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
inset-inline-end: 24px;
|
||||
inset-inline-start: initial;
|
||||
top: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
:host([dir="rtl"]) .header-actions {
|
||||
right: auto;
|
||||
left: 24px;
|
||||
}
|
||||
.header-actions .icon-link {
|
||||
margin-top: -16px;
|
||||
margin-right: 8px;
|
||||
|
@ -327,14 +327,12 @@ export class CloudGooglePref extends LitElement {
|
||||
.header-actions {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
inset-inline-end: 24px;
|
||||
inset-inline-start: initial;
|
||||
top: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
:host([dir="rtl"]) .header-actions {
|
||||
right: auto;
|
||||
left: 24px;
|
||||
}
|
||||
.header-actions .icon-link {
|
||||
margin-top: -16px;
|
||||
margin-right: 8px;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import { CloudStatus } from "../../../data/cloud";
|
||||
import { ExposeEntitySettings } from "../../../data/expose";
|
||||
|
||||
@ -48,7 +47,6 @@ export class HaConfigVoiceAssistantsAssistants extends LitElement {
|
||||
${isComponentLoaded(this.hass, "assist_pipeline")
|
||||
? html`
|
||||
<assist-pref
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.hass=${this.hass}
|
||||
.cloudStatus=${this.cloudStatus}
|
||||
.exposedEntities=${this.exposedEntities}
|
||||
@ -61,13 +59,11 @@ export class HaConfigVoiceAssistantsAssistants extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.exposedEntities=${this.exposedEntities}
|
||||
.cloudStatus=${this.cloudStatus}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
></cloud-alexa-pref>
|
||||
<cloud-google-pref
|
||||
.hass=${this.hass}
|
||||
.exposedEntities=${this.exposedEntities}
|
||||
.cloudStatus=${this.cloudStatus}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
></cloud-google-pref>
|
||||
`
|
||||
: html`<cloud-discover .hass=${this.hass}></cloud-discover>`}
|
||||
|
@ -27,7 +27,6 @@ import {
|
||||
isEmptyFilter,
|
||||
} from "../../../common/entity/entity_filter";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import {
|
||||
DataTableColumnContainer,
|
||||
DataTableRowData,
|
||||
@ -618,7 +617,6 @@ export class VoiceAssistantsExpose extends LitElement {
|
||||
"ui.panel.config.voice_assistants.expose.add"
|
||||
)}
|
||||
extended
|
||||
?rtl=${computeRTL(this.hass)}
|
||||
@click=${this._addEntry}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
|
@ -588,13 +588,10 @@ class HaPanelDevService extends LitElement {
|
||||
}
|
||||
|
||||
.attributes th {
|
||||
text-align: left;
|
||||
text-align: var(--float-start);
|
||||
background-color: var(--card-background-color);
|
||||
border-bottom: 1px solid var(--primary-text-color);
|
||||
}
|
||||
|
||||
:host([rtl]) .attributes th {
|
||||
text-align: right;
|
||||
direction: var(--direction);
|
||||
}
|
||||
|
||||
.attributes tr {
|
||||
|
@ -16,9 +16,7 @@ import memoizeOne from "memoize-one";
|
||||
import { formatDateTimeWithSeconds } from "../../../common/datetime/format_date_time";
|
||||
import { storage } from "../../../common/decorators/storage";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { toggleAttribute } from "../../../common/dom/toggle_attribute";
|
||||
import { escapeRegExp } from "../../../common/string/escape_regexp";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import { copyToClipboard } from "../../../common/util/copy-clipboard";
|
||||
import "../../../components/entity/ha-entity-picker";
|
||||
import "../../../components/ha-alert";
|
||||
@ -69,8 +67,6 @@ class HaPanelDevState extends LitElement {
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public narrow = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public rtl = false;
|
||||
|
||||
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
|
||||
|
||||
private _filteredEntities = memoizeOne(
|
||||
@ -325,14 +321,6 @@ class HaPanelDevState extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
protected updated(changedProps) {
|
||||
super.updated(changedProps);
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.locale !== this.hass.locale) {
|
||||
toggleAttribute(this, "rtl", computeRTL(this.hass));
|
||||
}
|
||||
}
|
||||
|
||||
private _copyEntity(ev) {
|
||||
ev.preventDefault();
|
||||
const entity = (ev.currentTarget! as any).entity;
|
||||
@ -626,7 +614,8 @@ class HaPanelDevState extends LitElement {
|
||||
|
||||
.entities th {
|
||||
padding: 0 8px;
|
||||
text-align: left;
|
||||
text-align: var(--float-start);
|
||||
direction: var(--direction);
|
||||
}
|
||||
|
||||
.filters th {
|
||||
@ -652,15 +641,6 @@ class HaPanelDevState extends LitElement {
|
||||
bottom: -8px;
|
||||
}
|
||||
|
||||
:host([rtl]) .entities th {
|
||||
text-align: right;
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
:host([rtl]) .filters {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.entities tr {
|
||||
vertical-align: top;
|
||||
direction: ltr;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import { mdiSlopeUphill } from "@mdi/js";
|
||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import { css, CSSResultGroup, html, LitElement } from "lit";
|
||||
import { CSSResultGroup, html, LitElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
@ -26,7 +26,6 @@ import { haStyle } from "../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { showStatisticsAdjustSumDialog } from "./show-dialog-statistics-adjust-sum";
|
||||
import { showFixStatisticsUnitsChangedDialog } from "./show-dialog-statistics-fix-units-changed";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import { documentationUrl } from "../../../util/documentation-url";
|
||||
|
||||
const FIX_ISSUES_ORDER = {
|
||||
@ -183,7 +182,6 @@ class HaPanelDevStatistics extends SubscribeMixin(LitElement) {
|
||||
id="statistic_id"
|
||||
clickable
|
||||
@row-click=${this._rowClicked}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
></ha-data-table>
|
||||
`;
|
||||
}
|
||||
@ -411,45 +409,7 @@ class HaPanelDevStatistics extends SubscribeMixin(LitElement) {
|
||||
};
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.content {
|
||||
padding: 16px;
|
||||
padding: max(16px, env(safe-area-inset-top))
|
||||
max(16px, env(safe-area-inset-right))
|
||||
max(16px, env(safe-area-inset-bottom))
|
||||
max(16px, env(safe-area-inset-left));
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 0 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
:host([rtl]) th {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
tr {
|
||||
vertical-align: top;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
tr:nth-child(odd) {
|
||||
background-color: var(--table-row-background-color, #fff);
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: var(--table-row-alternative-background-color, #eee);
|
||||
}
|
||||
td {
|
||||
padding: 4px;
|
||||
min-width: 200px;
|
||||
word-break: break-word;
|
||||
}
|
||||
`,
|
||||
];
|
||||
return haStyle;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import formatISO9075 from "date-fns/formatISO9075";
|
||||
import {
|
||||
css,
|
||||
@ -21,6 +20,7 @@ import "../../../components/ha-selector/ha-selector-datetime";
|
||||
import "../../../components/ha-selector/ha-selector-number";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import "../../../components/ha-icon-next";
|
||||
import "../../../components/ha-list-item";
|
||||
import {
|
||||
adjustStatisticsSum,
|
||||
fetchStatistics,
|
||||
@ -151,7 +151,7 @@ export class DialogStatisticsFixUnsupportedUnitMetadata extends LitElement {
|
||||
const stat = data[i];
|
||||
const growth = Math.round(stat.change! * 100) / 100;
|
||||
rows.push(html`
|
||||
<mwc-list-item
|
||||
<ha-list-item
|
||||
twoline
|
||||
hasMeta
|
||||
.stat=${stat}
|
||||
@ -166,7 +166,7 @@ export class DialogStatisticsFixUnsupportedUnitMetadata extends LitElement {
|
||||
)}
|
||||
</span>
|
||||
<ha-icon-next slot="meta"></ha-icon-next>
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
`);
|
||||
}
|
||||
stats = html`${rows}`;
|
||||
@ -413,7 +413,7 @@ export class DialogStatisticsFixUnsupportedUnitMetadata extends LitElement {
|
||||
ha-selector-number {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
mwc-list-item {
|
||||
ha-list-item {
|
||||
margin: 0 -24px;
|
||||
--mdc-list-side-padding: 24px;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { mdiDownload, mdiFilterRemove, mdiRefresh } from "@mdi/js";
|
||||
import { mdiDownload, mdiFilterRemove } from "@mdi/js";
|
||||
import { differenceInHours } from "date-fns/esm";
|
||||
import {
|
||||
HassServiceTarget,
|
||||
@ -6,6 +6,7 @@ import {
|
||||
} from "home-assistant-js-websocket/dist/types";
|
||||
import { LitElement, PropertyValues, css, html } from "lit";
|
||||
import { property, query, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { ensureArray } from "../../common/array/ensure-array";
|
||||
import { storage } from "../../common/decorators/storage";
|
||||
import { navigate } from "../../common/navigate";
|
||||
@ -15,7 +16,6 @@ import {
|
||||
extractSearchParamsObject,
|
||||
removeSearchParam,
|
||||
} from "../../common/url/search-params";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import { MIN_TIME_BETWEEN_UPDATES } from "../../components/chart/ha-chart-base";
|
||||
import "../../components/chart/state-history-charts";
|
||||
import type { StateHistoryCharts } from "../../components/chart/state-history-charts";
|
||||
@ -45,8 +45,8 @@ import {
|
||||
HistoryStates,
|
||||
EntityHistoryState,
|
||||
LineChartUnit,
|
||||
LineChartEntity,
|
||||
computeGroupKey,
|
||||
LineChartState,
|
||||
} from "../../data/history";
|
||||
import { fetchStatistics, Statistics } from "../../data/recorder";
|
||||
import { getSensorNumericDeviceClasses } from "../../data/sensor";
|
||||
@ -54,6 +54,7 @@ import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
||||
import { haStyle } from "../../resources/styles";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { fileDownload } from "../../util/file_download";
|
||||
import { showAlertDialog } from "../../dialogs/generic/show-dialog-box";
|
||||
|
||||
class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
@property({ attribute: false }) hass!: HomeAssistant;
|
||||
@ -71,7 +72,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
state: true,
|
||||
subscribe: false,
|
||||
})
|
||||
private _targetPickerValue?: HassServiceTarget;
|
||||
private _targetPickerValue: HassServiceTarget = {};
|
||||
|
||||
@state() private _isLoading = false;
|
||||
|
||||
@ -138,6 +139,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const entitiesSelected = this._getEntityIds().length > 0;
|
||||
return html`
|
||||
<ha-top-app-bar-fixed>
|
||||
${this._showBack
|
||||
@ -155,7 +157,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
></ha-menu-button>
|
||||
`}
|
||||
<div slot="title">${this.hass.localize("panel.history")}</div>
|
||||
${this._targetPickerValue
|
||||
${entitiesSelected
|
||||
? html`
|
||||
<ha-icon-button
|
||||
slot="actionItems"
|
||||
@ -166,17 +168,10 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
></ha-icon-button>
|
||||
`
|
||||
: ""}
|
||||
<ha-icon-button
|
||||
slot="actionItems"
|
||||
@click=${this._getHistory}
|
||||
.disabled=${this._isLoading || !this._targetPickerValue}
|
||||
.path=${mdiRefresh}
|
||||
.label=${this.hass.localize("ui.common.refresh")}
|
||||
></ha-icon-button>
|
||||
<ha-icon-button
|
||||
slot="actionItems"
|
||||
@click=${this._downloadHistory}
|
||||
.disabled=${this._isLoading || !this._targetPickerValue}
|
||||
.disabled=${this._isLoading}
|
||||
.path=${mdiDownload}
|
||||
.label=${this.hass.localize("ui.panel.history.download_data")}
|
||||
></ha-icon-button>
|
||||
@ -203,7 +198,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
? html`<div class="progress-wrapper">
|
||||
<ha-circular-progress indeterminate></ha-circular-progress>
|
||||
</div>`
|
||||
: !this._targetPickerValue
|
||||
: !entitiesSelected
|
||||
? html`<div class="start-search">
|
||||
${this.hass.localize("ui.panel.history.start_search")}
|
||||
</div>`
|
||||
@ -227,50 +222,83 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
): HistoryResult {
|
||||
const result: HistoryResult = { ...historyResult, line: [] };
|
||||
|
||||
const keys = new Set(
|
||||
historyResult.line
|
||||
.map((i) => computeGroupKey(i.unit, i.device_class, true))
|
||||
.concat(
|
||||
ltsResult.line.map((i) =>
|
||||
computeGroupKey(i.unit, i.device_class, true)
|
||||
)
|
||||
)
|
||||
);
|
||||
keys.forEach((key) => {
|
||||
const historyItem = historyResult.line.find(
|
||||
(i) => computeGroupKey(i.unit, i.device_class, true) === key
|
||||
);
|
||||
const ltsItem = ltsResult.line.find(
|
||||
(i) => computeGroupKey(i.unit, i.device_class, true) === key
|
||||
);
|
||||
if (historyItem && ltsItem) {
|
||||
const newLineItem: LineChartUnit = { ...historyItem, data: [] };
|
||||
const entities = new Set(
|
||||
historyItem.data
|
||||
.map((d) => d.entity_id)
|
||||
.concat(ltsItem.data.map((d) => d.entity_id))
|
||||
);
|
||||
entities.forEach((entity) => {
|
||||
const historyDataItem = historyItem.data.find(
|
||||
(d) => d.entity_id === entity
|
||||
);
|
||||
const ltsDataItem = ltsItem.data.find((d) => d.entity_id === entity);
|
||||
if (historyDataItem && ltsDataItem) {
|
||||
const newDataItem: LineChartEntity = {
|
||||
...historyDataItem,
|
||||
statistics: ltsDataItem.statistics,
|
||||
};
|
||||
newLineItem.data.push(newDataItem);
|
||||
} else {
|
||||
newLineItem.data.push(historyDataItem || ltsDataItem!);
|
||||
}
|
||||
});
|
||||
result.line.push(newLineItem);
|
||||
const lookup: Record<
|
||||
string,
|
||||
{ historyItem?: LineChartUnit; ltsItem?: LineChartUnit }
|
||||
> = {};
|
||||
|
||||
for (const item of historyResult.line) {
|
||||
const key = computeGroupKey(item.unit, item.device_class, true);
|
||||
if (key) {
|
||||
lookup[key] = {
|
||||
historyItem: item,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of ltsResult.line) {
|
||||
const key = computeGroupKey(item.unit, item.device_class, true);
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
if (key in lookup) {
|
||||
lookup[key].ltsItem = item;
|
||||
} else {
|
||||
lookup[key] = { ltsItem: item };
|
||||
}
|
||||
}
|
||||
|
||||
for (const { historyItem, ltsItem } of Object.values(lookup)) {
|
||||
if (!historyItem || !ltsItem) {
|
||||
// Only one result has data for this item, so just push it directly instead of merging.
|
||||
result.line.push(historyItem || ltsItem!);
|
||||
continue;
|
||||
}
|
||||
});
|
||||
|
||||
const newLineItem: LineChartUnit = { ...historyItem, data: [] };
|
||||
const entities = new Set([
|
||||
...historyItem.data.map((d) => d.entity_id),
|
||||
...ltsItem.data.map((d) => d.entity_id),
|
||||
]);
|
||||
|
||||
for (const entity of entities) {
|
||||
const historyDataItem = historyItem.data.find(
|
||||
(d) => d.entity_id === entity
|
||||
);
|
||||
const ltsDataItem = ltsItem.data.find((d) => d.entity_id === entity);
|
||||
|
||||
if (!historyDataItem || !ltsDataItem) {
|
||||
newLineItem.data.push(historyDataItem || ltsDataItem!);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove statistics that overlap with states
|
||||
const oldestState =
|
||||
historyDataItem.states[0]?.last_changed ||
|
||||
// If no state, fall back to the max last changed of the last statistics (so approve all)
|
||||
ltsDataItem.statistics![ltsDataItem.statistics!.length - 1]
|
||||
.last_changed + 1;
|
||||
|
||||
const statistics: LineChartState[] = [];
|
||||
for (const s of ltsDataItem.statistics!) {
|
||||
if (s.last_changed >= oldestState) {
|
||||
break;
|
||||
}
|
||||
statistics.push(s);
|
||||
}
|
||||
|
||||
newLineItem.data.push(
|
||||
statistics.length === 0
|
||||
? // All statistics overlapped with states, so just push the states
|
||||
historyDataItem
|
||||
: {
|
||||
...historyDataItem,
|
||||
statistics,
|
||||
}
|
||||
);
|
||||
}
|
||||
result.line.push(newLineItem);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -342,114 +370,90 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
if (
|
||||
this._targetPickerValue &&
|
||||
(changedProps.has("_startDate") ||
|
||||
changedProps.has("_endDate") ||
|
||||
changedProps.has("_targetPickerValue") ||
|
||||
(!this._stateHistory &&
|
||||
(changedProps.has("_deviceEntityLookup") ||
|
||||
changedProps.has("_areaEntityLookup") ||
|
||||
changedProps.has("_areaDeviceLookup"))))
|
||||
changedProps.has("_startDate") ||
|
||||
changedProps.has("_endDate") ||
|
||||
changedProps.has("_targetPickerValue") ||
|
||||
(!this._stateHistory &&
|
||||
(changedProps.has("_deviceEntityLookup") ||
|
||||
changedProps.has("_areaEntityLookup") ||
|
||||
changedProps.has("_areaDeviceLookup")))
|
||||
) {
|
||||
this._getHistory();
|
||||
this._getStats();
|
||||
}
|
||||
|
||||
if (!changedProps.has("hass") && !changedProps.has("_entities")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.language !== this.hass.language) {
|
||||
this.rtl = computeRTL(this.hass);
|
||||
}
|
||||
}
|
||||
|
||||
private _removeAll() {
|
||||
this._targetPickerValue = undefined;
|
||||
this._targetPickerValue = {};
|
||||
this._updatePath();
|
||||
}
|
||||
|
||||
private async _getStats() {
|
||||
const entityIds = this._getEntityIds();
|
||||
if (!entityIds) {
|
||||
const statisticIds = this._getEntityIds();
|
||||
|
||||
if (statisticIds.length === 0) {
|
||||
this._statisticsHistory = undefined;
|
||||
return;
|
||||
}
|
||||
this._getStatistics(entityIds);
|
||||
}
|
||||
|
||||
private async _getStatistics(statisticIds: string[]): Promise<void> {
|
||||
try {
|
||||
const statistics = await fetchStatistics(
|
||||
this.hass!,
|
||||
this._startDate,
|
||||
this._endDate,
|
||||
statisticIds,
|
||||
"hour",
|
||||
undefined,
|
||||
["mean", "state"]
|
||||
);
|
||||
const statistics = await fetchStatistics(
|
||||
this.hass!,
|
||||
this._startDate,
|
||||
this._endDate,
|
||||
statisticIds,
|
||||
"hour",
|
||||
undefined,
|
||||
["mean", "state"]
|
||||
);
|
||||
|
||||
// Maintain the statistic id ordering
|
||||
const orderedStatistics: Statistics = {};
|
||||
statisticIds.forEach((id) => {
|
||||
if (id in statistics) {
|
||||
orderedStatistics[id] = statistics[id];
|
||||
}
|
||||
// Maintain the statistic id ordering
|
||||
const orderedStatistics: Statistics = {};
|
||||
statisticIds.forEach((id) => {
|
||||
if (id in statistics) {
|
||||
orderedStatistics[id] = statistics[id];
|
||||
}
|
||||
});
|
||||
|
||||
// Convert statistics to HistoryResult format
|
||||
const statsHistoryStates: HistoryStates = {};
|
||||
Object.entries(orderedStatistics).forEach(([key, value]) => {
|
||||
const entityHistoryStates: EntityHistoryState[] = value.map((e) => ({
|
||||
s: e.mean != null ? e.mean.toString() : e.state!.toString(),
|
||||
lc: e.start / 1000,
|
||||
a: {},
|
||||
lu: e.start / 1000,
|
||||
}));
|
||||
statsHistoryStates[key] = entityHistoryStates;
|
||||
});
|
||||
|
||||
const { numeric_device_classes: sensorNumericDeviceClasses } =
|
||||
await getSensorNumericDeviceClasses(this.hass);
|
||||
|
||||
this._statisticsHistory = computeHistory(
|
||||
this.hass,
|
||||
statsHistoryStates,
|
||||
this.hass.localize,
|
||||
sensorNumericDeviceClasses,
|
||||
true
|
||||
);
|
||||
// remap states array to statistics array
|
||||
(this._statisticsHistory?.line || []).forEach((item) => {
|
||||
item.data.forEach((data) => {
|
||||
data.statistics = data.states;
|
||||
data.states = [];
|
||||
});
|
||||
|
||||
// Convert statistics to HistoryResult format
|
||||
const statsHistoryStates: HistoryStates = {};
|
||||
Object.entries(orderedStatistics).forEach(([key, value]) => {
|
||||
const entityHistoryStates: EntityHistoryState[] = value.map((e) => ({
|
||||
s: e.mean != null ? e.mean.toString() : e.state!.toString(),
|
||||
lc: e.start / 1000,
|
||||
a: {},
|
||||
lu: e.start / 1000,
|
||||
}));
|
||||
statsHistoryStates[key] = entityHistoryStates;
|
||||
});
|
||||
|
||||
const { numeric_device_classes: sensorNumericDeviceClasses } =
|
||||
await getSensorNumericDeviceClasses(this.hass);
|
||||
|
||||
this._statisticsHistory = computeHistory(
|
||||
this.hass,
|
||||
statsHistoryStates,
|
||||
this.hass.localize,
|
||||
sensorNumericDeviceClasses,
|
||||
true
|
||||
);
|
||||
// remap states array to statistics array
|
||||
(this._statisticsHistory?.line || []).forEach((item) => {
|
||||
item.data.forEach((data) => {
|
||||
data.statistics = data.states;
|
||||
data.states = [];
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
this._statisticsHistory = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async _getHistory() {
|
||||
if (!this._targetPickerValue) {
|
||||
return;
|
||||
}
|
||||
this._isLoading = true;
|
||||
const entityIds = this._getEntityIds();
|
||||
|
||||
if (entityIds === undefined) {
|
||||
this._isLoading = false;
|
||||
if (entityIds.length === 0) {
|
||||
this._stateHistory = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
if (entityIds.length === 0) {
|
||||
this._isLoading = false;
|
||||
this._stateHistory = { line: [], timeline: [] };
|
||||
return;
|
||||
}
|
||||
this._isLoading = true;
|
||||
|
||||
if (this._subscribed) {
|
||||
this._unsubscribeHistory();
|
||||
@ -512,84 +516,100 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
}
|
||||
|
||||
private _getEntityIds(): string[] | undefined {
|
||||
if (
|
||||
!this._targetPickerValue ||
|
||||
this._deviceEntityLookup === undefined ||
|
||||
this._areaEntityLookup === undefined ||
|
||||
this._areaDeviceLookup === undefined
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
private _getEntityIds(): string[] {
|
||||
return this.__getEntityIds(
|
||||
this._targetPickerValue,
|
||||
this._deviceEntityLookup,
|
||||
this._areaEntityLookup,
|
||||
this._areaDeviceLookup
|
||||
);
|
||||
}
|
||||
|
||||
const entityIds = new Set<string>();
|
||||
let {
|
||||
area_id: searchingAreaId,
|
||||
device_id: searchingDeviceId,
|
||||
entity_id: searchingEntityId,
|
||||
} = this._targetPickerValue;
|
||||
private __getEntityIds = memoizeOne(
|
||||
(
|
||||
targetPickerValue: HassServiceTarget,
|
||||
deviceEntityLookup: DeviceEntityLookup | undefined,
|
||||
areaEntityLookup: AreaEntityLookup | undefined,
|
||||
areaDeviceLookup: AreaDeviceLookup | undefined
|
||||
): string[] => {
|
||||
if (
|
||||
!targetPickerValue ||
|
||||
deviceEntityLookup === undefined ||
|
||||
areaEntityLookup === undefined ||
|
||||
areaDeviceLookup === undefined
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const entityIds = new Set<string>();
|
||||
let {
|
||||
area_id: searchingAreaId,
|
||||
device_id: searchingDeviceId,
|
||||
entity_id: searchingEntityId,
|
||||
} = targetPickerValue;
|
||||
|
||||
if (searchingAreaId) {
|
||||
searchingAreaId = ensureArray(searchingAreaId);
|
||||
for (const singleSearchingAreaId of searchingAreaId) {
|
||||
const foundEntities = areaEntityLookup[singleSearchingAreaId];
|
||||
if (foundEntities?.length) {
|
||||
for (const foundEntity of foundEntities) {
|
||||
if (foundEntity.entity_category === null) {
|
||||
entityIds.add(foundEntity.entity_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const foundDevices = areaDeviceLookup[singleSearchingAreaId];
|
||||
if (!foundDevices?.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const foundDevice of foundDevices) {
|
||||
const foundDeviceEntities = deviceEntityLookup[foundDevice.id];
|
||||
if (!foundDeviceEntities?.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const foundDeviceEntity of foundDeviceEntities) {
|
||||
if (
|
||||
(!foundDeviceEntity.area_id ||
|
||||
foundDeviceEntity.area_id === singleSearchingAreaId) &&
|
||||
foundDeviceEntity.entity_category === null
|
||||
) {
|
||||
entityIds.add(foundDeviceEntity.entity_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchingDeviceId) {
|
||||
searchingDeviceId = ensureArray(searchingDeviceId);
|
||||
for (const singleSearchingDeviceId of searchingDeviceId) {
|
||||
const foundEntities = deviceEntityLookup[singleSearchingDeviceId];
|
||||
if (!foundEntities?.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (searchingAreaId) {
|
||||
searchingAreaId = ensureArray(searchingAreaId);
|
||||
for (const singleSearchingAreaId of searchingAreaId) {
|
||||
const foundEntities = this._areaEntityLookup[singleSearchingAreaId];
|
||||
if (foundEntities?.length) {
|
||||
for (const foundEntity of foundEntities) {
|
||||
if (foundEntity.entity_category === null) {
|
||||
entityIds.add(foundEntity.entity_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const foundDevices = this._areaDeviceLookup[singleSearchingAreaId];
|
||||
if (!foundDevices?.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const foundDevice of foundDevices) {
|
||||
const foundDeviceEntities = this._deviceEntityLookup[foundDevice.id];
|
||||
if (!foundDeviceEntities?.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const foundDeviceEntity of foundDeviceEntities) {
|
||||
if (
|
||||
(!foundDeviceEntity.area_id ||
|
||||
foundDeviceEntity.area_id === singleSearchingAreaId) &&
|
||||
foundDeviceEntity.entity_category === null
|
||||
) {
|
||||
entityIds.add(foundDeviceEntity.entity_id);
|
||||
}
|
||||
}
|
||||
if (searchingEntityId) {
|
||||
searchingEntityId = ensureArray(searchingEntityId);
|
||||
for (const singleSearchingEntityId of searchingEntityId) {
|
||||
entityIds.add(singleSearchingEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
return [...entityIds];
|
||||
}
|
||||
|
||||
if (searchingDeviceId) {
|
||||
searchingDeviceId = ensureArray(searchingDeviceId);
|
||||
for (const singleSearchingDeviceId of searchingDeviceId) {
|
||||
const foundEntities = this._deviceEntityLookup[singleSearchingDeviceId];
|
||||
if (!foundEntities?.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const foundEntity of foundEntities) {
|
||||
if (foundEntity.entity_category === null) {
|
||||
entityIds.add(foundEntity.entity_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchingEntityId) {
|
||||
searchingEntityId = ensureArray(searchingEntityId);
|
||||
for (const singleSearchingEntityId of searchingEntityId) {
|
||||
entityIds.add(singleSearchingEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
return [...entityIds];
|
||||
}
|
||||
);
|
||||
|
||||
private _dateRangeChanged(ev) {
|
||||
this._startDate = ev.detail.startDate;
|
||||
@ -611,20 +631,18 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
private _updatePath() {
|
||||
const params: Record<string, string> = {};
|
||||
|
||||
if (this._targetPickerValue) {
|
||||
if (this._targetPickerValue.entity_id) {
|
||||
params.entity_id = ensureArray(this._targetPickerValue.entity_id).join(
|
||||
","
|
||||
);
|
||||
}
|
||||
if (this._targetPickerValue.area_id) {
|
||||
params.area_id = ensureArray(this._targetPickerValue.area_id).join(",");
|
||||
}
|
||||
if (this._targetPickerValue.device_id) {
|
||||
params.device_id = ensureArray(this._targetPickerValue.device_id).join(
|
||||
","
|
||||
);
|
||||
}
|
||||
if (this._targetPickerValue.entity_id) {
|
||||
params.entity_id = ensureArray(this._targetPickerValue.entity_id).join(
|
||||
","
|
||||
);
|
||||
}
|
||||
if (this._targetPickerValue.area_id) {
|
||||
params.area_id = ensureArray(this._targetPickerValue.area_id).join(",");
|
||||
}
|
||||
if (this._targetPickerValue.device_id) {
|
||||
params.device_id = ensureArray(this._targetPickerValue.device_id).join(
|
||||
","
|
||||
);
|
||||
}
|
||||
|
||||
if (this._startDate) {
|
||||
@ -639,23 +657,35 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
|
||||
private _downloadHistory() {
|
||||
const entities = this._getEntityIds();
|
||||
if (entities.length === 0 || !this._mungedStateHistory) {
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize("ui.panel.history.download_data_error"),
|
||||
text: this.hass.localize("ui.panel.history.error_no_data"),
|
||||
warning: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const csv: string[] = ["entity_id,state,last_changed\n"];
|
||||
const formatDate = (number) => new Date(number).toISOString();
|
||||
|
||||
for (const line of this._mungedStateHistory!.line) {
|
||||
for (const line of this._mungedStateHistory.line) {
|
||||
for (const entity of line.data) {
|
||||
const entityId = entity.entity_id;
|
||||
for (const data of [entity.states, entity.statistics]) {
|
||||
if (!data) {
|
||||
continue;
|
||||
}
|
||||
for (const s of data) {
|
||||
|
||||
if (entity.statistics) {
|
||||
for (const s of entity.statistics) {
|
||||
csv.push(`${entityId},${s.state},${formatDate(s.last_changed)}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const s of entity.states) {
|
||||
csv.push(`${entityId},${s.state},${formatDate(s.last_changed)}\n`);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const timeline of this._mungedStateHistory!.timeline) {
|
||||
for (const timeline of this._mungedStateHistory.timeline) {
|
||||
const entityId = timeline.entity_id;
|
||||
for (const s of timeline.data) {
|
||||
csv.push(`${entityId},${s.state},${formatDate(s.last_changed)}\n`);
|
||||
@ -710,6 +740,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||
ha-date-range-picker {
|
||||
margin-right: 0;
|
||||
margin-inline-end: 0;
|
||||
margin-inline-start: initial;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@ -215,6 +215,8 @@ class HuiEnergyCarbonGaugeCard
|
||||
ha-svg-icon {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
inset-inline-end: 4px;
|
||||
inset-inline-start: initial;
|
||||
top: 4px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
@ -192,6 +192,8 @@ class HuiEnergyGridGaugeCard
|
||||
ha-svg-icon {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
inset-inline-end: 4px;
|
||||
inset-inline-start: initial;
|
||||
top: 4px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
@ -255,6 +255,8 @@ class HuiEnergySelfSufficiencyGaugeCard
|
||||
ha-svg-icon {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
inset-inline-end: 4px;
|
||||
inset-inline-start: initial;
|
||||
top: 4px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
@ -194,6 +194,8 @@ class HuiEnergySolarGaugeCard
|
||||
ha-svg-icon {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
inset-inline-end: 4px;
|
||||
inset-inline-start: initial;
|
||||
top: 4px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
@ -187,8 +187,6 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
|
||||
return html`
|
||||
<ha-card
|
||||
@action=${this._handleAction}
|
||||
@focus=${this.handleRippleFocus}
|
||||
@blur=${this.handleRippleBlur}
|
||||
@mousedown=${this.handleRippleActivate}
|
||||
@mouseup=${this.handleRippleDeactivate}
|
||||
@mouseenter=${this.handleRippleMouseEnter}
|
||||
@ -289,16 +287,6 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
|
||||
this._rippleHandlers.endPress();
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private handleRippleFocus() {
|
||||
this._rippleHandlers.startFocus();
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private handleRippleBlur() {
|
||||
this._rippleHandlers.endFocus();
|
||||
}
|
||||
|
||||
@eventOptions({ passive: true })
|
||||
private handleRippleMouseEnter() {
|
||||
this._rippleHandlers.startHover();
|
||||
@ -352,7 +340,18 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:host(:focus-visible) ha-state-icon,
|
||||
ha-card:focus-visible {
|
||||
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent);
|
||||
--shadow-focus: 0 0 0 1px
|
||||
var(--state-color, var(--paper-item-icon-color, #44739e));
|
||||
border-color: var(
|
||||
--state-color,
|
||||
var(--paper-item-icon-color, #44739e)
|
||||
);
|
||||
box-shadow: var(--shadow-default), var(--shadow-focus);
|
||||
}
|
||||
|
||||
ha-card:focus-visible ha-state-icon,
|
||||
:host(:active) ha-state-icon {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { mdiImageFilterCenterFocus } from "@mdi/js";
|
||||
import { isToday } from "date-fns";
|
||||
import { HassEntities } from "home-assistant-js-websocket";
|
||||
import { LatLngTuple } from "leaflet";
|
||||
import {
|
||||
@ -14,12 +13,8 @@ import { customElement, property, query, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { getColorByIndex } from "../../../common/color/colors";
|
||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||
import { formatDateTime } from "../../../common/datetime/format_date_time";
|
||||
import {
|
||||
formatTimeWithSeconds,
|
||||
formatTimeWeekday,
|
||||
} from "../../../common/datetime/format_time";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import { deepEqual } from "../../../common/util/deep-equal";
|
||||
import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
|
||||
import "../../../components/ha-card";
|
||||
@ -391,28 +386,23 @@ class HuiMapCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
const p = {} as HaMapPathPoint;
|
||||
p.point = [latitude, longitude] as LatLngTuple;
|
||||
const t = new Date(entityState.lu * 1000);
|
||||
if ((config.hours_to_show! ?? DEFAULT_HOURS_TO_SHOW) > 144) {
|
||||
// if showing > 6 days in the history trail, show the full
|
||||
// date and time
|
||||
p.tooltip = formatDateTime(t, this.hass.locale, this.hass.config);
|
||||
} else if (isToday(t)) {
|
||||
p.tooltip = formatTimeWithSeconds(
|
||||
t,
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
);
|
||||
} else {
|
||||
p.tooltip = formatTimeWeekday(
|
||||
t,
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
);
|
||||
}
|
||||
p.timestamp = new Date(entityState.lu * 1000);
|
||||
points.push(p);
|
||||
}
|
||||
|
||||
const entityConfig = this._configEntities?.find(
|
||||
(e) => e.entity === entityId
|
||||
);
|
||||
const name =
|
||||
entityConfig?.name ??
|
||||
(entityId in this.hass.states
|
||||
? computeStateName(this.hass.states[entityId])
|
||||
: entityId);
|
||||
|
||||
paths.push({
|
||||
points,
|
||||
name,
|
||||
fullDatetime: (config.hours_to_show ?? DEFAULT_HOURS_TO_SHOW) > 144,
|
||||
color: this._getColor(entityId),
|
||||
gradualOpacity: 0.8,
|
||||
});
|
||||
|
@ -524,6 +524,8 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
inset-inline-end: -3px;
|
||||
inset-inline-start: initial;
|
||||
}
|
||||
.icon-container:not([role="button"]) {
|
||||
pointer-events: none;
|
||||
|
@ -612,11 +612,6 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ============= RTL ============= */
|
||||
:host([rtl]) .temp-attribute {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* ============= NARROW ============= */
|
||||
|
||||
:host([narrow]) .icon-image {
|
||||
|
@ -13,7 +13,6 @@ import { DOMAINS_INPUT_ROW } from "../../../common/const";
|
||||
import { toggleAttribute } from "../../../common/dom/toggle_attribute";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import "../../../components/entity/state-badge";
|
||||
import "../../../components/ha-relative-time";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace/action_handler";
|
||||
@ -186,9 +185,6 @@ export class HuiGenericEntityRow extends LitElement {
|
||||
"no-secondary",
|
||||
!this.secondaryText && !this.config?.secondary_info
|
||||
);
|
||||
if (changedProps.has("hass")) {
|
||||
toggleAttribute(this, "rtl", computeRTL(this.hass!));
|
||||
}
|
||||
}
|
||||
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
@ -233,22 +229,11 @@ export class HuiGenericEntityRow extends LitElement {
|
||||
state-badge {
|
||||
flex: 0 0 40px;
|
||||
}
|
||||
:host([rtl]) .flex {
|
||||
margin-left: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
:host([rtl]) .flex ::slotted(*) {
|
||||
margin-left: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.state {
|
||||
text-align: right;
|
||||
}
|
||||
.state.rtl {
|
||||
text-align: left;
|
||||
text-align: var(--float-end);
|
||||
}
|
||||
.value {
|
||||
direction: ltr;
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { PropertyValues, ReactiveElement } from "lit";
|
||||
import { property } from "lit/decorators";
|
||||
import { computeRTL } from "../../../../common/util/compute_rtl";
|
||||
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { createCardElement } from "../../create-element/create-card-element";
|
||||
@ -70,13 +69,6 @@ export class HuiCardPreview extends ReactiveElement {
|
||||
}
|
||||
|
||||
if (changedProperties.has("hass")) {
|
||||
const oldHass = changedProperties.get("hass") as
|
||||
| HomeAssistant
|
||||
| undefined;
|
||||
if (!oldHass || oldHass.language !== this.hass!.language) {
|
||||
this.style.direction = computeRTL(this.hass!) ? "rtl" : "ltr";
|
||||
}
|
||||
|
||||
if (this._element) {
|
||||
this._element.hass = this.hass;
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||
import "../../../../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
@ -33,7 +32,6 @@ export class HuiEntityPickerTable extends LitElement {
|
||||
.id=${"entity_id"}
|
||||
.columns=${this._columns(this.narrow!)}
|
||||
.data=${this.entities}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.searchLabel=${this.hass.localize(
|
||||
"ui.panel.lovelace.unused_entities.search"
|
||||
)}
|
||||
|
@ -18,7 +18,6 @@ import {
|
||||
} from "superstruct";
|
||||
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||
import { customType } from "../../../../common/structs/is-custom-type";
|
||||
import { computeRTLDirection } from "../../../../common/util/compute_rtl";
|
||||
import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-formfield";
|
||||
import "../../../../components/ha-icon";
|
||||
@ -265,7 +264,6 @@ export class HuiEntitiesCardEditor
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.card.entities.show_header_toggle"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${this._config!.show_header_toggle !== false}
|
||||
@ -277,7 +275,6 @@ export class HuiEntitiesCardEditor
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.state_color"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${this._config!.state_color}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import "../../../components/entity/ha-state-label-badge";
|
||||
import { LovelaceBadgeConfig } from "../../../data/lovelace/config/badge";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
@ -29,10 +28,6 @@ export class HuiBadgePreview extends HTMLElement {
|
||||
}
|
||||
|
||||
set hass(hass: HomeAssistant) {
|
||||
if (!this._hass || this._hass.language !== hass.language) {
|
||||
this.style.direction = computeRTL(hass) ? "rtl" : "ltr";
|
||||
}
|
||||
|
||||
this._hass = hass;
|
||||
if (this._element) {
|
||||
this._element.hass = hass;
|
||||
|
@ -3,7 +3,6 @@ import { mdiHelpCircle } from "@mdi/js";
|
||||
import { CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import "../../../components/ha-circular-progress";
|
||||
import "../../../components/ha-dialog";
|
||||
import "../../../components/ha-formfield";
|
||||
@ -64,7 +63,6 @@ export class HuiSaveConfig extends LitElement implements HassDialog {
|
||||
title=${this.hass!.localize("ui.panel.lovelace.menu.help")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
dir=${computeRTLDirection(this.hass!)}
|
||||
>
|
||||
<ha-icon-button
|
||||
.path=${mdiHelpCircle}
|
||||
@ -88,7 +86,6 @@ export class HuiSaveConfig extends LitElement implements HassDialog {
|
||||
.label=${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.save_config.empty_config"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass!)}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${this._emptyConfig}
|
||||
|
@ -11,7 +11,6 @@ import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { computeDomain } from "../../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../../common/entity/compute_state_name";
|
||||
import { computeRTL } from "../../../../common/util/compute_rtl";
|
||||
import type { DataTableRowData } from "../../../../components/data-table/ha-data-table";
|
||||
import "../../../../components/ha-fab";
|
||||
import "../../../../components/ha-svg-icon";
|
||||
@ -99,7 +98,6 @@ export class HuiUnusedEntities extends LitElement {
|
||||
</div>
|
||||
<div
|
||||
class="fab ${classMap({
|
||||
rtl: computeRTL(this.hass),
|
||||
selected: this._selectedEntities.length,
|
||||
})}"
|
||||
>
|
||||
@ -171,20 +169,13 @@ export class HuiUnusedEntities extends LitElement {
|
||||
}
|
||||
.fab {
|
||||
position: sticky;
|
||||
float: right;
|
||||
float: var(--float-end);
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
inset-inline-end: calc(16px + env(safe-area-inset-right));
|
||||
inset-inline-start: initial;
|
||||
z-index: 1;
|
||||
}
|
||||
.fab.rtl {
|
||||
right: initial;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding-right: 16px;
|
||||
padding-left: calc(16px + env(safe-area-inset-left));
|
||||
padding-inline-end: 16px;
|
||||
padding-inline-start: calc(16px + env(safe-area-inset-left));
|
||||
}
|
||||
ha-fab {
|
||||
position: relative;
|
||||
bottom: calc(-80px - env(safe-area-inset-bottom));
|
||||
|
@ -7,7 +7,6 @@ import {
|
||||
nothing,
|
||||
} from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import { debounce } from "../../../common/util/debounce";
|
||||
import "../../../components/ha-slider";
|
||||
import "../../../components/ha-textfield";
|
||||
@ -86,7 +85,6 @@ class HuiInputNumberEntityRow extends LitElement implements LovelaceRow {
|
||||
<div class="flex">
|
||||
<ha-slider
|
||||
labeled
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.disabled=${isUnavailableState(stateObj.state)}
|
||||
.step=${Number(stateObj.attributes.step)}
|
||||
.min=${Number(stateObj.attributes.min)}
|
||||
|
@ -23,7 +23,6 @@ import {
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { stateActive } from "../../../common/entity/state_active";
|
||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import { debounce } from "../../../common/util/debounce";
|
||||
import "../../../components/ha-icon-button";
|
||||
import "../../../components/ha-slider";
|
||||
@ -254,7 +253,6 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow {
|
||||
? html`
|
||||
<ha-slider
|
||||
labeled
|
||||
.dir=${computeRTLDirection(this.hass!)}
|
||||
.value=${Number(stateObj.attributes.volume_level) * 100}
|
||||
@change=${this._selectedValueChanged}
|
||||
id="input"
|
||||
|
@ -7,7 +7,6 @@ import {
|
||||
nothing,
|
||||
} from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import { debounce } from "../../../common/util/debounce";
|
||||
import "../../../components/ha-slider";
|
||||
import "../../../components/ha-textfield";
|
||||
@ -91,7 +90,6 @@ class HuiNumberEntityRow extends LitElement implements LovelaceRow {
|
||||
<ha-slider
|
||||
labeled
|
||||
.disabled=${stateObj.state === UNAVAILABLE}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.step=${Number(stateObj.attributes.step)}
|
||||
.min=${Number(stateObj.attributes.min)}
|
||||
.max=${Number(stateObj.attributes.max)}
|
||||
|
@ -260,11 +260,6 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow {
|
||||
--mdc-icon-size: 40px;
|
||||
}
|
||||
|
||||
:host([rtl]) .flex {
|
||||
margin-left: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -73,6 +73,8 @@ export class LovelacePanel extends LitElement {
|
||||
|
||||
private _unsubUpdates?: Promise<UnsubscribeFunc>;
|
||||
|
||||
private _loading = false;
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
if (
|
||||
@ -162,7 +164,7 @@ export class LovelacePanel extends LitElement {
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues) {
|
||||
super.willUpdate(changedProps);
|
||||
if (!this.lovelace && this._panelState !== "error") {
|
||||
if (!this.lovelace && this._panelState !== "error" && !this._loading) {
|
||||
this._fetchConfig(false);
|
||||
}
|
||||
}
|
||||
@ -233,6 +235,8 @@ export class LovelacePanel extends LitElement {
|
||||
}
|
||||
|
||||
private async _fetchConfig(forceDiskRefresh: boolean) {
|
||||
this._loading = true;
|
||||
|
||||
let conf: LovelaceConfig;
|
||||
let rawConf: LovelaceRawConfig | undefined;
|
||||
let confMode: Lovelace["mode"] = this.panel!.config.mode;
|
||||
@ -301,6 +305,7 @@ export class LovelacePanel extends LitElement {
|
||||
rawConf = DEFAULT_CONFIG;
|
||||
confMode = "generated";
|
||||
} finally {
|
||||
this._loading = false;
|
||||
// Ignore updates for another 2 seconds.
|
||||
if (this.lovelace && this.lovelace.mode === "yaml") {
|
||||
setTimeout(() => {
|
||||
|
@ -8,9 +8,7 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit";
|
||||
import { property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import { nextRender } from "../../../common/util/render-status";
|
||||
import "../../../components/entity/ha-state-label-badge";
|
||||
import "../../../components/ha-svg-icon";
|
||||
@ -97,9 +95,6 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
||||
)}
|
||||
extended
|
||||
@click=${this._addCard}
|
||||
class=${classMap({
|
||||
rtl: computeRTL(this.hass!),
|
||||
})}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
@ -338,14 +333,11 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
||||
position: fixed;
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
inset-inline-end: calc(16px + env(safe-area-inset-right));
|
||||
inset-inline-start: initial;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
ha-fab.rtl {
|
||||
right: auto;
|
||||
left: calc(16px + env(safe-area-inset-left));
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.column > * {
|
||||
margin-left: 0;
|
||||
|
@ -137,12 +137,9 @@ export class PanelView extends LitElement implements LovelaceViewElement {
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
ha-fab.rtl {
|
||||
float: left;
|
||||
right: auto;
|
||||
left: calc(16px + env(safe-area-inset-left));
|
||||
float: var(--float-end);
|
||||
inset-inline-end: calc(16px + env(safe-area-inset-right));
|
||||
inset-inline-start: initial;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@ -8,9 +8,7 @@ import {
|
||||
html,
|
||||
} from "lit";
|
||||
import { property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import type { LovelaceViewElement } from "../../../data/lovelace";
|
||||
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
@ -100,9 +98,6 @@ export class SideBarView extends LitElement implements LovelaceViewElement {
|
||||
)}
|
||||
extended
|
||||
@click=${this._addCard}
|
||||
class=${classMap({
|
||||
rtl: computeRTL(this.hass!),
|
||||
})}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
@ -241,13 +236,10 @@ export class SideBarView extends LitElement implements LovelaceViewElement {
|
||||
position: fixed;
|
||||
right: calc(16px + env(safe-area-inset-right));
|
||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
inset-inline-end: calc(16px + env(safe-area-inset-right));
|
||||
inset-inline-start: initial;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
ha-fab.rtl {
|
||||
right: auto;
|
||||
left: calc(16px + env(safe-area-inset-left));
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -430,6 +430,8 @@ class PanelTodo extends LitElement {
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
inset-inline-end: 16px;
|
||||
inset-inline-start: initial;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@ -62,22 +62,16 @@ export const sidebarEditStyle = css`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 4px;
|
||||
inset-inline-end: 4px;
|
||||
inset-inline-start: initial;
|
||||
--mdc-icon-button-size: 40px;
|
||||
}
|
||||
|
||||
:host([rtl]) .show-panel {
|
||||
right: initial;
|
||||
left: 4px;
|
||||
}
|
||||
|
||||
.hide-panel {
|
||||
top: 4px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
:host([rtl]) .hide-panel {
|
||||
right: initial;
|
||||
left: 8px;
|
||||
inset-inline-end: 8px;
|
||||
inset-inline-start: initial;
|
||||
}
|
||||
|
||||
:host([expanded]) .hide-panel {
|
||||
|
@ -2,7 +2,6 @@ import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { stateActive } from "../common/entity/state_active";
|
||||
import { computeRTL } from "../common/util/compute_rtl";
|
||||
import "../components/entity/ha-entity-toggle";
|
||||
import "../components/entity/state-info";
|
||||
import { haStyle } from "../resources/styles";
|
||||
@ -16,9 +15,6 @@ class StateCardAlert extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public inDialog = false;
|
||||
|
||||
// property used only in CSS
|
||||
@property({ type: Boolean, reflect: true }) public rtl = false;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div class="horizontal justified layout">
|
||||
@ -40,18 +36,6 @@ class StateCardAlert extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
protected updated(changedProps) {
|
||||
super.updated(changedProps);
|
||||
if (!changedProps.has("hass")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.language !== this.hass.language) {
|
||||
this.rtl = computeRTL(this.hass);
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
@ -69,7 +53,6 @@ class StateCardAlert extends LitElement {
|
||||
overflow-wrap: break-word;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
direction: ltr;
|
||||
}
|
||||
ha-entity-toggle {
|
||||
margin: -4px -16px -4px 0;
|
||||
|
@ -3,7 +3,6 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { computeDomain } from "../common/entity/compute_domain";
|
||||
import { computeRTL } from "../common/util/compute_rtl";
|
||||
import "../components/entity/state-info";
|
||||
import { isUnavailableState } from "../data/entity";
|
||||
import { SENSOR_DEVICE_CLASS_TIMESTAMP } from "../data/sensor";
|
||||
@ -53,18 +52,6 @@ class StateCardDisplay extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
protected updated(changedProps) {
|
||||
super.updated(changedProps);
|
||||
if (!changedProps.has("hass")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass || oldHass.language !== this.hass.language) {
|
||||
this.rtl = computeRTL(this.hass);
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
@ -83,7 +70,6 @@ class StateCardDisplay extends LitElement {
|
||||
word-break: break-word;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
direction: ltr;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.state.has-unit_of_measurement {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { computeRTLDirection } from "../common/util/compute_rtl";
|
||||
import { debounce } from "../common/util/debounce";
|
||||
import "../components/entity/state-info";
|
||||
import "../components/ha-slider";
|
||||
@ -58,7 +57,6 @@ class StateCardInputNumber extends LitElement {
|
||||
<div class="flex">
|
||||
<ha-slider
|
||||
labeled
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.disabled=${isUnavailableState(this.stateObj.state)}
|
||||
.step=${Number(this.stateObj.attributes.step)}
|
||||
.min=${Number(this.stateObj.attributes.min)}
|
||||
|
@ -7,7 +7,6 @@ import "../components/ha-textfield";
|
||||
import { HomeAssistant } from "../types";
|
||||
import { haStyle } from "../resources/styles";
|
||||
import { loadPolyfillIfNeeded } from "../resources/resize-observer.polyfill";
|
||||
import { computeRTLDirection } from "../common/util/compute_rtl";
|
||||
import { isUnavailableState } from "../data/entity";
|
||||
import { debounce } from "../common/util/debounce";
|
||||
|
||||
@ -61,7 +60,6 @@ class StateCardNumber extends LitElement {
|
||||
<div class="flex">
|
||||
<ha-slider
|
||||
labeled
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.disabled=${isUnavailableState(this.stateObj.state)}
|
||||
.step=${Number(this.stateObj.attributes.step)}
|
||||
.min=${Number(this.stateObj.attributes.min)}
|
||||
|
@ -4625,7 +4625,7 @@
|
||||
"device_actions": {
|
||||
"reinterview_device": "Re-interview device",
|
||||
"ping_device": "Ping device",
|
||||
"open_commissioning_window": "Enable commisisioning mode",
|
||||
"open_commissioning_window": "Share device",
|
||||
"manage_fabrics": "Manage fabrics",
|
||||
"view_thread_network": "View Thread network"
|
||||
},
|
||||
@ -4657,11 +4657,12 @@
|
||||
"ping_complete": "Ping device complete."
|
||||
},
|
||||
"open_commissioning_window": {
|
||||
"title": "Enable commissioning mode",
|
||||
"title": "Share device",
|
||||
"introduction": "Enable commissioning mode on the device to pair it to another Matter controller.",
|
||||
"start_commissioning": "Enable commissioning mode",
|
||||
"start_commissioning": "Share device",
|
||||
"in_progress": "We're communicating with the device. This may take some time.",
|
||||
"failed": "The command failed. Additional information may be available in the logs.",
|
||||
"success": "Your device can now be added to another Matter controller, scan the QR code below or enter the sharing code in the app of the controller you want to add your device to.",
|
||||
"sharing_code": "Sharing code"
|
||||
}
|
||||
},
|
||||
@ -6505,7 +6506,9 @@
|
||||
"start_search": "Start by selecting an area, device or entity above",
|
||||
"add_all": "Add all entities",
|
||||
"remove_all": "Remove all selections",
|
||||
"download_data": "Download data"
|
||||
"download_data": "Download data",
|
||||
"download_data_error": "Unable to download data",
|
||||
"error_no_data": "You need to select data first."
|
||||
}
|
||||
},
|
||||
"tips": {
|
||||
|
134
yarn.lock
134
yarn.lock
@ -4515,15 +4515,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/eslint-plugin@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:6.19.1"
|
||||
"@typescript-eslint/eslint-plugin@npm:6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:6.20.0"
|
||||
dependencies:
|
||||
"@eslint-community/regexpp": "npm:^4.5.1"
|
||||
"@typescript-eslint/scope-manager": "npm:6.19.1"
|
||||
"@typescript-eslint/type-utils": "npm:6.19.1"
|
||||
"@typescript-eslint/utils": "npm:6.19.1"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.19.1"
|
||||
"@typescript-eslint/scope-manager": "npm:6.20.0"
|
||||
"@typescript-eslint/type-utils": "npm:6.20.0"
|
||||
"@typescript-eslint/utils": "npm:6.20.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.20.0"
|
||||
debug: "npm:^4.3.4"
|
||||
graphemer: "npm:^1.4.0"
|
||||
ignore: "npm:^5.2.4"
|
||||
@ -4536,44 +4536,44 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: e88a35527b066a42d0253d153183a360faedc1cd39867c541ce7cb1f7b22f8446bb913b998fcdeba269d5d4217888af42e6d64da5c0592b1f49ed5648d2e3e84
|
||||
checksum: dee6a2392c831e6ae69611ecc4de06e66a7b16f6bf6d8e3bfd25091eb14d88c9d0bb9c9cd634efcfa318902341f7a459cf48f713d55cb1d610145ca1f52af4d3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/parser@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/parser@npm:6.19.1"
|
||||
"@typescript-eslint/parser@npm:6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "@typescript-eslint/parser@npm:6.20.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager": "npm:6.19.1"
|
||||
"@typescript-eslint/types": "npm:6.19.1"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.19.1"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.19.1"
|
||||
"@typescript-eslint/scope-manager": "npm:6.20.0"
|
||||
"@typescript-eslint/types": "npm:6.20.0"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.20.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.20.0"
|
||||
debug: "npm:^4.3.4"
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 63ff00a56586879a62e40b27b55c94501173fcf2fb5a620d01e7505851b4bb20feb1e7fbad36010af97aefc0a722267d9ce3aa004abab22cb7eb23eebb0102ce
|
||||
checksum: 691062d47cae7977604ede848ffff3689162428a53577f298989f585954aa3a3450e7fd5c2b363d024cd5f16022c163cecf0f1f1d138234bbd78048050b4b8bf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/scope-manager@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/scope-manager@npm:6.19.1"
|
||||
"@typescript-eslint/scope-manager@npm:6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "@typescript-eslint/scope-manager@npm:6.20.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:6.19.1"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.19.1"
|
||||
checksum: 2a17f68d3c41582bfac7ecd192e2c2539cf4d2c9728a7018d842da7a8a23986b8a1f8cfcb59862c909b483140a2d164a4ba44451905e0a141378e5dd0df056cc
|
||||
"@typescript-eslint/types": "npm:6.20.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.20.0"
|
||||
checksum: 2c1a644f2931454b34875f2e6dffad52a1fc7b6ac508d7d1ad3cd9da028a7dff9c6191feeea2c9ca691deba199ac9e83cbd0036914be4cd45b6954437f03c09a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/type-utils@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/type-utils@npm:6.19.1"
|
||||
"@typescript-eslint/type-utils@npm:6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "@typescript-eslint/type-utils@npm:6.20.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree": "npm:6.19.1"
|
||||
"@typescript-eslint/utils": "npm:6.19.1"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.20.0"
|
||||
"@typescript-eslint/utils": "npm:6.20.0"
|
||||
debug: "npm:^4.3.4"
|
||||
ts-api-utils: "npm:^1.0.1"
|
||||
peerDependencies:
|
||||
@ -4581,23 +4581,23 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 5150b897d8b3778c549c6b964b031981da1039dfa0fb89a0eb92702735ca55793d2f840af14b340eccbca81669ba3dd02d7f09fb420fb66b18ec9f1f211b3243
|
||||
checksum: bc2f2793cfec3463164b5f5ded31b4e169e21c3a1990c1ce4effe70a359c486d92fbbc4cd92758bbf1c30a468ad0839e0fa890bd452c707d0c294cb3a7b14021
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/types@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/types@npm:6.19.1"
|
||||
checksum: 93f3ded80b81a1b8686866b93e36ddf9bac04604d09e88d7ed1ec25b6b2f49ff64747d8d194ba1f3215e231fd0790b88fb5ecadcc6ed53ff584f8c0b87423216
|
||||
"@typescript-eslint/types@npm:6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "@typescript-eslint/types@npm:6.20.0"
|
||||
checksum: 74ed1761e27c3c1a29fd260fe51096f42cfb1472b20390d6df6ec41de0420208f379e809de416e81cd7c00fdc3d5550b2391872be56bf4a1b0c595f71db0b1ea
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/typescript-estree@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:6.19.1"
|
||||
"@typescript-eslint/typescript-estree@npm:6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:6.20.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:6.19.1"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.19.1"
|
||||
"@typescript-eslint/types": "npm:6.20.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.20.0"
|
||||
debug: "npm:^4.3.4"
|
||||
globby: "npm:^11.1.0"
|
||||
is-glob: "npm:^4.0.3"
|
||||
@ -4607,34 +4607,34 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 3ce91dd477ccb2cc3cf5d07ac8d23792988f4fad78bfd39783292846f32daea5081d3790ba9cc795d9de89ea2e1d55dc9c3d2aeaa8597093b0f6ac3a206195e9
|
||||
checksum: 55b280c6e71c79cb009ac80189a7f0e1aa9011bc7206c810bbb52d9703a894aa2817dfd44d947edf64d62f3aa0962e01f3423fcb21d2f39964a4840287d9e196
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/utils@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/utils@npm:6.19.1"
|
||||
"@typescript-eslint/utils@npm:6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "@typescript-eslint/utils@npm:6.20.0"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": "npm:^4.4.0"
|
||||
"@types/json-schema": "npm:^7.0.12"
|
||||
"@types/semver": "npm:^7.5.0"
|
||||
"@typescript-eslint/scope-manager": "npm:6.19.1"
|
||||
"@typescript-eslint/types": "npm:6.19.1"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.19.1"
|
||||
"@typescript-eslint/scope-manager": "npm:6.20.0"
|
||||
"@typescript-eslint/types": "npm:6.20.0"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.20.0"
|
||||
semver: "npm:^7.5.4"
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
checksum: f8931df675defa84af373c81bbb13cc34c2fcf0803c687a38b982e85335dbf2fb8415667fbabaa043df0326ba3e98ed974104bbd21f09ec538304fc3adeed0c3
|
||||
checksum: 6d4604be6123e0073dd5e7dd357c95b370c678572d2e982478d0d6937d4d65f0cad0ac207b8b724f3bce239e64ba1ddd6bece11e1592734d8bf691177e6971e6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/visitor-keys@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:6.19.1"
|
||||
"@typescript-eslint/visitor-keys@npm:6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:6.20.0"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:6.19.1"
|
||||
"@typescript-eslint/types": "npm:6.20.0"
|
||||
eslint-visitor-keys: "npm:^3.4.1"
|
||||
checksum: b41f3247520e1e4d3e43876843b03f0d887e544d4ac8a9e1f4b25d08568da36fedde883fa226488a595f688198859cd0290d0f1351c2ca6cbc30cca2c90adf21
|
||||
checksum: df066c73f3880ad78880c442f307e58f026e6047d9caab9d7c356d13276f4fe466fab3e8d19cdb1e6749e87639cb7c4babcfe118f554fcd2d3929ce9f4983216
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -7909,9 +7909,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-plugin-lit-a11y@npm:4.1.1":
|
||||
version: 4.1.1
|
||||
resolution: "eslint-plugin-lit-a11y@npm:4.1.1"
|
||||
"eslint-plugin-lit-a11y@npm:4.1.2":
|
||||
version: 4.1.2
|
||||
resolution: "eslint-plugin-lit-a11y@npm:4.1.2"
|
||||
dependencies:
|
||||
aria-query: "npm:^5.1.3"
|
||||
axe-core: "npm:^4.3.3"
|
||||
@ -7926,7 +7926,7 @@ __metadata:
|
||||
requireindex: "npm:~1.2.0"
|
||||
peerDependencies:
|
||||
eslint: ">= 5"
|
||||
checksum: f8d20e4e18ea9cf17c95546f878213d57f3eb9fd71a01ebae1b5d1689c0da7c35f0fe39137994717e600c3d12cfaa754ab3d4cdd854a6cf4d0a907ae898bc9a5
|
||||
checksum: 2d70f0b9fa6afc7f259877acd7e69c14f0104a69a019efb594d5de603e12b982e4a96fec5b169005fab244655951f85bff77f469d9aeadb885974f963a7d9996
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -9437,10 +9437,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hls.js@npm:1.5.2":
|
||||
version: 1.5.2
|
||||
resolution: "hls.js@npm:1.5.2"
|
||||
checksum: bf92e8f005eb4e906bc19a0baf6428df4cbfd344b517de70496b953d77f1231324d26b4dc88c375d3cd481311601c1d1d5aea34ec4e0fc96e9df22b9b0e28a84
|
||||
"hls.js@npm:1.5.3":
|
||||
version: 1.5.3
|
||||
resolution: "hls.js@npm:1.5.3"
|
||||
checksum: c5b7cb6fddd6ad425a82e1b8b4f818552e6e242254b35c7d7c7b9d3beb4dd40cc85d8bbc32a5d1b57031305d7d9f4973f9d0f80b70351bb8597393f4629072fc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -9546,8 +9546,8 @@ __metadata:
|
||||
"@types/tar": "npm:6.1.11"
|
||||
"@types/ua-parser-js": "npm:0.7.39"
|
||||
"@types/webspeechapi": "npm:0.0.29"
|
||||
"@typescript-eslint/eslint-plugin": "npm:6.19.1"
|
||||
"@typescript-eslint/parser": "npm:6.19.1"
|
||||
"@typescript-eslint/eslint-plugin": "npm:6.20.0"
|
||||
"@typescript-eslint/parser": "npm:6.20.0"
|
||||
"@vaadin/combo-box": "npm:24.3.4"
|
||||
"@vaadin/vaadin-themable-mixin": "npm:24.3.4"
|
||||
"@vibrant/color": "npm:3.2.1-alpha.1"
|
||||
@ -9580,7 +9580,7 @@ __metadata:
|
||||
eslint-plugin-disable: "npm:2.0.3"
|
||||
eslint-plugin-import: "npm:2.29.1"
|
||||
eslint-plugin-lit: "npm:1.11.0"
|
||||
eslint-plugin-lit-a11y: "npm:4.1.1"
|
||||
eslint-plugin-lit-a11y: "npm:4.1.2"
|
||||
eslint-plugin-unused-imports: "npm:3.0.0"
|
||||
eslint-plugin-wc: "npm:2.0.4"
|
||||
fancy-log: "npm:2.0.0"
|
||||
@ -9594,10 +9594,10 @@ __metadata:
|
||||
gulp-merge-json: "npm:2.1.2"
|
||||
gulp-rename: "npm:2.0.0"
|
||||
gulp-zopfli-green: "npm:6.0.1"
|
||||
hls.js: "npm:1.5.2"
|
||||
hls.js: "npm:1.5.3"
|
||||
home-assistant-js-websocket: "npm:9.1.0"
|
||||
html-minifier-terser: "npm:7.2.0"
|
||||
husky: "npm:9.0.6"
|
||||
husky: "npm:9.0.7"
|
||||
idb-keyval: "npm:6.2.1"
|
||||
instant-mocha: "npm:1.5.2"
|
||||
intl-messageformat: "npm:10.5.11"
|
||||
@ -9879,12 +9879,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"husky@npm:9.0.6":
|
||||
version: 9.0.6
|
||||
resolution: "husky@npm:9.0.6"
|
||||
"husky@npm:9.0.7":
|
||||
version: 9.0.7
|
||||
resolution: "husky@npm:9.0.7"
|
||||
bin:
|
||||
husky: bin.js
|
||||
checksum: e198c90a59d460cf860c33e0a4c3927ecfb645d4fd4c2de3fbcd5fb56b858a923af452508d549f6ed020bb48de08290912cd77c006dd2a83e551c24c17340d5b
|
||||
checksum: c5673acb9f224b6d2b36ee4892c6b99dbe9a077b041aee6013efeacb71d2d2cbe6ab7fac061f68fa5653c7dbe93aacfeed69eea01f755688e4c36c4044dcc5c0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user