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