mirror of
https://github.com/home-assistant/frontend.git
synced 2026-03-01 12:57:44 +00:00
Compare commits
1 Commits
dev
...
fix-dialog
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef3e6302f1 |
@@ -30,7 +30,7 @@
|
||||
"@braintree/sanitize-url": "7.1.2",
|
||||
"@codemirror/autocomplete": "6.20.0",
|
||||
"@codemirror/commands": "6.10.2",
|
||||
"@codemirror/language": "6.12.2",
|
||||
"@codemirror/language": "6.12.1",
|
||||
"@codemirror/legacy-modes": "6.5.2",
|
||||
"@codemirror/search": "6.6.0",
|
||||
"@codemirror/state": "6.5.4",
|
||||
@@ -92,7 +92,7 @@
|
||||
"@webcomponents/scoped-custom-element-registry": "0.0.10",
|
||||
"@webcomponents/webcomponentsjs": "2.8.0",
|
||||
"app-datepicker": "5.1.1",
|
||||
"barcode-detector": "3.1.0",
|
||||
"barcode-detector": "3.0.8",
|
||||
"color-name": "2.1.0",
|
||||
"comlink": "4.4.2",
|
||||
"core-js": "3.48.0",
|
||||
@@ -149,7 +149,7 @@
|
||||
"@babel/plugin-transform-runtime": "7.29.0",
|
||||
"@babel/preset-env": "7.29.0",
|
||||
"@bundle-stats/plugin-webpack-filter": "4.21.10",
|
||||
"@html-eslint/eslint-plugin": "0.57.1",
|
||||
"@html-eslint/eslint-plugin": "0.57.0",
|
||||
"@lokalise/node-api": "15.6.1",
|
||||
"@octokit/auth-oauth-device": "8.0.3",
|
||||
"@octokit/plugin-retry": "8.1.0",
|
||||
|
||||
@@ -133,34 +133,33 @@ const computeStateToPartsFromEntityAttributes = (
|
||||
),
|
||||
});
|
||||
} catch (_err) {
|
||||
// fallback to default numeric formatting below
|
||||
// fallback to default
|
||||
}
|
||||
|
||||
if (parts.length) {
|
||||
const TYPE_MAP: Record<string, ValuePart["type"]> = {
|
||||
integer: "value",
|
||||
group: "value",
|
||||
decimal: "value",
|
||||
fraction: "value",
|
||||
literal: "literal",
|
||||
currency: "unit",
|
||||
};
|
||||
const TYPE_MAP: Record<string, ValuePart["type"]> = {
|
||||
integer: "value",
|
||||
group: "value",
|
||||
decimal: "value",
|
||||
fraction: "value",
|
||||
literal: "literal",
|
||||
currency: "unit",
|
||||
};
|
||||
|
||||
const valueParts: ValuePart[] = [];
|
||||
const valueParts: ValuePart[] = [];
|
||||
|
||||
for (const part of parts) {
|
||||
const type = TYPE_MAP[part.type];
|
||||
if (!type) continue;
|
||||
const last = valueParts[valueParts.length - 1];
|
||||
// Merge consecutive numeric parts (e.g. "1" + "," + "234" + "." + "56" → "1,234.56")
|
||||
if (type === "value" && last?.type === "value") {
|
||||
last.value += part.value;
|
||||
} else {
|
||||
valueParts.push({ type, value: part.value });
|
||||
}
|
||||
for (const part of parts) {
|
||||
const type = TYPE_MAP[part.type];
|
||||
if (!type) continue;
|
||||
const last = valueParts[valueParts.length - 1];
|
||||
// Merge consecutive numeric parts (e.g. "1" + "," + "234" + "." + "56" → "1,234.56")
|
||||
if (type === "value" && last?.type === "value") {
|
||||
last.value += part.value;
|
||||
} else {
|
||||
valueParts.push({ type, value: part.value });
|
||||
}
|
||||
return valueParts;
|
||||
}
|
||||
|
||||
return valueParts;
|
||||
}
|
||||
|
||||
// default processing of numeric values
|
||||
|
||||
@@ -245,7 +245,7 @@ export class HaButton extends Button {
|
||||
}
|
||||
|
||||
.label {
|
||||
overflow: var(--ha-button-label-overflow, hidden);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding: var(--ha-space-1) 0;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { mdiMenuDown } from "@mdi/js";
|
||||
import type { TemplateResult } from "lit";
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import "./ha-attribute-icon";
|
||||
import "./ha-dropdown";
|
||||
import "./ha-dropdown-item";
|
||||
import "./ha-icon";
|
||||
@@ -14,10 +16,17 @@ export interface SelectOption {
|
||||
value: string;
|
||||
iconPath?: string;
|
||||
icon?: string;
|
||||
attributeIcon?: {
|
||||
stateObj: HassEntity;
|
||||
attribute: string;
|
||||
attributeValue?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@customElement("ha-control-select-menu")
|
||||
export class HaControlSelectMenu extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ type: Boolean, attribute: "show-arrow" })
|
||||
public showArrow = false;
|
||||
|
||||
@@ -38,9 +47,6 @@ export class HaControlSelectMenu extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public options: SelectOption[] = [];
|
||||
|
||||
@property({ attribute: false })
|
||||
public renderIcon?: (value: string) => TemplateResult<1> | typeof nothing;
|
||||
|
||||
@query("button") private _triggerButton!: HTMLButtonElement;
|
||||
|
||||
public override render() {
|
||||
@@ -88,8 +94,14 @@ export class HaControlSelectMenu extends LitElement {
|
||||
? html`<ha-svg-icon slot="icon" .path=${option.iconPath}></ha-svg-icon>`
|
||||
: option.icon
|
||||
? html`<ha-icon slot="icon" .icon=${option.icon}></ha-icon>`
|
||||
: this.renderIcon
|
||||
? html`<span slot="icon">${this.renderIcon(option.value)}</span>`
|
||||
: option.attributeIcon
|
||||
? html`<ha-attribute-icon
|
||||
slot="icon"
|
||||
.hass=${this.hass}
|
||||
.stateObj=${option.attributeIcon.stateObj}
|
||||
.attribute=${option.attributeIcon.attribute}
|
||||
.attributeValue=${option.attributeIcon.attributeValue}
|
||||
></ha-attribute-icon>`
|
||||
: nothing}
|
||||
${option.label}</ha-dropdown-item
|
||||
>`;
|
||||
@@ -107,20 +119,24 @@ export class HaControlSelectMenu extends LitElement {
|
||||
}
|
||||
|
||||
private _renderIcon() {
|
||||
const value = this.getValueObject(this.options, this.value);
|
||||
const { iconPath, icon, attributeIcon } =
|
||||
this.getValueObject(this.options, this.value) ?? {};
|
||||
const defaultIcon = this.querySelector("[slot='icon']");
|
||||
|
||||
return html`
|
||||
<div class="icon">
|
||||
${value?.iconPath
|
||||
? html`<ha-svg-icon
|
||||
slot="icon"
|
||||
.path=${value.iconPath}
|
||||
></ha-svg-icon>`
|
||||
: value?.icon
|
||||
? html`<ha-icon slot="icon" .icon=${value.icon}></ha-icon>`
|
||||
: this.renderIcon && this.value
|
||||
? this.renderIcon(this.value)
|
||||
${iconPath
|
||||
? html`<ha-svg-icon slot="icon" .path=${iconPath}></ha-svg-icon>`
|
||||
: icon
|
||||
? html`<ha-icon slot="icon" .icon=${icon}></ha-icon>`
|
||||
: attributeIcon
|
||||
? html`<ha-attribute-icon
|
||||
slot="icon"
|
||||
.hass=${this.hass}
|
||||
.stateObj=${attributeIcon.stateObj}
|
||||
.attribute=${attributeIcon.attribute}
|
||||
.attributeValue=${attributeIcon.attributeValue}
|
||||
></ha-attribute-icon>`
|
||||
: defaultIcon
|
||||
? html`<slot name="icon"></slot>`
|
||||
: nothing}
|
||||
@@ -156,12 +172,12 @@ export class HaControlSelectMenu extends LitElement {
|
||||
font-size: var(--ha-font-size-m);
|
||||
line-height: 1.4;
|
||||
width: auto;
|
||||
color: var(--primary-text-color);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.select-anchor {
|
||||
border: none;
|
||||
text-align: left;
|
||||
color: var(--primary-text-color);
|
||||
height: var(--control-select-menu-height);
|
||||
padding: var(--control-select-menu-padding);
|
||||
overflow: hidden;
|
||||
|
||||
@@ -63,12 +63,9 @@ export class HaDialogHeader extends LitElement {
|
||||
justify-content: center;
|
||||
min-height: var(--ha-space-12);
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.header-title {
|
||||
height: var(
|
||||
min-height: var(
|
||||
--ha-dialog-header-title-height,
|
||||
calc(var(--ha-font-size-xl) + var(--ha-space-1))
|
||||
);
|
||||
|
||||
@@ -74,7 +74,6 @@ export class HaIconButton extends LitElement {
|
||||
);
|
||||
--wa-color-on-normal: currentColor;
|
||||
--wa-color-fill-quiet: transparent;
|
||||
--ha-button-label-overflow: visible;
|
||||
}
|
||||
ha-button::after {
|
||||
content: "";
|
||||
|
||||
@@ -9,7 +9,6 @@ import type { CSSResultGroup, PropertyValues } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||
import "../../../components/ha-attribute-icon";
|
||||
import "../../../components/ha-control-select-menu";
|
||||
import "../../../components/ha-icon-button-group";
|
||||
import "../../../components/ha-icon-button-toggle";
|
||||
@@ -40,38 +39,6 @@ class MoreInfoClimate extends LitElement {
|
||||
|
||||
@state() private _mainControl: MainControl = "temperature";
|
||||
|
||||
private _renderPresetModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="preset_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private _renderFanModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="fan_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private _renderSwingModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="swing_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private _renderSwingHorizontalModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="swing_horizontal_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
if (
|
||||
changedProps.has("stateObj") &&
|
||||
@@ -238,8 +205,12 @@ class MoreInfoClimate extends LitElement {
|
||||
"preset_mode",
|
||||
mode
|
||||
),
|
||||
attributeIcon: {
|
||||
stateObj,
|
||||
attribute: "preset_mode",
|
||||
attributeValue: mode,
|
||||
},
|
||||
}))}
|
||||
.renderIcon=${this._renderPresetModeIcon}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
@@ -263,8 +234,12 @@ class MoreInfoClimate extends LitElement {
|
||||
"fan_mode",
|
||||
mode
|
||||
),
|
||||
attributeIcon: {
|
||||
stateObj,
|
||||
attribute: "fan_mode",
|
||||
attributeValue: mode,
|
||||
},
|
||||
}))}
|
||||
.renderIcon=${this._renderFanModeIcon}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiFan}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
@@ -288,8 +263,12 @@ class MoreInfoClimate extends LitElement {
|
||||
"swing_mode",
|
||||
mode
|
||||
),
|
||||
attributeIcon: {
|
||||
stateObj,
|
||||
attribute: "swing_mode",
|
||||
attributeValue: mode,
|
||||
},
|
||||
}))}
|
||||
.renderIcon=${this._renderSwingModeIcon}
|
||||
>
|
||||
<ha-svg-icon
|
||||
slot="icon"
|
||||
@@ -318,9 +297,13 @@ class MoreInfoClimate extends LitElement {
|
||||
"swing_horizontal_mode",
|
||||
mode
|
||||
),
|
||||
attributeIcon: {
|
||||
stateObj,
|
||||
attribute: "swing_horizontal_mode",
|
||||
attributeValue: mode,
|
||||
},
|
||||
})
|
||||
)}
|
||||
.renderIcon=${this._renderSwingHorizontalModeIcon}
|
||||
>
|
||||
<ha-svg-icon
|
||||
slot="icon"
|
||||
|
||||
@@ -40,22 +40,6 @@ class MoreInfoFan extends LitElement {
|
||||
|
||||
@state() public _presetMode?: string;
|
||||
|
||||
private _renderPresetModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="preset_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private _renderDirectionIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="direction"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private _toggle = () => {
|
||||
const service = this.stateObj?.state === "on" ? "turn_off" : "turn_on";
|
||||
forwardHaptic(this, "light");
|
||||
@@ -208,9 +192,15 @@ class MoreInfoFan extends LitElement {
|
||||
"preset_mode",
|
||||
mode
|
||||
),
|
||||
attributeIcon: this.stateObj
|
||||
? {
|
||||
stateObj: this.stateObj,
|
||||
attribute: "preset_mode",
|
||||
attributeValue: mode,
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
)}
|
||||
.renderIcon=${this._renderPresetModeIcon}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
@@ -236,8 +226,14 @@ class MoreInfoFan extends LitElement {
|
||||
direction
|
||||
)
|
||||
: direction,
|
||||
attributeIcon: this.stateObj
|
||||
? {
|
||||
stateObj: this.stateObj,
|
||||
attribute: "direction",
|
||||
attributeValue: direction,
|
||||
}
|
||||
: undefined,
|
||||
}))}
|
||||
.renderIcon=${this._renderDirectionIcon}
|
||||
>
|
||||
<ha-attribute-icon
|
||||
slot="icon"
|
||||
|
||||
@@ -23,14 +23,6 @@ class MoreInfoHumidifier extends LitElement {
|
||||
|
||||
@state() public _mode?: string;
|
||||
|
||||
private _renderModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
super.willUpdate(changedProps);
|
||||
if (changedProps.has("stateObj")) {
|
||||
@@ -114,8 +106,14 @@ class MoreInfoHumidifier extends LitElement {
|
||||
mode
|
||||
)
|
||||
: mode,
|
||||
attributeIcon: stateObj
|
||||
? {
|
||||
stateObj,
|
||||
attribute: "mode",
|
||||
attributeValue: mode,
|
||||
}
|
||||
: undefined,
|
||||
})) || []}
|
||||
.renderIcon=${this._renderModeIcon}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
|
||||
@@ -55,14 +55,6 @@ class MoreInfoLight extends LitElement {
|
||||
|
||||
@state() private _mainControl: MainControl = "brightness";
|
||||
|
||||
private _renderEffectIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="effect"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
protected updated(changedProps: PropertyValues<typeof this>): void {
|
||||
if (changedProps.has("stateObj")) {
|
||||
this._effect = this.stateObj?.attributes.effect;
|
||||
@@ -279,9 +271,15 @@ class MoreInfoLight extends LitElement {
|
||||
effect
|
||||
)
|
||||
: effect,
|
||||
attributeIcon: this.stateObj
|
||||
? {
|
||||
stateObj: this.stateObj,
|
||||
attribute: "effect",
|
||||
attributeValue: effect,
|
||||
}
|
||||
: undefined,
|
||||
})
|
||||
)}
|
||||
.renderIcon=${this._renderEffectIcon}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiCreation}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
|
||||
@@ -24,14 +24,6 @@ class MoreInfoWaterHeater extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public stateObj?: WaterHeaterEntity;
|
||||
|
||||
private _renderOperationModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
attribute="operation_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
protected render() {
|
||||
if (!this.stateObj) {
|
||||
return nothing;
|
||||
@@ -93,8 +85,12 @@ class MoreInfoWaterHeater extends LitElement {
|
||||
.map((mode) => ({
|
||||
value: mode,
|
||||
label: this.hass.formatEntityState(stateObj, mode),
|
||||
attributeIcon: {
|
||||
stateObj,
|
||||
attribute: "operation_mode",
|
||||
attributeValue: mode,
|
||||
},
|
||||
}))}
|
||||
.renderIcon=${this._renderOperationModeIcon}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiWaterBoiler}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
|
||||
@@ -2,27 +2,17 @@ import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import type { CSSResultGroup, PropertyValues } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { computeAttributeNameDisplay } from "../../common/entity/compute_attribute_display";
|
||||
import checkValidDate from "../../common/datetime/check_valid_date";
|
||||
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
|
||||
import "../../components/ha-attribute-value";
|
||||
import "../../components/ha-card";
|
||||
import type { LocalizeKeys } from "../../common/translations/localize";
|
||||
import { computeShownAttributes } from "../../data/entity/entity_attributes";
|
||||
import type { ExtEntityRegistryEntry } from "../../data/entity/entity_registry";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import "../../components/ha-yaml-editor";
|
||||
|
||||
interface DetailsViewParams {
|
||||
entityId: string;
|
||||
}
|
||||
|
||||
interface DetailEntry {
|
||||
translationKey: LocalizeKeys;
|
||||
value: string;
|
||||
}
|
||||
|
||||
@customElement("ha-more-info-details")
|
||||
class HaMoreInfoDetails extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@@ -31,8 +21,6 @@ class HaMoreInfoDetails extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public params?: DetailsViewParams;
|
||||
|
||||
@property({ attribute: false }) public yamlMode = false;
|
||||
|
||||
@state() private _stateObj?: HassEntity;
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
@@ -49,127 +37,60 @@ class HaMoreInfoDetails extends LitElement {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const { stateEntries, attributes, yamlData } = this._getDetailData(
|
||||
this._stateObj
|
||||
const translatedState = this.hass.formatEntityState(this._stateObj);
|
||||
const detailsAttributes = computeShownAttributes(this._stateObj);
|
||||
const detailsAttributeSet = new Set(detailsAttributes);
|
||||
const builtInAttributes = Object.keys(this._stateObj.attributes).filter(
|
||||
(attribute) => !detailsAttributeSet.has(attribute)
|
||||
);
|
||||
const allAttributes = [...detailsAttributes, ...builtInAttributes];
|
||||
|
||||
return html`
|
||||
<div class="content">
|
||||
${this.yamlMode
|
||||
? html`<ha-yaml-editor
|
||||
.hass=${this.hass}
|
||||
.value=${yamlData}
|
||||
read-only
|
||||
auto-update
|
||||
></ha-yaml-editor>`
|
||||
: html`
|
||||
<section class="section">
|
||||
<h2 class="section-title">
|
||||
${this.hass.localize(
|
||||
"ui.components.entity.entity-state-picker.state"
|
||||
)}
|
||||
</h2>
|
||||
<ha-card>
|
||||
<div class="card-content">
|
||||
<div class="data-group">
|
||||
${stateEntries.map(
|
||||
(entry) =>
|
||||
html`<div class="data-entry">
|
||||
<div class="key">
|
||||
${this.hass.localize(entry.translationKey)}
|
||||
</div>
|
||||
<div class="value">${entry.value}</div>
|
||||
</div>`
|
||||
)}
|
||||
</div>
|
||||
<section class="section">
|
||||
<h2 class="section-title">
|
||||
${this.hass.localize(
|
||||
"ui.components.entity.entity-state-picker.state"
|
||||
)}
|
||||
</h2>
|
||||
<ha-card>
|
||||
<div class="card-content">
|
||||
<div class="attribute-group">
|
||||
<div class="data-entry">
|
||||
<div class="key">
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.translated"
|
||||
)}
|
||||
</div>
|
||||
</ha-card>
|
||||
</section>
|
||||
<div class="value">${translatedState}</div>
|
||||
</div>
|
||||
<div class="data-entry">
|
||||
<div class="key">
|
||||
${this.hass.localize("ui.dialogs.more_info_control.raw")}
|
||||
</div>
|
||||
<div class="value">${this._stateObj.state}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ha-card>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2 class="section-title">
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.attributes"
|
||||
)}
|
||||
</h2>
|
||||
<ha-card>
|
||||
<div class="card-content">
|
||||
<div class="data-group">
|
||||
${this._renderAttributes(attributes)}
|
||||
</div>
|
||||
</div>
|
||||
</ha-card>
|
||||
</section>
|
||||
`}
|
||||
<section class="section">
|
||||
<h2 class="section-title">
|
||||
${this.hass.localize("ui.dialogs.more_info_control.attributes")}
|
||||
</h2>
|
||||
<ha-card>
|
||||
<div class="card-content">
|
||||
<div class="attribute-group">
|
||||
${this._renderAttributes(allAttributes)}
|
||||
</div>
|
||||
</div>
|
||||
</ha-card>
|
||||
</section>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _getDetailData = memoizeOne(
|
||||
(
|
||||
stateObj: HassEntity
|
||||
): {
|
||||
stateEntries: DetailEntry[];
|
||||
attributes: string[];
|
||||
yamlData: {
|
||||
state: {
|
||||
translated: string;
|
||||
raw: string;
|
||||
last_changed: string;
|
||||
last_updated: string;
|
||||
};
|
||||
attributes: Record<string, string>;
|
||||
};
|
||||
} => {
|
||||
const translatedState = this.hass.formatEntityState(stateObj);
|
||||
|
||||
const detailsAttributes = computeShownAttributes(stateObj);
|
||||
const detailsAttributeSet = new Set(detailsAttributes);
|
||||
const builtInAttributes = Object.keys(stateObj.attributes).filter(
|
||||
(attribute) => !detailsAttributeSet.has(attribute)
|
||||
);
|
||||
|
||||
return {
|
||||
stateEntries: [
|
||||
{
|
||||
translationKey: "ui.dialogs.more_info_control.translated",
|
||||
value: translatedState,
|
||||
},
|
||||
{
|
||||
translationKey: "ui.dialogs.more_info_control.raw",
|
||||
value: stateObj.state,
|
||||
},
|
||||
{
|
||||
translationKey: "ui.dialogs.more_info_control.last_changed",
|
||||
value: this._formatTimestamp(stateObj.last_changed),
|
||||
},
|
||||
{
|
||||
translationKey: "ui.dialogs.more_info_control.last_updated",
|
||||
value: this._formatTimestamp(stateObj.last_updated),
|
||||
},
|
||||
],
|
||||
attributes: [...detailsAttributes, ...builtInAttributes],
|
||||
yamlData: {
|
||||
state: {
|
||||
translated: translatedState,
|
||||
raw: stateObj.state,
|
||||
last_changed: stateObj.last_changed,
|
||||
last_updated: stateObj.last_updated,
|
||||
},
|
||||
attributes: stateObj.attributes,
|
||||
},
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
private _formatTimestamp(value: string): string {
|
||||
const date = new Date(value);
|
||||
|
||||
return checkValidDate(date)
|
||||
? formatDateTimeWithSeconds(date, this.hass.locale, this.hass.config)
|
||||
: value;
|
||||
}
|
||||
|
||||
private _renderAttributes(attributes: string[]) {
|
||||
if (attributes.length === 0) {
|
||||
return html`<div class="empty">
|
||||
@@ -238,7 +159,7 @@ class HaMoreInfoDetails extends LitElement {
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
|
||||
.data-group .data-entry:last-of-type {
|
||||
.attribute-group .data-entry:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
mdiChartBoxOutline,
|
||||
mdiClose,
|
||||
mdiCodeBraces,
|
||||
mdiCogOutline,
|
||||
mdiDevices,
|
||||
mdiDotsVertical,
|
||||
@@ -133,8 +132,6 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
|
||||
|
||||
@state() private _infoEditMode = false;
|
||||
|
||||
@state() private _detailsYamlMode = false;
|
||||
|
||||
@state() private _isEscapeEnabled = true;
|
||||
|
||||
@state() private _sensorNumericDeviceClasses?: string[] = [];
|
||||
@@ -185,7 +182,6 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
|
||||
this._parentEntityIds = [];
|
||||
this._entry = undefined;
|
||||
this._infoEditMode = false;
|
||||
this._detailsYamlMode = false;
|
||||
this._initialView = DEFAULT_VIEW;
|
||||
this._currView = DEFAULT_VIEW;
|
||||
this._childView = undefined;
|
||||
@@ -255,7 +251,6 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
|
||||
private _goBack() {
|
||||
if (this._childView) {
|
||||
this._childView = undefined;
|
||||
this._detailsYamlMode = false;
|
||||
return;
|
||||
}
|
||||
if (this._initialView !== this._currView) {
|
||||
@@ -319,10 +314,6 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
|
||||
this._infoEditMode = !this._infoEditMode;
|
||||
}
|
||||
|
||||
private _toggleDetailsYamlMode() {
|
||||
this._detailsYamlMode = !this._detailsYamlMode;
|
||||
}
|
||||
|
||||
private _handleToggleInfoEditModeEvent(ev) {
|
||||
this._infoEditMode = ev.detail;
|
||||
}
|
||||
@@ -646,18 +637,7 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
|
||||
</ha-dropdown-item>
|
||||
</ha-dropdown>
|
||||
`
|
||||
: this._childView?.viewTag === "ha-more-info-details"
|
||||
? html`
|
||||
<ha-icon-button
|
||||
slot="headerActionItems"
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.toggle_yaml_mode"
|
||||
)}
|
||||
.path=${mdiCodeBraces}
|
||||
@click=${this._toggleDetailsYamlMode}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: nothing}
|
||||
: nothing}
|
||||
<div
|
||||
class=${classMap({
|
||||
"content-wrapper": true,
|
||||
@@ -683,7 +663,6 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
|
||||
hass: this.hass,
|
||||
entry: this._entry,
|
||||
params: this._childView.viewParams,
|
||||
yamlMode: this._detailsYamlMode,
|
||||
})}
|
||||
</div>
|
||||
`
|
||||
@@ -752,7 +731,6 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
|
||||
if (changedProps.has("_currView")) {
|
||||
this._childView = undefined;
|
||||
this._infoEditMode = false;
|
||||
this._detailsYamlMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@ class DialogSystemLogDetail extends LitElement {
|
||||
<ha-dialog
|
||||
.hass=${this.hass}
|
||||
.open=${this._open}
|
||||
width="large"
|
||||
@closed=${this._dialogClosed}
|
||||
>
|
||||
<span slot="headerTitle">${title}</span>
|
||||
|
||||
@@ -143,7 +143,8 @@ class HaConfigRepairs extends LitElement {
|
||||
}
|
||||
} else if (
|
||||
issue.domain === "vacuum" &&
|
||||
issue.translation_key === "segments_changed"
|
||||
(issue.translation_key === "segments_changed" ||
|
||||
issue.translation_key === "segments_mapping_not_configured")
|
||||
) {
|
||||
const data = await fetchRepairsIssueData(
|
||||
this.hass.connection,
|
||||
|
||||
@@ -49,14 +49,6 @@ class HuiClimateFanModesCardFeature
|
||||
|
||||
@state() _currentFanMode?: string;
|
||||
|
||||
private _renderFanModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this._stateObj}
|
||||
attribute="fan_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private get _stateObj() {
|
||||
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||
return undefined;
|
||||
@@ -183,8 +175,14 @@ class HuiClimateFanModesCardFeature
|
||||
.value=${this._currentFanMode}
|
||||
.disabled=${this._stateObj.state === UNAVAILABLE}
|
||||
@wa-select=${this._valueChanged}
|
||||
.options=${options}
|
||||
.renderIcon=${this._renderFanModeIcon}
|
||||
.options=${options.map((option) => ({
|
||||
...option,
|
||||
attributeIcon: {
|
||||
stateObj: stateObj,
|
||||
attribute: "fan_mode",
|
||||
attributeValue: option.value,
|
||||
},
|
||||
}))}
|
||||
><ha-svg-icon slot="icon" .path=${mdiFan}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
`;
|
||||
|
||||
@@ -48,14 +48,6 @@ class HuiClimatePresetModesCardFeature
|
||||
|
||||
@state() _currentPresetMode?: string;
|
||||
|
||||
private _renderPresetModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this._stateObj}
|
||||
attribute="preset_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private get _stateObj() {
|
||||
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||
return undefined;
|
||||
@@ -187,8 +179,14 @@ class HuiClimatePresetModesCardFeature
|
||||
.value=${this._currentPresetMode}
|
||||
.disabled=${this._stateObj.state === UNAVAILABLE}
|
||||
@wa-select=${this._valueChanged}
|
||||
.options=${options}
|
||||
.renderIcon=${this._renderPresetModeIcon}
|
||||
.options=${options.map((option) => ({
|
||||
...option,
|
||||
attributeIcon: {
|
||||
stateObj: stateObj,
|
||||
attribute: "preset_mode",
|
||||
attributeValue: option.value,
|
||||
},
|
||||
}))}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
|
||||
@@ -48,14 +48,6 @@ class HuiClimateSwingHorizontalModesCardFeature
|
||||
|
||||
@state() _currentSwingHorizontalMode?: string;
|
||||
|
||||
private _renderSwingHorizontalModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this._stateObj}
|
||||
attribute="swing_horizontal_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private get _stateObj() {
|
||||
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||
return undefined;
|
||||
@@ -195,8 +187,14 @@ class HuiClimateSwingHorizontalModesCardFeature
|
||||
.value=${this._currentSwingHorizontalMode}
|
||||
.disabled=${this._stateObj.state === UNAVAILABLE}
|
||||
@wa-select=${this._valueChanged}
|
||||
.options=${options}
|
||||
.renderIcon=${this._renderSwingHorizontalModeIcon}
|
||||
.options=${options.map((option) => ({
|
||||
...option,
|
||||
attributeIcon: {
|
||||
stateObj: stateObj,
|
||||
attribute: "swing_horizontal_mode",
|
||||
attributeValue: option.value,
|
||||
},
|
||||
}))}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiArrowOscillating}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
|
||||
@@ -48,14 +48,6 @@ class HuiClimateSwingModesCardFeature
|
||||
|
||||
@state() _currentSwingMode?: string;
|
||||
|
||||
private _renderSwingModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this._stateObj}
|
||||
attribute="swing_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private get _stateObj() {
|
||||
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||
return undefined;
|
||||
@@ -187,8 +179,14 @@ class HuiClimateSwingModesCardFeature
|
||||
.value=${this._currentSwingMode}
|
||||
.disabled=${this._stateObj.state === UNAVAILABLE}
|
||||
@wa-select=${this._valueChanged}
|
||||
.options=${options}
|
||||
.renderIcon=${this._renderSwingModeIcon}
|
||||
.options=${options.map((option) => ({
|
||||
...option,
|
||||
attributeIcon: {
|
||||
stateObj,
|
||||
attribute: "swing_mode",
|
||||
attributeValue: option.value,
|
||||
},
|
||||
}))}
|
||||
><ha-svg-icon slot="icon" .path=${mdiArrowOscillating}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
`;
|
||||
|
||||
@@ -47,14 +47,6 @@ class HuiFanPresetModesCardFeature
|
||||
|
||||
@state() _currentPresetMode?: string;
|
||||
|
||||
private _renderPresetModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this._stateObj}
|
||||
attribute="preset_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private get _stateObj() {
|
||||
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||
return undefined;
|
||||
@@ -181,8 +173,14 @@ class HuiFanPresetModesCardFeature
|
||||
.value=${this._currentPresetMode}
|
||||
.disabled=${this._stateObj.state === UNAVAILABLE}
|
||||
@wa-select=${this._valueChanged}
|
||||
.options=${options}
|
||||
.renderIcon=${this._renderPresetModeIcon}
|
||||
.options=${options.map((option) => ({
|
||||
...option,
|
||||
attributeIcon: {
|
||||
stateObj: stateObj,
|
||||
attribute: "preset_mode",
|
||||
attributeValue: option.value,
|
||||
},
|
||||
}))}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
|
||||
@@ -48,14 +48,6 @@ class HuiHumidifierModesCardFeature
|
||||
|
||||
@state() _currentMode?: string;
|
||||
|
||||
private _renderModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this._stateObj}
|
||||
attribute="mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private get _stateObj() {
|
||||
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||
return undefined;
|
||||
@@ -182,8 +174,14 @@ class HuiHumidifierModesCardFeature
|
||||
.value=${this._currentMode}
|
||||
.disabled=${this._stateObj.state === UNAVAILABLE}
|
||||
@wa-select=${this._valueChanged}
|
||||
.options=${options}
|
||||
.renderIcon=${this._renderModeIcon}
|
||||
.options=${options.map((option) => ({
|
||||
...option,
|
||||
attributeIcon: {
|
||||
stateObj,
|
||||
attribute: "mode",
|
||||
attributeValue: option.value,
|
||||
},
|
||||
}))}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
|
||||
@@ -49,14 +49,6 @@ class HuiWaterHeaterOperationModeCardFeature
|
||||
|
||||
@state() _currentOperationMode?: OperationMode;
|
||||
|
||||
private _renderOperationModeIcon = (value: string) =>
|
||||
html`<ha-attribute-icon
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this._stateObj}
|
||||
attribute="operation_mode"
|
||||
.attributeValue=${value}
|
||||
></ha-attribute-icon>`;
|
||||
|
||||
private get _stateObj() {
|
||||
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||
return undefined;
|
||||
@@ -161,8 +153,14 @@ class HuiWaterHeaterOperationModeCardFeature
|
||||
.value=${this._currentOperationMode}
|
||||
.disabled=${this._stateObj.state === UNAVAILABLE}
|
||||
@wa-select=${this._valueChanged}
|
||||
.options=${options}
|
||||
.renderIcon=${this._renderOperationModeIcon}
|
||||
.options=${options.map((option) => ({
|
||||
...option,
|
||||
attributeIcon: {
|
||||
stateObj: this._stateObj,
|
||||
attribute: "operation_mode",
|
||||
attributeValue: option.value,
|
||||
},
|
||||
}))}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiWaterBoiler}></ha-svg-icon>
|
||||
</ha-control-select-menu>
|
||||
|
||||
@@ -218,9 +218,7 @@ function formatTooltip(
|
||||
}
|
||||
// when comparing the first value is offset to match the main period
|
||||
// and the real date is in the third value
|
||||
// find the first param with the real date to handle gap-filled entries
|
||||
const origDate = params.find((p) => p.value?.[2] != null)?.value?.[2];
|
||||
const date = new Date(origDate ?? params[0].value?.[0]);
|
||||
const date = new Date(params[0].value?.[2] ?? params[0].value?.[0]);
|
||||
let period: string;
|
||||
|
||||
if (suggestedPeriod === "month") {
|
||||
|
||||
@@ -6,7 +6,6 @@ import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import "../../../components/ha-spinner";
|
||||
import type { HistoryStates } from "../../../data/history";
|
||||
import { subscribeHistoryStatesTimeWindow } from "../../../data/history";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { findEntities } from "../common/find-entities";
|
||||
@@ -67,8 +66,6 @@ export class HuiGraphHeaderFooter
|
||||
|
||||
private _error?: string;
|
||||
|
||||
private _history?: HistoryStates;
|
||||
|
||||
private _interval?: number;
|
||||
|
||||
private _subscribed?: Promise<(() => Promise<void>) | undefined>;
|
||||
@@ -164,8 +161,24 @@ export class HuiGraphHeaderFooter
|
||||
// Message came in before we had a chance to unload
|
||||
return;
|
||||
}
|
||||
this._history = combinedHistory;
|
||||
this._computeCoordinates();
|
||||
const width = this.clientWidth || this.offsetWidth;
|
||||
// sample to 1 point per hour or 1 point per 5 pixels
|
||||
const maxDetails = Math.max(
|
||||
10,
|
||||
this._config.detail! > 1
|
||||
? Math.max(width / 5, this._config.hours_to_show!)
|
||||
: this._config.hours_to_show!
|
||||
);
|
||||
const useMean = this._config.detail !== 2;
|
||||
const { points } = coordinatesMinimalResponseCompressedState(
|
||||
combinedHistory[this._config.entity],
|
||||
width,
|
||||
width / 5,
|
||||
maxDetails,
|
||||
{ minY: this._config.limits?.min, maxY: this._config.limits?.max },
|
||||
useMean
|
||||
);
|
||||
this._coordinates = points;
|
||||
},
|
||||
this._config.hours_to_show!,
|
||||
[this._config.entity]
|
||||
@@ -177,63 +190,10 @@ export class HuiGraphHeaderFooter
|
||||
this._setRedrawTimer();
|
||||
}
|
||||
|
||||
private _computeCoordinates() {
|
||||
if (!this._history || !this._config) {
|
||||
return;
|
||||
}
|
||||
const entityHistory = this._history[this._config.entity];
|
||||
if (!entityHistory?.length) {
|
||||
return;
|
||||
}
|
||||
const width = this.clientWidth || this.offsetWidth;
|
||||
// sample to 1 point per hour or 1 point per 5 pixels
|
||||
const maxDetails = Math.max(
|
||||
10,
|
||||
this._config.detail! > 1
|
||||
? Math.max(width / 5, this._config.hours_to_show!)
|
||||
: this._config.hours_to_show!
|
||||
);
|
||||
const useMean = this._config.detail !== 2;
|
||||
const { points } = coordinatesMinimalResponseCompressedState(
|
||||
entityHistory,
|
||||
width,
|
||||
width / 5,
|
||||
maxDetails,
|
||||
{ minY: this._config.limits?.min, maxY: this._config.limits?.max },
|
||||
useMean
|
||||
);
|
||||
this._coordinates = points;
|
||||
}
|
||||
|
||||
private _redrawGraph() {
|
||||
if (!this._history || !this._config?.hours_to_show) {
|
||||
return;
|
||||
if (this._coordinates) {
|
||||
this._coordinates = [...this._coordinates];
|
||||
}
|
||||
const entityId = this._config.entity;
|
||||
const entityHistory = this._history[entityId];
|
||||
if (entityHistory?.length) {
|
||||
const purgeBeforeTimestamp =
|
||||
(Date.now() - this._config.hours_to_show * 60 * 60 * 1000) / 1000;
|
||||
let purgedHistory = entityHistory.filter(
|
||||
(entry) => entry.lu >= purgeBeforeTimestamp
|
||||
);
|
||||
if (purgedHistory.length !== entityHistory.length) {
|
||||
if (
|
||||
!purgedHistory.length ||
|
||||
purgedHistory[0].lu !== purgeBeforeTimestamp
|
||||
) {
|
||||
// Preserve the last expired state as the start boundary
|
||||
const lastExpiredState = {
|
||||
...entityHistory[entityHistory.length - purgedHistory.length - 1],
|
||||
};
|
||||
lastExpiredState.lu = purgeBeforeTimestamp;
|
||||
delete lastExpiredState.lc;
|
||||
purgedHistory = [lastExpiredState, ...purgedHistory];
|
||||
}
|
||||
this._history = { ...this._history, [entityId]: purgedHistory };
|
||||
}
|
||||
}
|
||||
this._computeCoordinates();
|
||||
}
|
||||
|
||||
private _setRedrawTimer() {
|
||||
@@ -251,7 +211,6 @@ export class HuiGraphHeaderFooter
|
||||
this._subscribed.then((unsub) => unsub?.());
|
||||
this._subscribed = undefined;
|
||||
}
|
||||
this._history = undefined;
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
|
||||
@@ -1485,8 +1485,6 @@ class HUIRoot extends LitElement {
|
||||
padding-inline-start: var(--safe-area-inset-left);
|
||||
}
|
||||
hui-view-container > * {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@@ -461,7 +461,6 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
--column-min-width: var(--ha-view-sections-column-min-width, 320px);
|
||||
--top-margin: var(--ha-view-sections-extra-top-margin, 80px);
|
||||
display: block;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
@@ -471,9 +470,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: calc(100% - 2 * var(--row-gap));
|
||||
display: block;
|
||||
padding: var(--row-gap) var(--column-gap);
|
||||
box-sizing: content-box;
|
||||
margin: 0 auto;
|
||||
@@ -506,7 +503,6 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
gap: var(--row-gap) var(--column-gap);
|
||||
padding: var(--row-gap) 0;
|
||||
align-items: flex-start;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.wrapper.has-sidebar .container {
|
||||
|
||||
@@ -1524,7 +1524,6 @@
|
||||
"settings": "Settings",
|
||||
"edit": "Edit entity",
|
||||
"details": "Details",
|
||||
"toggle_yaml_mode": "Toggle YAML mode",
|
||||
"translated": "Translated",
|
||||
"raw": "Raw",
|
||||
"back_to_info": "Back to info",
|
||||
|
||||
61
yarn.lock
61
yarn.lock
@@ -1250,9 +1250,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@codemirror/language@npm:6.12.2, @codemirror/language@npm:^6.0.0":
|
||||
version: 6.12.2
|
||||
resolution: "@codemirror/language@npm:6.12.2"
|
||||
"@codemirror/language@npm:6.12.1, @codemirror/language@npm:^6.0.0":
|
||||
version: 6.12.1
|
||||
resolution: "@codemirror/language@npm:6.12.1"
|
||||
dependencies:
|
||||
"@codemirror/state": "npm:^6.0.0"
|
||||
"@codemirror/view": "npm:^6.23.0"
|
||||
@@ -1260,7 +1260,7 @@ __metadata:
|
||||
"@lezer/highlight": "npm:^1.0.0"
|
||||
"@lezer/lr": "npm:^1.0.0"
|
||||
style-mod: "npm:^4.0.0"
|
||||
checksum: 10/9afc704e17cad4782b68ad02869503a27103c4c3ac6927d2ffa3c6decfad627ade40b0ed78d1d6e941b2e879a7a79bda0d573e58604f3923f9e1f3311108ec36
|
||||
checksum: 10/a24c3512d38cbb2a20cc3128da0eea074b4a6102b6a5a041b3dfd5e67638fb61dcdf4743ed87708db882df5d72a84d9f891aac6fa68447830989c8e2d9ffa2ba
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2001,34 +2001,33 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@html-eslint/eslint-plugin@npm:0.57.1":
|
||||
version: 0.57.1
|
||||
resolution: "@html-eslint/eslint-plugin@npm:0.57.1"
|
||||
"@html-eslint/eslint-plugin@npm:0.57.0":
|
||||
version: 0.57.0
|
||||
resolution: "@html-eslint/eslint-plugin@npm:0.57.0"
|
||||
dependencies:
|
||||
"@eslint/plugin-kit": "npm:^0.4.1"
|
||||
"@html-eslint/core": "npm:^0.57.0"
|
||||
"@html-eslint/parser": "npm:^0.57.1"
|
||||
"@html-eslint/parser": "npm:^0.57.0"
|
||||
"@html-eslint/template-parser": "npm:^0.57.0"
|
||||
"@html-eslint/template-syntax-parser": "npm:^0.57.0"
|
||||
"@html-eslint/types": "npm:^0.57.0"
|
||||
"@rviscomi/capo.js": "npm:^2.1.0"
|
||||
html-standard: "npm:^0.0.13"
|
||||
peerDependencies:
|
||||
eslint: ">=8.0.0 || ^10.0.0-0"
|
||||
checksum: 10/21a923a1ee8efb02f01c015345a23b38cd0a9e98c4f3fa07d79afe1f8e9f26651e0a9d6983b2f9cfae76be71c14f3224fd64433612535c1e04e3c9b440e46245
|
||||
checksum: 10/34cf11eaab3c07436c9c8b2896ed331c3ba5d591db5d8a8ff79d19b174e6e090323eb71e1368ad93d2afa945d4740749c599436a03be1195d4e4a4b0d3d9e9b6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@html-eslint/parser@npm:^0.57.1":
|
||||
version: 0.57.1
|
||||
resolution: "@html-eslint/parser@npm:0.57.1"
|
||||
"@html-eslint/parser@npm:^0.57.0":
|
||||
version: 0.57.0
|
||||
resolution: "@html-eslint/parser@npm:0.57.0"
|
||||
dependencies:
|
||||
"@eslint/css-tree": "npm:^3.6.9"
|
||||
"@html-eslint/template-syntax-parser": "npm:^0.57.0"
|
||||
"@html-eslint/types": "npm:^0.57.0"
|
||||
css-tree: "npm:^3.1.0"
|
||||
es-html-parser: "npm:0.3.1"
|
||||
checksum: 10/3e148f0bf83600e5b931938dc02d01e805c275b0534fad0adc8ac68ceb37220896c007b1d33ebc4347cb59ab35d1cc3c57207ff798f08d2327d92abf1c88e72b
|
||||
checksum: 10/d742a26ef8122eab82e35ab27de6fe40cd45d2ac59ade9bed9d16df0da3cd18425c7892fedd245b9d60da2a4fbfb8c6afe05b1b6415033ab8fad996b94be020e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -6087,12 +6086,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"barcode-detector@npm:3.1.0":
|
||||
version: 3.1.0
|
||||
resolution: "barcode-detector@npm:3.1.0"
|
||||
"barcode-detector@npm:3.0.8":
|
||||
version: 3.0.8
|
||||
resolution: "barcode-detector@npm:3.0.8"
|
||||
dependencies:
|
||||
zxing-wasm: "npm:3.0.0"
|
||||
checksum: 10/60767161081b827e290b60bb3416999dee616bab39291ee55565df9b72d59f0bbbf511fd3bb85db18eee7c0ad9acf1ff90359cdb21e10f80793acd0105c86a1d
|
||||
zxing-wasm: "npm:2.2.4"
|
||||
checksum: 10/7de6225f659c69a0f4101d080a9e0812f2404c485fa2406424b8b13eaff274f6e7405c94de24827a09def52c32a63b19b9c9fba61c5274b074d558f696ec1684
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -9178,7 +9177,7 @@ __metadata:
|
||||
"@bundle-stats/plugin-webpack-filter": "npm:4.21.10"
|
||||
"@codemirror/autocomplete": "npm:6.20.0"
|
||||
"@codemirror/commands": "npm:6.10.2"
|
||||
"@codemirror/language": "npm:6.12.2"
|
||||
"@codemirror/language": "npm:6.12.1"
|
||||
"@codemirror/legacy-modes": "npm:6.5.2"
|
||||
"@codemirror/search": "npm:6.6.0"
|
||||
"@codemirror/state": "npm:6.5.4"
|
||||
@@ -9201,7 +9200,7 @@ __metadata:
|
||||
"@fullcalendar/luxon3": "npm:6.1.20"
|
||||
"@fullcalendar/timegrid": "npm:6.1.20"
|
||||
"@home-assistant/webawesome": "npm:3.2.1-ha.3"
|
||||
"@html-eslint/eslint-plugin": "npm:0.57.1"
|
||||
"@html-eslint/eslint-plugin": "npm:0.57.0"
|
||||
"@lezer/highlight": "npm:1.2.3"
|
||||
"@lit-labs/motion": "npm:1.1.0"
|
||||
"@lit-labs/observers": "npm:2.1.0"
|
||||
@@ -9269,7 +9268,7 @@ __metadata:
|
||||
app-datepicker: "npm:5.1.1"
|
||||
babel-loader: "npm:10.0.0"
|
||||
babel-plugin-template-html-minifier: "npm:4.1.0"
|
||||
barcode-detector: "npm:3.1.0"
|
||||
barcode-detector: "npm:3.0.8"
|
||||
browserslist-useragent-regexp: "npm:4.1.3"
|
||||
color-name: "npm:2.1.0"
|
||||
comlink: "npm:4.4.2"
|
||||
@@ -14140,12 +14139,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"type-fest@npm:^5.4.4":
|
||||
version: 5.4.4
|
||||
resolution: "type-fest@npm:5.4.4"
|
||||
"type-fest@npm:^5.2.0":
|
||||
version: 5.4.1
|
||||
resolution: "type-fest@npm:5.4.1"
|
||||
dependencies:
|
||||
tagged-tag: "npm:^1.0.0"
|
||||
checksum: 10/0bbdca645f95740587f389a2d712fe8d5e9ab7d13e74aac97cf396112510abcaab6b75fd90d65172bc13b02fdfc827e6a871322cc9c1c1a5a2754d9ab264c6f5
|
||||
checksum: 10/be7d4749e1e5cf2e2c9904fa1aaf9da5eef6c47c130881bf93bfd5a670b2ab59c5502466768e42c521281056a2375b1617176a75cf6c52b575f4bbabbd450b21
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -15704,14 +15703,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"zxing-wasm@npm:3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "zxing-wasm@npm:3.0.0"
|
||||
"zxing-wasm@npm:2.2.4":
|
||||
version: 2.2.4
|
||||
resolution: "zxing-wasm@npm:2.2.4"
|
||||
dependencies:
|
||||
"@types/emscripten": "npm:^1.41.5"
|
||||
type-fest: "npm:^5.4.4"
|
||||
type-fest: "npm:^5.2.0"
|
||||
peerDependencies:
|
||||
"@types/emscripten": ">=1.39.6"
|
||||
checksum: 10/0acf04829acf8f3987173af011784642792fc877c7765f79222fe33efff8af09fbf95bf5d590d2490ae39ec411e6c4de06ea24e96d4eb48189b9d06f7502eaa2
|
||||
checksum: 10/e5928cbb066c854c970cbf724e978e502c3469d69de2469bd37d1f6ab8f5d2a2acdbaa9dea32d35cfc058e2b482e29a9c4f12161d9df3e1e952c30dda3a96d8c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
Reference in New Issue
Block a user