mirror of
https://github.com/home-assistant/frontend.git
synced 2025-10-02 00:09:40 +00:00
Compare commits
101 Commits
config-lab
...
ha-dialog-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
66d86620de | ||
![]() |
4249035dc7 | ||
![]() |
8502d073fa | ||
![]() |
b0568fac8b | ||
![]() |
ed44c905e6 | ||
![]() |
f94343c5f1 | ||
![]() |
6c2d802b83 | ||
![]() |
c8736bca0e | ||
![]() |
546b52f89a | ||
![]() |
7c1c0b6a4a | ||
![]() |
d8abb8ea7b | ||
![]() |
699da04965 | ||
![]() |
fe8c655cef | ||
![]() |
2f9754446d | ||
![]() |
3d241084db | ||
![]() |
8c8910dd35 | ||
![]() |
21449842c3 | ||
![]() |
a182d566df | ||
![]() |
5d42740d92 | ||
![]() |
eaed098256 | ||
![]() |
b15262ce83 | ||
![]() |
ad48a0c4b0 | ||
![]() |
20ad9054ce | ||
![]() |
788447ebe7 | ||
![]() |
847e8c14e0 | ||
![]() |
94e756bd79 | ||
![]() |
065069f21e | ||
![]() |
c72c1e66f5 | ||
![]() |
6470ddbf5a | ||
![]() |
e736d56ff3 | ||
![]() |
bb6d5add9a | ||
![]() |
f401dce7c7 | ||
![]() |
70a417a51a | ||
![]() |
213b53b596 | ||
![]() |
228362b836 | ||
![]() |
0a64af26eb | ||
![]() |
76bbd1f51c | ||
![]() |
1c82e8b316 | ||
![]() |
7f438b57b7 | ||
![]() |
2d09edd8d2 | ||
![]() |
b2bb71d7f8 | ||
![]() |
1e60e1fb9c | ||
![]() |
1df53fe23d | ||
![]() |
3b66db5631 | ||
![]() |
dc772ebe85 | ||
![]() |
0337f68986 | ||
![]() |
77997c7382 | ||
![]() |
6fc69df64b | ||
![]() |
77a0e16f4e | ||
![]() |
717be78457 | ||
![]() |
d8638983d7 | ||
![]() |
d47e181607 | ||
![]() |
39a5249406 | ||
![]() |
525cfd1929 | ||
![]() |
4db9f2652c | ||
![]() |
a994f21acf | ||
![]() |
f7499acfb5 | ||
![]() |
a32c6f956b | ||
![]() |
9b95f87f73 | ||
![]() |
892a09ecd5 | ||
![]() |
4671074cfd | ||
![]() |
236d469f7d | ||
![]() |
ec7056606b | ||
![]() |
677020d4cd | ||
![]() |
7bf7b9c52f | ||
![]() |
a9241a8009 | ||
![]() |
e84f83d5ec | ||
![]() |
0d73d3f1f7 | ||
![]() |
d48a08df40 | ||
![]() |
e2574e99bf | ||
![]() |
8a276c9b6a | ||
![]() |
50843ba43b | ||
![]() |
462277b61b | ||
![]() |
d8dd7fa03f | ||
![]() |
9996655b21 | ||
![]() |
0344ba31c1 | ||
![]() |
b912bfec61 | ||
![]() |
7e16834c22 | ||
![]() |
3076365819 | ||
![]() |
58e623c86c | ||
![]() |
9cb6f762b6 | ||
![]() |
93d8f7f87b | ||
![]() |
9ad0c6000e | ||
![]() |
e7c3895745 | ||
![]() |
5f93224055 | ||
![]() |
a38811ff57 | ||
![]() |
87df38a969 | ||
![]() |
e670df2c68 | ||
![]() |
065e071cc3 | ||
![]() |
d2ae3c6867 | ||
![]() |
405eb5f870 | ||
![]() |
994c1b5751 | ||
![]() |
6823c647b6 | ||
![]() |
866b478dc0 | ||
![]() |
d746dc5752 | ||
![]() |
5f53e1e71c | ||
![]() |
3da82df093 | ||
![]() |
4cedfffb71 | ||
![]() |
1e1514e7da | ||
![]() |
60e07075bc | ||
![]() |
c998086474 |
@@ -52,7 +52,7 @@
|
||||
"@fullcalendar/list": "6.1.19",
|
||||
"@fullcalendar/luxon3": "6.1.19",
|
||||
"@fullcalendar/timegrid": "6.1.19",
|
||||
"@home-assistant/webawesome": "3.0.0-beta.4.ha.3",
|
||||
"@home-assistant/webawesome": "3.0.0-beta.6.ha.0",
|
||||
"@lezer/highlight": "1.2.1",
|
||||
"@lit-labs/motion": "1.0.9",
|
||||
"@lit-labs/observers": "2.0.6",
|
||||
|
7
src/common/dom/has-slot-content.ts
Normal file
7
src/common/dom/has-slot-content.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Check if a slot has any assigned content
|
||||
* @param slot - The HTMLSlotElement to check
|
||||
* @returns true if the slot has any assigned nodes
|
||||
*/
|
||||
export const hasSlotContent = (slot: HTMLSlotElement | null): boolean =>
|
||||
slot ? slot.assignedNodes({ flatten: true }).length > 0 : false;
|
@@ -586,15 +586,19 @@ export class HaChartBase extends LitElement {
|
||||
const isMobile = window.matchMedia(
|
||||
"all and (max-width: 450px), all and (max-height: 500px)"
|
||||
).matches;
|
||||
if (isMobile && options.tooltip) {
|
||||
// mobile charts are full width so we need to confine the tooltip to the chart
|
||||
if (options.tooltip) {
|
||||
const tooltips = Array.isArray(options.tooltip)
|
||||
? options.tooltip
|
||||
: [options.tooltip];
|
||||
tooltips.forEach((tooltip) => {
|
||||
tooltip.confine = true;
|
||||
tooltip.appendTo = undefined;
|
||||
tooltip.triggerOn = "click";
|
||||
// Tooltips should render within the component, not in the body of the html
|
||||
tooltip.appendTo = () =>
|
||||
this.renderRoot.querySelector(".chart-container") as HTMLElement;
|
||||
// Mobile charts are full width so we need to confine the tooltip to the chart
|
||||
if (isMobile) {
|
||||
tooltip.confine = true;
|
||||
tooltip.triggerOn = "click";
|
||||
}
|
||||
});
|
||||
options.tooltip = tooltips;
|
||||
}
|
||||
|
@@ -112,7 +112,7 @@ export class HaEntityToggle extends LitElement {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
const stateDomain = computeStateDomain(this.stateObj);
|
||||
let serviceDomain;
|
||||
let service;
|
||||
|
52
src/components/ha-dialog-footer.ts
Normal file
52
src/components/ha-dialog-footer.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement } from "lit/decorators";
|
||||
|
||||
/**
|
||||
* Home Assistant dialog footer component
|
||||
*
|
||||
* @element ha-dialog-footer
|
||||
* @extends {LitElement}
|
||||
*
|
||||
* @summary
|
||||
* A simple footer container for dialog actions,
|
||||
* typically used as the `footer` slot in `ha-wa-dialog`.
|
||||
*
|
||||
* @slot primaryAction - Primary action button(s), aligned to the end.
|
||||
* @slot secondaryAction - Secondary action button(s), placed before the primary action.
|
||||
*
|
||||
* @remarks
|
||||
* **Button Styling Guidance:**
|
||||
* - `primaryAction` slot: Use `variant="accent"`
|
||||
* - `secondaryAction` slot: Use `variant="plain"`
|
||||
*/
|
||||
@customElement("ha-dialog-footer")
|
||||
export class HaDialogFooter extends LitElement {
|
||||
protected render() {
|
||||
return html`
|
||||
<footer class="footer">
|
||||
<slot name="secondaryAction"></slot>
|
||||
<slot name="primaryAction"></slot>
|
||||
</footer>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
.footer {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-dialog-footer": HaDialogFooter;
|
||||
}
|
||||
}
|
@@ -1,22 +1,47 @@
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement } from "lit/decorators";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { hasSlotContent } from "../common/dom/has-slot-content";
|
||||
|
||||
@customElement("ha-dialog-header")
|
||||
export class HaDialogHeader extends LitElement {
|
||||
@property({ type: String, attribute: "subtitle-position" })
|
||||
public subtitlePosition: "above" | "below" = "below";
|
||||
|
||||
@state()
|
||||
private _hasSubtitle = false;
|
||||
|
||||
@query('slot[name="subtitle"]')
|
||||
private _subtitleSlot!: HTMLSlotElement;
|
||||
|
||||
private _checkSubtitleContent() {
|
||||
this._hasSubtitle = hasSlotContent(this._subtitleSlot);
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const titleSlot = html`<div class="header-title">
|
||||
<slot name="title"></slot>
|
||||
</div>`;
|
||||
|
||||
const subtitleSlot = html`<div class="header-subtitle">
|
||||
<slot name="subtitle" @slotchange=${this._checkSubtitleContent}></slot>
|
||||
</div>`;
|
||||
|
||||
return html`
|
||||
<header class="header">
|
||||
<div class="header-bar">
|
||||
<div
|
||||
class=${classMap({
|
||||
"header-bar": true,
|
||||
"no-subtitle": !this._hasSubtitle,
|
||||
})}
|
||||
>
|
||||
<section class="header-navigation-icon">
|
||||
<slot name="navigationIcon"></slot>
|
||||
</section>
|
||||
<section class="header-content">
|
||||
<div class="header-title">
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
<div class="header-subtitle">
|
||||
<slot name="subtitle"></slot>
|
||||
</div>
|
||||
${this.subtitlePosition === "above"
|
||||
? html`${subtitleSlot}${titleSlot}`
|
||||
: html`${titleSlot}${subtitleSlot}`}
|
||||
</section>
|
||||
<section class="header-action-items">
|
||||
<slot name="actionItems"></slot>
|
||||
@@ -32,6 +57,7 @@ export class HaDialogHeader extends LitElement {
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
min-height: 48px;
|
||||
}
|
||||
:host([show-border]) {
|
||||
border-bottom: 1px solid
|
||||
@@ -44,6 +70,9 @@ export class HaDialogHeader extends LitElement {
|
||||
padding: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.header-bar.no-subtitle {
|
||||
align-items: center;
|
||||
}
|
||||
.header-content {
|
||||
flex: 1;
|
||||
padding: 10px 4px;
|
||||
@@ -55,11 +84,11 @@ export class HaDialogHeader extends LitElement {
|
||||
.header-title {
|
||||
font-size: var(--ha-font-size-xl);
|
||||
line-height: var(--ha-line-height-condensed);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
}
|
||||
.header-subtitle {
|
||||
font-size: var(--ha-font-size-m);
|
||||
line-height: 20px;
|
||||
line-height: var(--ha-line-height-normal);
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
@media all and (min-width: 450px) and (min-height: 500px) {
|
||||
|
@@ -100,6 +100,8 @@ export class HaDialog extends DialogBase {
|
||||
}
|
||||
.mdc-dialog__container {
|
||||
align-items: var(--vertical-align-dialog, center);
|
||||
padding-top: var(--safe-area-inset-top);
|
||||
padding-bottom: var(--safe-area-inset-bottom);
|
||||
}
|
||||
.mdc-dialog__title {
|
||||
padding: 16px 16px 0 16px;
|
||||
@@ -121,7 +123,11 @@ export class HaDialog extends DialogBase {
|
||||
position: var(--dialog-surface-position, relative);
|
||||
top: var(--dialog-surface-top);
|
||||
margin-top: var(--dialog-surface-margin-top);
|
||||
min-width: var(--mdc-dialog-min-width, 100vw);
|
||||
min-width: calc(
|
||||
var(--mdc-dialog-min-width, 100vw) - var(
|
||||
--safe-area-inset-left
|
||||
) - var(--safe-area-inset-right)
|
||||
);
|
||||
min-height: var(--mdc-dialog-min-height, auto);
|
||||
border-radius: var(--ha-dialog-border-radius, 24px);
|
||||
-webkit-backdrop-filter: var(--ha-dialog-surface-backdrop-filter, none);
|
||||
@@ -138,12 +144,18 @@ export class HaDialog extends DialogBase {
|
||||
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
.mdc-dialog .mdc-dialog__surface {
|
||||
min-height: 100vh;
|
||||
max-height: 100vh;
|
||||
padding-top: var(--safe-area-inset-top);
|
||||
padding-bottom: var(--safe-area-inset-bottom);
|
||||
padding-left: var(--safe-area-inset-left);
|
||||
padding-right: var(--safe-area-inset-right);
|
||||
min-height: calc(
|
||||
100vh - var(--safe-area-inset-top, 0px) - var(
|
||||
--safe-area-inset-bottom,
|
||||
0px
|
||||
)
|
||||
);
|
||||
max-height: calc(
|
||||
100vh - var(--safe-area-inset-top, 0px) - var(
|
||||
--safe-area-inset-bottom,
|
||||
0px
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@ export class HaSwitch extends SwitchBase {
|
||||
super.firstUpdated();
|
||||
this.addEventListener("change", () => {
|
||||
if (this.haptic) {
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
366
src/components/ha-wa-dialog.ts
Normal file
366
src/components/ha-wa-dialog.ts
Normal file
@@ -0,0 +1,366 @@
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import "@home-assistant/webawesome/dist/components/dialog/dialog";
|
||||
import { mdiClose } from "@mdi/js";
|
||||
import "./ha-dialog-header";
|
||||
import "./ha-icon-button";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { haStyleScrollbar } from "../resources/styles";
|
||||
|
||||
export type DialogWidth = "small" | "medium" | "large" | "full";
|
||||
export type DialogWidthOnTitleClick = DialogWidth | "none";
|
||||
|
||||
/**
|
||||
* Home Assistant dialog component
|
||||
*
|
||||
* @element ha-wa-dialog
|
||||
* @extends {LitElement}
|
||||
*
|
||||
* @summary
|
||||
* A stylable dialog built using the `wa-dialog` component, providing a standardized header (ha-dialog-header),
|
||||
* body, and footer (preferably using `ha-dialog-footer`) with slots
|
||||
*
|
||||
* You can open and close the dialog declaratively by using the `data-dialog="close"` attribute.
|
||||
* @see https://webawesome.com/docs/components/dialog/#opening-and-closing-dialogs-declaratively
|
||||
* @see src/dialogs/more-info/ha-more-info-dialog.ts#L366
|
||||
*
|
||||
* @slot heading - Replace the entire header area.
|
||||
* @slot navigationIcon - Leading header action (e.g. close/back button).
|
||||
* @slot title - Header title. Click can toggle width if `width-on-title-click` is not "none".
|
||||
* @slot subtitle - Header subtitle, shown under the title.
|
||||
* @slot actionItems - Trailing header actions (e.g. buttons, menus).
|
||||
* @slot - Dialog content body.
|
||||
* @slot footer - Dialog footer content.
|
||||
*
|
||||
* @csspart dialog - The dialog surface.
|
||||
* @csspart header - The header container.
|
||||
* @csspart body - The scrollable body container.
|
||||
* @csspart footer - The footer container.
|
||||
*
|
||||
* @cssprop --dialog-content-padding - Padding for the dialog content sections. Defaults to 24px.
|
||||
* @cssprop --ha-dialog-show-duration - Show animation duration. Defaults to 200ms.
|
||||
* @cssprop --ha-dialog-hide-duration - Hide animation duration. Defaults to 200ms.
|
||||
* @cssprop --ha-dialog-surface-background - Dialog background color. Defaults to surface.
|
||||
* @cssprop --ha-dialog-border-radius - Border radius of the dialog surface. Defaults to 24px.
|
||||
* @cssprop --dialog-z-index - Z-index for the dialog. Defaults to 8.
|
||||
* @cssprop --dialog-surface-position - CSS position of the dialog surface. Defaults to relative.
|
||||
* @cssprop --dialog-surface-margin-top - Top margin for the dialog surface. Defaults to auto.
|
||||
* @cssprop --ha-dialog-expand-duration - Duration for width transitions when changing width. Defaults to 200ms.
|
||||
*
|
||||
* @attr {boolean} open - Controls the dialog open state.
|
||||
* @attr {("small"|"medium"|"large"|"full")} width - Preferred dialog width preset. Defaults to "medium".
|
||||
* @attr {("none"|"small"|"medium"|"large"|"full")} width-on-title-click - Target width when clicking the title. "none" disables.
|
||||
* @attr {boolean} prevent-scrim-close - Prevents closing the dialog by clicking the scrim/overlay. Defaults to false.
|
||||
* @attr {string} header-title - Header title text when no custom title slot is provided.
|
||||
* @attr {string} header-subtitle - Header subtitle text when no custom subtitle slot is provided.
|
||||
* @attr {("above"|"below")} header-subtitle-position - Position of the subtitle relative to the title. Defaults to "below".
|
||||
* @attr {boolean} flexcontent - Makes the dialog body a flex container for flexible layouts.
|
||||
*
|
||||
* @event opened - Fired when the dialog is shown.
|
||||
* @event closed - Fired after the dialog is hidden.
|
||||
*/
|
||||
@customElement("ha-wa-dialog")
|
||||
export class HaWaDialog extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ type: Boolean, reflect: true })
|
||||
public open = false;
|
||||
|
||||
@property({ type: String, reflect: true, attribute: "width" })
|
||||
public width: DialogWidth = "medium";
|
||||
|
||||
@property({
|
||||
type: String,
|
||||
reflect: true,
|
||||
attribute: "width-on-title-click",
|
||||
})
|
||||
public widthOnTitleClick: DialogWidthOnTitleClick = "none";
|
||||
|
||||
@property({ type: Boolean, reflect: true, attribute: "prevent-scrim-close" })
|
||||
public preventScrimClose = false;
|
||||
|
||||
@property({ type: String, attribute: "header-title" })
|
||||
public headerTitle = "";
|
||||
|
||||
@property({ type: String, attribute: "header-subtitle" })
|
||||
public headerSubtitle = "";
|
||||
|
||||
@property({ type: String, attribute: "header-subtitle-position" })
|
||||
public headerSubtitlePosition: "above" | "below" = "below";
|
||||
|
||||
@property({ type: Boolean, reflect: true, attribute: "flexcontent" })
|
||||
public flexContent = false;
|
||||
|
||||
@state()
|
||||
private _open = false;
|
||||
|
||||
@state()
|
||||
private _sizeChanged = false;
|
||||
|
||||
protected updated(
|
||||
changedProperties: Map<string | number | symbol, unknown>
|
||||
): void {
|
||||
super.updated(changedProperties);
|
||||
|
||||
if (changedProperties.has("open")) {
|
||||
if (this.open) {
|
||||
this._open = this.open;
|
||||
}
|
||||
}
|
||||
|
||||
if (changedProperties.has("width")) {
|
||||
this._sizeChanged = false;
|
||||
}
|
||||
|
||||
this.classList.toggle("size-changed", this._sizeChanged);
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<wa-dialog
|
||||
.open=${this._open}
|
||||
.lightDismiss=${!this.preventScrimClose}
|
||||
without-header
|
||||
@wa-show=${this._handleShow}
|
||||
@wa-after-hide=${this._handleAfterHide}
|
||||
>
|
||||
<slot name="heading">
|
||||
<ha-dialog-header .subtitlePosition=${this.headerSubtitlePosition}>
|
||||
<slot name="navigationIcon" slot="navigationIcon">
|
||||
<ha-icon-button
|
||||
data-dialog="close"
|
||||
.label=${this.hass?.localize("ui.common.close") ?? "Close"}
|
||||
.path=${mdiClose}
|
||||
></ha-icon-button>
|
||||
</slot>
|
||||
<slot name="title" slot="title">
|
||||
<span @click=${this.toggleWidth} class="title">
|
||||
${this.headerTitle}
|
||||
</span>
|
||||
</slot>
|
||||
<slot name="subtitle" slot="subtitle">
|
||||
<span>${this.headerSubtitle}</span>
|
||||
</slot>
|
||||
<slot name="actionItems" slot="actionItems"></slot>
|
||||
</ha-dialog-header>
|
||||
</slot>
|
||||
<div class="body ha-scrollbar">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<slot name="footer" slot="footer"></slot>
|
||||
</wa-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleShow = () => {
|
||||
this._open = true;
|
||||
fireEvent(this, "opened");
|
||||
|
||||
this.updateComplete.then(() => {
|
||||
const focusElement = this.querySelector(
|
||||
"[dialogInitialFocus]"
|
||||
) as HTMLElement;
|
||||
focusElement?.focus();
|
||||
});
|
||||
};
|
||||
|
||||
private _handleAfterHide = () => {
|
||||
this._open = false;
|
||||
fireEvent(this, "closed");
|
||||
};
|
||||
|
||||
public disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this._open = false;
|
||||
}
|
||||
|
||||
public toggleWidth = () => {
|
||||
if (this.widthOnTitleClick === "none") {
|
||||
return;
|
||||
}
|
||||
|
||||
this._sizeChanged = !this._sizeChanged;
|
||||
};
|
||||
|
||||
static styles = [
|
||||
haStyleScrollbar,
|
||||
css`
|
||||
:host([scrolled]) wa-dialog::part(header) {
|
||||
max-width: 100%;
|
||||
border-bottom: 1px solid
|
||||
var(--dialog-scroll-divider-color, var(--divider-color));
|
||||
}
|
||||
|
||||
wa-dialog {
|
||||
--full-width: min(
|
||||
95vw,
|
||||
calc(
|
||||
100vw - var(--safe-area-inset-left, 0px) - var(
|
||||
--safe-area-inset-right,
|
||||
0px
|
||||
)
|
||||
)
|
||||
);
|
||||
--width: min(var(--ha-dialog-width-md, 580px), var(--full-width));
|
||||
--spacing: var(--dialog-content-padding, 24px);
|
||||
--show-duration: var(--ha-dialog-show-duration, 200ms);
|
||||
--hide-duration: var(--ha-dialog-hide-duration, 200ms);
|
||||
--ha-dialog-surface-background: var(
|
||||
--card-background-color,
|
||||
var(--ha-color-surface-default)
|
||||
);
|
||||
--wa-color-surface-raised: var(
|
||||
--ha-dialog-surface-background,
|
||||
var(--card-background-color, var(--ha-color-surface-default))
|
||||
);
|
||||
--wa-panel-border-radius: var(
|
||||
--ha-dialog-border-radius,
|
||||
var(--ha-border-radius-3xl)
|
||||
);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
:host([width="small"]),
|
||||
:host(.size-changed[width-on-title-click="small"]) wa-dialog {
|
||||
--width: min(var(--ha-dialog-width-sm, 320px), var(--full-width));
|
||||
}
|
||||
|
||||
:host([width="large"]),
|
||||
:host(.size-changed[width-on-title-click="large"]) wa-dialog {
|
||||
--width: min(var(--ha-dialog-width-lg, 720px), var(--full-width));
|
||||
}
|
||||
|
||||
:host([width="full"]),
|
||||
:host(.size-changed[width-on-title-click="full"]) wa-dialog {
|
||||
--width: var(--full-width);
|
||||
}
|
||||
|
||||
wa-dialog::part(dialog) {
|
||||
min-width: var(--width, var(--full-width));
|
||||
max-width: var(--width, var(--full-width));
|
||||
max-height: calc(100% - 80px);
|
||||
position: var(--dialog-surface-position, relative);
|
||||
margin-top: var(--dialog-surface-margin-top, auto);
|
||||
transition:
|
||||
min-width var(--ha-dialog-expand-duration, 200ms) ease-in-out,
|
||||
max-width var(--ha-dialog-expand-duration, 200ms) ease-in-out;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
:host {
|
||||
--ha-dialog-border-radius: 0px;
|
||||
}
|
||||
|
||||
wa-dialog {
|
||||
--full-width: 100vw;
|
||||
}
|
||||
|
||||
wa-dialog::part(dialog) {
|
||||
min-height: 100%;
|
||||
padding-top: var(--safe-area-inset-top, 0px);
|
||||
padding-bottom: var(--safe-area-inset-bottom, 0px);
|
||||
padding-left: var(--safe-area-inset-left, 0px);
|
||||
padding-right: var(--safe-area-inset-right, 0px);
|
||||
}
|
||||
}
|
||||
|
||||
wa-dialog::part(header) {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24px 24px 16px 24px;
|
||||
gap: 4px;
|
||||
}
|
||||
:host([has-custom-heading]) wa-dialog::part(header) {
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
wa-dialog::part(close-button),
|
||||
wa-dialog::part(close-button__base) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header-title-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
margin: 0;
|
||||
margin-bottom: 0;
|
||||
color: var(
|
||||
--ha-dialog-header-title-color,
|
||||
var(--ha-color-on-surface-default, var(--primary-text-color))
|
||||
);
|
||||
font-size: var(
|
||||
--ha-dialog-header-title-font-size,
|
||||
var(--ha-font-size-2xl)
|
||||
);
|
||||
line-height: var(
|
||||
--ha-dialog-header-title-line-height,
|
||||
var(--ha-line-height-condensed)
|
||||
);
|
||||
font-weight: var(
|
||||
--ha-dialog-header-title-font-weight,
|
||||
var(--ha-font-weight-normal)
|
||||
);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
wa-dialog::part(body) {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.body {
|
||||
position: var(--dialog-content-position, relative);
|
||||
padding: 0 var(--dialog-content-padding, 24px)
|
||||
var(--dialog-content-padding, 24px)
|
||||
var(--dialog-content-padding, 24px);
|
||||
overflow: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
:host([flexcontent]) .body {
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
wa-dialog::part(footer) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::slotted([slot="footer"]) {
|
||||
display: flex;
|
||||
padding: 12px 16px 16px 16px;
|
||||
gap: 12px;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-wa-dialog": HaWaDialog;
|
||||
}
|
||||
|
||||
interface HASSDomEvents {
|
||||
opened: undefined;
|
||||
closed: undefined;
|
||||
}
|
||||
}
|
@@ -28,6 +28,6 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export const forwardHaptic = (hapticType: HapticType) => {
|
||||
fireEvent(window, "haptic", hapticType);
|
||||
export const forwardHaptic = (node: HTMLElement, hapticType: HapticType) => {
|
||||
fireEvent(node, "haptic", hapticType);
|
||||
};
|
||||
|
@@ -42,7 +42,7 @@ class MoreInfoFan extends LitElement {
|
||||
|
||||
private _toggle = () => {
|
||||
const service = this.stateObj?.state === "on" ? "turn_off" : "turn_on";
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
this.hass.callService("fan", service, {
|
||||
entity_id: this.stateObj!.entity_id,
|
||||
});
|
||||
|
@@ -310,7 +310,7 @@ class MoreInfoLight extends LitElement {
|
||||
|
||||
private _toggle = () => {
|
||||
const service = this.stateObj?.state === "on" ? "turn_off" : "turn_on";
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
this.hass.callService("light", service, {
|
||||
entity_id: this.stateObj!.entity_id,
|
||||
});
|
||||
|
@@ -258,7 +258,10 @@ class MoreInfoMediaPlayer extends LitElement {
|
||||
|
||||
const stateObj = this.stateObj;
|
||||
const controls = computeMediaControls(stateObj, true);
|
||||
const coverUrl = stateObj.attributes.entity_picture || "";
|
||||
const coverUrl =
|
||||
stateObj.attributes.entity_picture_local ||
|
||||
stateObj.attributes.entity_picture ||
|
||||
"";
|
||||
const playerObj = new HassMediaPlayerEntity(this.hass, this.stateObj);
|
||||
|
||||
const position = Math.max(Math.floor(playerObj.currentProgress || 0), 0);
|
||||
|
@@ -28,8 +28,7 @@ import { getEntityEntryContext } from "../../common/entity/context/get_entity_co
|
||||
import { shouldHandleRequestSelectedEvent } from "../../common/mwc/handle-request-selected-event";
|
||||
import { navigate } from "../../common/navigate";
|
||||
import "../../components/ha-button-menu";
|
||||
import "../../components/ha-dialog";
|
||||
import "../../components/ha-dialog-header";
|
||||
import "../../components/ha-wa-dialog";
|
||||
import "../../components/ha-icon-button";
|
||||
import "../../components/ha-icon-button-prev";
|
||||
import "../../components/ha-list-item";
|
||||
@@ -91,8 +90,6 @@ const DEFAULT_VIEW: View = "info";
|
||||
export class MoreInfoDialog extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public large = false;
|
||||
|
||||
@state() private _parentEntityIds: string[] = [];
|
||||
|
||||
@state() private _entityId?: string | null;
|
||||
@@ -124,7 +121,6 @@ export class MoreInfoDialog extends LitElement {
|
||||
this._currView = params.view || DEFAULT_VIEW;
|
||||
this._initialView = params.view || DEFAULT_VIEW;
|
||||
this._childView = undefined;
|
||||
this.large = false;
|
||||
this._loadEntityRegistryEntry();
|
||||
}
|
||||
|
||||
@@ -350,200 +346,201 @@ export class MoreInfoDialog extends LitElement {
|
||||
const title = this._childView?.viewTitle || breadcrumb.pop() || entityId;
|
||||
|
||||
return html`
|
||||
<ha-dialog
|
||||
<ha-wa-dialog
|
||||
open
|
||||
@closed=${this.closeDialog}
|
||||
@opened=${this._handleOpened}
|
||||
.escapeKeyAction=${this._isEscapeEnabled ? undefined : ""}
|
||||
.heading=${title}
|
||||
hideActions
|
||||
.backLabel=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.back_to_info"
|
||||
)}
|
||||
.headerTitle=${title}
|
||||
.preventScrimClose=${!this._isEscapeEnabled}
|
||||
width-on-title-click="full"
|
||||
flexContent
|
||||
>
|
||||
<ha-dialog-header slot="heading">
|
||||
${showCloseIcon
|
||||
? html`
|
||||
<ha-icon-button
|
||||
slot="navigationIcon"
|
||||
dialogAction="cancel"
|
||||
.label=${this.hass.localize("ui.common.close")}
|
||||
.path=${mdiClose}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: html`
|
||||
<ha-icon-button-prev
|
||||
slot="navigationIcon"
|
||||
@click=${this._goBack}
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.back_to_info"
|
||||
)}
|
||||
></ha-icon-button-prev>
|
||||
`}
|
||||
<span slot="title" @click=${this._enlarge} class="title">
|
||||
${breadcrumb.length > 0
|
||||
? !__DEMO__ && isAdmin
|
||||
? html`
|
||||
<button
|
||||
class="breadcrumb"
|
||||
@click=${this._breadcrumbClick}
|
||||
aria-label=${breadcrumb.join(" > ")}
|
||||
>
|
||||
${join(breadcrumb, html`<ha-icon-next></ha-icon-next>`)}
|
||||
</button>
|
||||
`
|
||||
: html`
|
||||
<p class="breadcrumb">
|
||||
${join(breadcrumb, html`<ha-icon-next></ha-icon-next>`)}
|
||||
</p>
|
||||
`
|
||||
: nothing}
|
||||
<p class="main">${title}</p>
|
||||
</span>
|
||||
${isDefaultView
|
||||
? html`
|
||||
${this._shouldShowHistory(domain)
|
||||
? html`
|
||||
<ha-icon-button
|
||||
slot="actionItems"
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.history"
|
||||
)}
|
||||
.path=${mdiChartBoxOutline}
|
||||
@click=${this._goToHistory}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: nothing}
|
||||
${!__DEMO__ && isAdmin
|
||||
? html`
|
||||
<ha-icon-button
|
||||
slot="actionItems"
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.settings"
|
||||
)}
|
||||
.path=${mdiCogOutline}
|
||||
@click=${this._goToSettings}
|
||||
></ha-icon-button>
|
||||
<ha-button-menu
|
||||
corner="BOTTOM_END"
|
||||
menu-corner="END"
|
||||
slot="actionItems"
|
||||
@closed=${stopPropagation}
|
||||
fixed
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass.localize("ui.common.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
|
||||
${deviceId
|
||||
? html`
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._goToDevice}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.device_or_service_info",
|
||||
{
|
||||
type: this.hass.localize(
|
||||
`ui.dialogs.more_info_control.device_type.${deviceType}`
|
||||
),
|
||||
}
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${deviceType === "service"
|
||||
? mdiTransitConnectionVariant
|
||||
: mdiDevices}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
`
|
||||
: nothing}
|
||||
${this._shouldShowEditIcon(domain, stateObj)
|
||||
? html`
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._goToEdit}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.edit"
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiPencilOutline}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
`
|
||||
: nothing}
|
||||
${this._entry &&
|
||||
stateObj &&
|
||||
domain === "light" &&
|
||||
lightSupportsFavoriteColors(stateObj)
|
||||
? html`
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._toggleInfoEditMode}
|
||||
>
|
||||
${this._infoEditMode
|
||||
? this.hass.localize(
|
||||
`ui.dialogs.more_info_control.exit_edit_mode`
|
||||
)
|
||||
: this.hass.localize(
|
||||
`ui.dialogs.more_info_control.${domain}.edit_mode`
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${this._infoEditMode
|
||||
? mdiPencilOff
|
||||
: mdiPencil}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
`
|
||||
: nothing}
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._goToRelated}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.related"
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiInformationOutline}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
</ha-button-menu>
|
||||
`
|
||||
: nothing}
|
||||
`
|
||||
: isSpecificInitialView
|
||||
${showCloseIcon
|
||||
? html`
|
||||
<ha-icon-button
|
||||
slot="navigationIcon"
|
||||
data-dialog="close"
|
||||
.label=${this.hass.localize("ui.common.close")}
|
||||
.path=${mdiClose}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: html`
|
||||
<ha-icon-button-prev
|
||||
slot="navigationIcon"
|
||||
@click=${this._goBack}
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.back_to_info"
|
||||
)}
|
||||
></ha-icon-button-prev>
|
||||
`}
|
||||
<span slot="title" @click=${this._toggleSize} class="title">
|
||||
${breadcrumb.length > 0
|
||||
? !__DEMO__ && isAdmin
|
||||
? html`
|
||||
<ha-button-menu
|
||||
corner="BOTTOM_END"
|
||||
menu-corner="END"
|
||||
slot="actionItems"
|
||||
@closed=${stopPropagation}
|
||||
fixed
|
||||
<button
|
||||
class="breadcrumb"
|
||||
@click=${this._breadcrumbClick}
|
||||
aria-label=${breadcrumb.join(" > ")}
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass.localize("ui.common.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._resetInitialView}
|
||||
>
|
||||
${this.hass.localize("ui.dialogs.more_info_control.info")}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiInformationOutline}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
</ha-button-menu>
|
||||
${join(breadcrumb, html`<ha-icon-next></ha-icon-next>`)}
|
||||
</button>
|
||||
`
|
||||
: nothing}
|
||||
</ha-dialog-header>
|
||||
: html`
|
||||
<p class="breadcrumb">
|
||||
${join(breadcrumb, html`<ha-icon-next></ha-icon-next>`)}
|
||||
</p>
|
||||
`
|
||||
: nothing}
|
||||
<p class="main">${title}</p>
|
||||
</span>
|
||||
${isDefaultView
|
||||
? html`
|
||||
${this._shouldShowHistory(domain)
|
||||
? html`
|
||||
<ha-icon-button
|
||||
slot="actionItems"
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.history"
|
||||
)}
|
||||
.path=${mdiChartBoxOutline}
|
||||
@click=${this._goToHistory}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: nothing}
|
||||
${!__DEMO__ && isAdmin
|
||||
? html`
|
||||
<ha-icon-button
|
||||
slot="actionItems"
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.settings"
|
||||
)}
|
||||
.path=${mdiCogOutline}
|
||||
@click=${this._goToSettings}
|
||||
></ha-icon-button>
|
||||
<ha-button-menu
|
||||
corner="BOTTOM_END"
|
||||
menu-corner="END"
|
||||
slot="actionItems"
|
||||
@closed=${stopPropagation}
|
||||
fixed
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass.localize("ui.common.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
|
||||
${deviceId
|
||||
? html`
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._goToDevice}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.device_or_service_info",
|
||||
{
|
||||
type: this.hass.localize(
|
||||
`ui.dialogs.more_info_control.device_type.${deviceType}`
|
||||
),
|
||||
}
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${deviceType === "service"
|
||||
? mdiTransitConnectionVariant
|
||||
: mdiDevices}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
`
|
||||
: nothing}
|
||||
${this._shouldShowEditIcon(domain, stateObj)
|
||||
? html`
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._goToEdit}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.edit"
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiPencilOutline}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
`
|
||||
: nothing}
|
||||
${this._entry &&
|
||||
stateObj &&
|
||||
domain === "light" &&
|
||||
lightSupportsFavoriteColors(stateObj)
|
||||
? html`
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._toggleInfoEditMode}
|
||||
>
|
||||
${this._infoEditMode
|
||||
? this.hass.localize(
|
||||
`ui.dialogs.more_info_control.exit_edit_mode`
|
||||
)
|
||||
: this.hass.localize(
|
||||
`ui.dialogs.more_info_control.${domain}.edit_mode`
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${this._infoEditMode
|
||||
? mdiPencilOff
|
||||
: mdiPencil}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
`
|
||||
: nothing}
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._goToRelated}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.more_info_control.related"
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiInformationOutline}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
</ha-button-menu>
|
||||
`
|
||||
: nothing}
|
||||
`
|
||||
: isSpecificInitialView
|
||||
? html`
|
||||
<ha-button-menu
|
||||
corner="BOTTOM_END"
|
||||
menu-corner="END"
|
||||
slot="actionItems"
|
||||
@closed=${stopPropagation}
|
||||
fixed
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass.localize("ui.common.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@request-selected=${this._resetInitialView}
|
||||
>
|
||||
${this.hass.localize("ui.dialogs.more_info_control.info")}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiInformationOutline}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
</ha-button-menu>
|
||||
`
|
||||
: nothing}
|
||||
${keyed(
|
||||
this._entityId,
|
||||
html`
|
||||
@@ -608,7 +605,7 @@ export class MoreInfoDialog extends LitElement {
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
</ha-dialog>
|
||||
</ha-wa-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -630,8 +627,8 @@ export class MoreInfoDialog extends LitElement {
|
||||
this._entry = ev.detail;
|
||||
}
|
||||
|
||||
private _enlarge() {
|
||||
this.large = !this.large;
|
||||
private _toggleSize() {
|
||||
this.shadowRoot?.querySelector("ha-wa-dialog")?.toggleWidth();
|
||||
}
|
||||
|
||||
private _handleOpened() {
|
||||
@@ -664,7 +661,7 @@ export class MoreInfoDialog extends LitElement {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-dialog {
|
||||
ha-wa-dialog {
|
||||
/* Set the top top of the dialog to a fixed position, so it doesnt jump when the content changes size */
|
||||
--vertical-align-dialog: flex-start;
|
||||
--dialog-surface-margin-top: max(
|
||||
@@ -693,34 +690,21 @@ export class MoreInfoDialog extends LitElement {
|
||||
}
|
||||
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
/* When in fullscreen dialog should be attached to top */
|
||||
ha-dialog {
|
||||
--dialog-surface-margin-top: 0px;
|
||||
ha-wa-dialog {
|
||||
--dialog-surface-margin-top: initial;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 600px) and (min-height: 501px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-min-width: 580px;
|
||||
--mdc-dialog-max-width: 580px;
|
||||
--mdc-dialog-max-height: calc(100% - 72px);
|
||||
}
|
||||
|
||||
.main-title {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
:host([large]) ha-dialog {
|
||||
--mdc-dialog-min-width: 90vw;
|
||||
--mdc-dialog-max-width: 90vw;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin: 0 0 -10px 0;
|
||||
}
|
||||
|
||||
.title p {
|
||||
|
@@ -5,8 +5,9 @@ import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { computeDeviceNameDisplay } from "../../../../common/entity/compute_device_name";
|
||||
import "../../../../components/ha-alert";
|
||||
import "../../../../components/ha-area-picker";
|
||||
import "../../../../components/ha-dialog";
|
||||
import "../../../../components/ha-button";
|
||||
import "../../../../components/ha-dialog-footer";
|
||||
import "../../../../components/ha-wa-dialog";
|
||||
import "../../../../components/ha-labels-picker";
|
||||
import type { HaSwitch } from "../../../../components/ha-switch";
|
||||
import "../../../../components/ha-textfield";
|
||||
@@ -57,10 +58,11 @@ class DialogDeviceRegistryDetail extends LitElement {
|
||||
}
|
||||
const device = this._params.device;
|
||||
return html`
|
||||
<ha-dialog
|
||||
<ha-wa-dialog
|
||||
open
|
||||
@closed=${this.closeDialog}
|
||||
.heading=${computeDeviceNameDisplay(device, this.hass)}
|
||||
.headerTitle=${computeDeviceNameDisplay(device, this.hass)}
|
||||
.preventScrimClose=${true}
|
||||
>
|
||||
<div>
|
||||
${this._error
|
||||
@@ -131,22 +133,24 @@ class DialogDeviceRegistryDetail extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ha-button
|
||||
slot="secondaryAction"
|
||||
@click=${this.closeDialog}
|
||||
.disabled=${this._submitting}
|
||||
appearance="plain"
|
||||
>
|
||||
${this.hass.localize("ui.common.cancel")}
|
||||
</ha-button>
|
||||
<ha-button
|
||||
slot="primaryAction"
|
||||
@click=${this._updateEntry}
|
||||
.disabled=${this._submitting}
|
||||
>
|
||||
${this.hass.localize("ui.dialogs.device-registry-detail.update")}
|
||||
</ha-button>
|
||||
</ha-dialog>
|
||||
<ha-dialog-footer slot="footer">
|
||||
<ha-button
|
||||
slot="secondaryAction"
|
||||
appearance="plain"
|
||||
data-dialog="close"
|
||||
.disabled=${this._submitting}
|
||||
>
|
||||
${this.hass.localize("ui.common.cancel")}
|
||||
</ha-button>
|
||||
<ha-button
|
||||
slot="primaryAction"
|
||||
.disabled=${this._submitting}
|
||||
@click=${this._updateEntry}
|
||||
>
|
||||
${this.hass.localize("ui.dialogs.device-registry-detail.update")}
|
||||
</ha-button>
|
||||
</ha-dialog-footer>
|
||||
</ha-wa-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -210,10 +210,10 @@ export class ZHAClusterAttributes extends LitElement {
|
||||
this._readingAttribute = true;
|
||||
try {
|
||||
this._attributeValue = await readAttributeValue(this.hass, data);
|
||||
forwardHaptic("success");
|
||||
forwardHaptic(this, "success");
|
||||
button.actionSuccess();
|
||||
} catch (_err: any) {
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(this, "failure");
|
||||
button.actionError();
|
||||
} finally {
|
||||
this._readingAttribute = false;
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
mdiDelete,
|
||||
mdiDevices,
|
||||
mdiDotsVertical,
|
||||
mdiHelpCircle,
|
||||
mdiPlus,
|
||||
mdiRobot,
|
||||
@@ -9,8 +8,9 @@ import {
|
||||
} from "@mdi/js";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { LitElement, html, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { computeCssColor } from "../../../common/color/compute-color";
|
||||
import { formatShortDateTime } from "../../../common/datetime/format_date_time";
|
||||
import { storage } from "../../../common/decorators/storage";
|
||||
@@ -23,6 +23,7 @@ import type {
|
||||
} from "../../../components/data-table/ha-data-table";
|
||||
import "../../../components/ha-fab";
|
||||
import "../../../components/ha-icon-button";
|
||||
import "../../../components/ha-icon-overflow-menu";
|
||||
import "../../../components/ha-relative-time";
|
||||
import type {
|
||||
LabelRegistryEntry,
|
||||
@@ -42,7 +43,6 @@ import "../../../layouts/hass-tabs-subpage-data-table";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { showLabelDetailDialog } from "./show-dialog-label-detail";
|
||||
import type { HaMdMenu } from "../../../components/ha-md-menu";
|
||||
|
||||
@customElement("ha-config-labels")
|
||||
export class HaConfigLabels extends LitElement {
|
||||
@@ -86,10 +86,6 @@ export class HaConfigLabels extends LitElement {
|
||||
})
|
||||
private _activeHiddenColumns?: string[];
|
||||
|
||||
@query("#overflow-menu") private _overflowMenu!: HaMdMenu;
|
||||
|
||||
private _overflowLabel!: LabelRegistryEntry;
|
||||
|
||||
private _columns = memoizeOne((localize: LocalizeFunc, narrow: boolean) => {
|
||||
const columns: DataTableColumnContainer<LabelRegistryEntry> = {
|
||||
icon: {
|
||||
@@ -109,13 +105,14 @@ export class HaConfigLabels extends LitElement {
|
||||
template: (label) =>
|
||||
label.color
|
||||
? html`<div
|
||||
style="
|
||||
background-color: ${computeCssColor(label.color)};
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--outline-color);
|
||||
box-sizing: border-box;
|
||||
width: 20px;
|
||||
height: 20px;"
|
||||
style=${styleMap({
|
||||
backgroundColor: computeCssColor(label.color),
|
||||
borderRadius: "10px",
|
||||
border: "1px solid var(--outline-color)",
|
||||
boxSizing: "border-box",
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
})}
|
||||
></div>`
|
||||
: nothing,
|
||||
},
|
||||
@@ -176,12 +173,34 @@ export class HaConfigLabels extends LitElement {
|
||||
hideable: false,
|
||||
type: "overflow-menu",
|
||||
template: (label) => html`
|
||||
<ha-icon-button
|
||||
.selected=${label}
|
||||
.label=${this.hass.localize("ui.common.overflow_menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
@click=${this._showOverflowMenu}
|
||||
></ha-icon-button>
|
||||
<ha-icon-overflow-menu
|
||||
.hass=${this.hass}
|
||||
narrow
|
||||
.items=${[
|
||||
{
|
||||
label: this.hass.localize("ui.panel.config.entities.caption"),
|
||||
path: mdiShape,
|
||||
action: () => this._navigateEntities(label),
|
||||
},
|
||||
{
|
||||
label: this.hass.localize("ui.panel.config.devices.caption"),
|
||||
path: mdiDevices,
|
||||
action: () => this._navigateDevices(label),
|
||||
},
|
||||
{
|
||||
label: this.hass.localize("ui.panel.config.automation.caption"),
|
||||
path: mdiRobot,
|
||||
action: () => this._navigateAutomations(label),
|
||||
},
|
||||
{
|
||||
label: this.hass.localize("ui.common.delete"),
|
||||
path: mdiDelete,
|
||||
action: () => this._removeLabel(label),
|
||||
warning: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
</ha-icon-overflow-menu>
|
||||
`,
|
||||
},
|
||||
};
|
||||
@@ -195,19 +214,6 @@ export class HaConfigLabels extends LitElement {
|
||||
}))
|
||||
);
|
||||
|
||||
private _showOverflowMenu = (ev) => {
|
||||
if (
|
||||
this._overflowMenu.open &&
|
||||
ev.target === this._overflowMenu.anchorElement
|
||||
) {
|
||||
this._overflowMenu.close();
|
||||
return;
|
||||
}
|
||||
this._overflowLabel = ev.target.selected;
|
||||
this._overflowMenu.anchorElement = ev.target;
|
||||
this._overflowMenu.show();
|
||||
};
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues) {
|
||||
super.firstUpdated(changedProperties);
|
||||
this._fetchLabels();
|
||||
@@ -251,32 +257,6 @@ export class HaConfigLabels extends LitElement {
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
</hass-tabs-subpage-data-table>
|
||||
<ha-md-menu id="overflow-menu" positioning="fixed">
|
||||
<ha-md-menu-item .clickAction=${this._navigateEntities}>
|
||||
<ha-svg-icon slot="start" .path=${mdiShape}></ha-svg-icon>
|
||||
${this.hass.localize("ui.panel.config.entities.caption")}
|
||||
</ha-md-menu-item>
|
||||
<ha-md-menu-item .clickAction=${this._navigateDevices}>
|
||||
<ha-svg-icon slot="start" .path=${mdiDevices}></ha-svg-icon>
|
||||
${this.hass.localize("ui.panel.config.devices.caption")}
|
||||
</ha-md-menu-item>
|
||||
<ha-md-menu-item .clickAction=${this._navigateAutomations}>
|
||||
<ha-svg-icon slot="start" .path=${mdiRobot}></ha-svg-icon>
|
||||
${this.hass.localize("ui.panel.config.automation.caption")}
|
||||
</ha-md-menu-item>
|
||||
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
||||
<ha-md-menu-item
|
||||
class="warning"
|
||||
.clickAction=${this._handleRemoveLabelClick}
|
||||
>
|
||||
<ha-svg-icon
|
||||
slot="start"
|
||||
class="warning"
|
||||
.path=${mdiDelete}
|
||||
></ha-svg-icon>
|
||||
${this.hass.localize("ui.common.delete")}
|
||||
</ha-md-menu-item>
|
||||
</ha-md-menu>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -337,10 +317,6 @@ export class HaConfigLabels extends LitElement {
|
||||
return updated;
|
||||
}
|
||||
|
||||
private _handleRemoveLabelClick = () => {
|
||||
this._removeLabel(this._overflowLabel);
|
||||
};
|
||||
|
||||
private async _removeLabel(selectedLabel: LabelRegistryEntry) {
|
||||
if (
|
||||
!(await showConfirmationDialog(this, {
|
||||
@@ -368,23 +344,19 @@ export class HaConfigLabels extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _navigateEntities = () => {
|
||||
navigate(
|
||||
`/config/entities?historyBack=1&label=${this._overflowLabel.label_id}`
|
||||
);
|
||||
};
|
||||
private _navigateEntities(label: LabelRegistryEntry) {
|
||||
navigate(`/config/entities?historyBack=1&label=${label.label_id}`);
|
||||
}
|
||||
|
||||
private _navigateDevices = () => {
|
||||
navigate(
|
||||
`/config/devices/dashboard?historyBack=1&label=${this._overflowLabel.label_id}`
|
||||
);
|
||||
};
|
||||
private _navigateDevices(label: LabelRegistryEntry) {
|
||||
navigate(`/config/devices/dashboard?historyBack=1&label=${label.label_id}`);
|
||||
}
|
||||
|
||||
private _navigateAutomations = () => {
|
||||
private _navigateAutomations(label: LabelRegistryEntry) {
|
||||
navigate(
|
||||
`/config/automation/dashboard?historyBack=1&label=${this._overflowLabel.label_id}`
|
||||
`/config/automation/dashboard?historyBack=1&label=${label.label_id}`
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
private _handleSortingChanged(ev: CustomEvent) {
|
||||
this._activeSorting = ev.detail;
|
||||
|
@@ -1087,7 +1087,7 @@ ${rejected
|
||||
name: computeStateName(scene),
|
||||
}),
|
||||
});
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
};
|
||||
|
||||
private _deleteConfirm(scene: SceneEntity): void {
|
||||
|
@@ -443,7 +443,7 @@ class HaPanelDevAction extends LitElement {
|
||||
const button = ev.currentTarget as HaProgressButton;
|
||||
|
||||
if (this._yamlMode && !this._yamlValid) {
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(this, "failure");
|
||||
button.actionError();
|
||||
this._error = this.hass.localize(
|
||||
"ui.panel.developer-tools.tabs.actions.errors.yaml.invalid_yaml"
|
||||
@@ -465,7 +465,7 @@ class HaPanelDevAction extends LitElement {
|
||||
);
|
||||
|
||||
if (this._error !== undefined) {
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(this, "failure");
|
||||
button.actionError();
|
||||
return;
|
||||
}
|
||||
@@ -534,7 +534,7 @@ class HaPanelDevAction extends LitElement {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(this, "failure");
|
||||
button.actionError();
|
||||
|
||||
let localizedErrorMessage: string | undefined;
|
||||
|
@@ -177,7 +177,7 @@ class HuiAreaControlsCardFeature
|
||||
.map((entityId) => this.hass!.states[entityId] as HassEntity | undefined)
|
||||
.filter((v): v is HassEntity => Boolean(v));
|
||||
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
toggleGroupEntities(this.hass, entities);
|
||||
}
|
||||
|
||||
|
@@ -69,7 +69,7 @@ class HuiLockCommandsCardFeature
|
||||
if (!this.hass || !this._stateObj || !service) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
callProtectedLockService(this, this.hass, this._stateObj, service);
|
||||
}
|
||||
|
||||
|
@@ -112,7 +112,7 @@ class HuiToggleCardFeature extends LitElement implements LovelaceCardFeature {
|
||||
if (!this.hass || !this._stateObj) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
const stateDomain = computeDomain(this._stateObj.entity_id);
|
||||
const serviceDomain = stateDomain;
|
||||
const service = turnOn ? "turn_on" : "turn_off";
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import type { PropertyValues } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { getColorByIndex } from "../../../common/color/colors";
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
@@ -16,7 +17,11 @@ import type {
|
||||
import "../../calendar/ha-full-calendar";
|
||||
import { findEntities } from "../common/find-entities";
|
||||
import "../components/hui-warning";
|
||||
import type { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import type {
|
||||
LovelaceCard,
|
||||
LovelaceCardEditor,
|
||||
LovelaceGridOptions,
|
||||
} from "../types";
|
||||
import type { CalendarCardConfig } from "./types";
|
||||
|
||||
@customElement("hui-calendar-card")
|
||||
@@ -48,6 +53,8 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
|
||||
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public layout?: string;
|
||||
|
||||
@state() private _events: CalendarEvent[] = [];
|
||||
|
||||
@state() private _config?: CalendarCardConfig;
|
||||
@@ -88,7 +95,16 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
public getCardSize(): number {
|
||||
return this._config?.header ? 1 : 0 + 11;
|
||||
return 12;
|
||||
}
|
||||
|
||||
public getGridOptions(): LovelaceGridOptions {
|
||||
return {
|
||||
rows: 6,
|
||||
columns: 12,
|
||||
min_columns: 4,
|
||||
min_rows: 4,
|
||||
};
|
||||
}
|
||||
|
||||
public connectedCallback(): void {
|
||||
@@ -118,6 +134,10 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
|
||||
<ha-card>
|
||||
<div class="header">${this._config.title}</div>
|
||||
<ha-full-calendar
|
||||
class=${classMap({
|
||||
"is-grid": this.layout === "grid",
|
||||
"is-panel": this.layout === "panel",
|
||||
})}
|
||||
.narrow=${this._narrow}
|
||||
.events=${this._events}
|
||||
.hass=${this.hass}
|
||||
@@ -224,6 +244,11 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
|
||||
ha-full-calendar {
|
||||
--calendar-height: 400px;
|
||||
}
|
||||
|
||||
ha-full-calendar.is-grid,
|
||||
ha-full-calendar.is-panel {
|
||||
height: calc(100% - 16px);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -231,6 +231,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
|
||||
static styles = css`
|
||||
ha-card {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
ha-alert {
|
||||
margin-bottom: 8px;
|
||||
|
@@ -53,7 +53,7 @@ export const handleAction = async (
|
||||
(e) => e.user === hass!.user?.id
|
||||
))
|
||||
) {
|
||||
forwardHaptic("warning");
|
||||
forwardHaptic(node, "warning");
|
||||
|
||||
let serviceName;
|
||||
if (
|
||||
@@ -107,7 +107,7 @@ export const handleAction = async (
|
||||
"ui.panel.lovelace.cards.actions.no_entity_more_info"
|
||||
),
|
||||
});
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(node, "failure");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ export const handleAction = async (
|
||||
"ui.panel.lovelace.cards.actions.no_navigation_path"
|
||||
),
|
||||
});
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(node, "failure");
|
||||
}
|
||||
break;
|
||||
case "url": {
|
||||
@@ -132,21 +132,21 @@ export const handleAction = async (
|
||||
showToast(node, {
|
||||
message: hass.localize("ui.panel.lovelace.cards.actions.no_url"),
|
||||
});
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(node, "failure");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "toggle": {
|
||||
if (config.entity) {
|
||||
toggleEntity(hass, config.entity!);
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(node, "light");
|
||||
} else {
|
||||
showToast(node, {
|
||||
message: hass.localize(
|
||||
"ui.panel.lovelace.cards.actions.no_entity_toggle"
|
||||
),
|
||||
});
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(node, "failure");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -156,7 +156,7 @@ export const handleAction = async (
|
||||
showToast(node, {
|
||||
message: hass.localize("ui.panel.lovelace.cards.actions.no_action"),
|
||||
});
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(node, "failure");
|
||||
return;
|
||||
}
|
||||
const [domain, service] = (actionConfig.perform_action ||
|
||||
@@ -167,7 +167,7 @@ export const handleAction = async (
|
||||
actionConfig.data ?? actionConfig.service_data,
|
||||
actionConfig.target
|
||||
);
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(node, "light");
|
||||
break;
|
||||
}
|
||||
case "assist": {
|
||||
|
@@ -58,7 +58,7 @@ class HuiEntitiesToggle extends LitElement {
|
||||
`;
|
||||
|
||||
private _callService(ev: MouseEvent): void {
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
const turnOn = (ev.target as HaSwitch).checked;
|
||||
turnOnOffEntities(this.hass!, this._toggleEntities!, turnOn!);
|
||||
}
|
||||
|
@@ -103,7 +103,7 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {
|
||||
return;
|
||||
}
|
||||
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
|
||||
setInputSelectOption(this.hass!, stateObj.entity_id, option);
|
||||
}
|
||||
|
@@ -104,7 +104,7 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
|
||||
return;
|
||||
}
|
||||
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
|
||||
setSelectOption(this.hass!, stateObj.entity_id, option);
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ class HaSetVibrateRow extends LitElement {
|
||||
fireEvent(this, "hass-vibrate", {
|
||||
vibrate,
|
||||
});
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -14,7 +14,15 @@ import {
|
||||
polyfillTimeZoneData,
|
||||
} from "./locale-data-polyfill";
|
||||
|
||||
let polyfilled = false;
|
||||
|
||||
const _polyfillTimeZoneData = polyfillTimeZoneData;
|
||||
|
||||
const polyfillIntl = async () => {
|
||||
if (polyfilled) {
|
||||
return;
|
||||
}
|
||||
polyfilled = true;
|
||||
const locale = getLocalLanguage();
|
||||
const polyfills: Promise<unknown>[] = [];
|
||||
if (shouldPolyfillGetCanonicalLocales()) {
|
||||
@@ -26,7 +34,7 @@ const polyfillIntl = async () => {
|
||||
if (shouldPolyfillDateTimeFormat(locale)) {
|
||||
polyfills.push(
|
||||
import("@formatjs/intl-datetimeformat/polyfill-force").then(() =>
|
||||
polyfillTimeZoneData()
|
||||
_polyfillTimeZoneData()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -58,7 +66,7 @@ const polyfillIntl = async () => {
|
||||
if (polyfills.length === 0) {
|
||||
return;
|
||||
}
|
||||
await Promise.all(polyfills).then(() =>
|
||||
await Promise.allSettled(polyfills).then(() =>
|
||||
// Load the default language
|
||||
polyfillLocaleData(locale)
|
||||
);
|
||||
|
@@ -152,6 +152,10 @@ export const semanticColorStyles = css`
|
||||
--ha-color-on-success-quiet: var(--ha-color-green-50);
|
||||
--ha-color-on-success-normal: var(--ha-color-green-40);
|
||||
--ha-color-on-success-loud: var(--white-color);
|
||||
|
||||
/* Surfaces */
|
||||
--ha-color-surface-default: var(--ha-color-neutral-95);
|
||||
--ha-color-on-surface-default: var(--ha-color-neutral-05);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -280,5 +284,9 @@ export const darkSemanticColorStyles = css`
|
||||
--ha-color-on-success-quiet: var(--ha-color-green-70);
|
||||
--ha-color-on-success-normal: var(--ha-color-green-60);
|
||||
--ha-color-on-success-loud: var(--white-color);
|
||||
|
||||
/* Surfaces */
|
||||
--ha-color-surface-default: var(--ha-color-neutral-10);
|
||||
--ha-color-on-surface-default: var(--ha-color-neutral-95);
|
||||
}
|
||||
`;
|
||||
|
@@ -19,8 +19,8 @@ export const coreStyles = css`
|
||||
--ha-border-radius-pill: 9999px;
|
||||
--ha-border-radius-circle: 50%;
|
||||
--ha-border-radius-square: 0;
|
||||
|
||||
# Spacing
|
||||
|
||||
/* Spacing */
|
||||
--ha-space-0: 0px;
|
||||
--ha-space-1: 4px;
|
||||
--ha-space-2: 8px;
|
||||
@@ -34,7 +34,7 @@ export const coreStyles = css`
|
||||
--ha-space-10: 40px;
|
||||
--ha-space-11: 44px;
|
||||
--ha-space-12: 48px;
|
||||
--ha-space-13: 44px;
|
||||
--ha-space-13: 52px;
|
||||
--ha-space-14: 56px;
|
||||
--ha-space-15: 60px;
|
||||
--ha-space-16: 64px;
|
||||
|
@@ -40,7 +40,7 @@ export class HaStateControlCoverToggle extends LitElement {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
|
||||
await this.hass.callService(
|
||||
"cover",
|
||||
|
@@ -46,7 +46,7 @@ export class HaStateControlToggle extends LitElement {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
const stateDomain = computeDomain(this.stateObj.entity_id);
|
||||
let serviceDomain;
|
||||
let service;
|
||||
|
@@ -68,7 +68,7 @@ export class HaStateControlLockToggle extends LitElement {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
fireEvent(this, "lock-service-called");
|
||||
callProtectedLockService(
|
||||
this,
|
||||
|
@@ -40,7 +40,7 @@ export class HaStateControlValveToggle extends LitElement {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("light");
|
||||
forwardHaptic(this, "light");
|
||||
|
||||
await this.hass.callService(
|
||||
"valve",
|
||||
|
@@ -127,7 +127,7 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
||||
);
|
||||
}
|
||||
if (notifyOnError) {
|
||||
forwardHaptic("failure");
|
||||
forwardHaptic(this, "failure");
|
||||
const lokalize = await this.hass!.loadBackendTranslation(
|
||||
"exceptions",
|
||||
err.translation_domain
|
||||
|
28
yarn.lock
28
yarn.lock
@@ -1351,10 +1351,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ctrl/tinycolor@npm:^4.1.0":
|
||||
version: 4.2.0
|
||||
resolution: "@ctrl/tinycolor@npm:4.2.0"
|
||||
checksum: 10/1be14de7d7e8184c0bc5c8d7e3486cc8186e6702e8ca899c7239f328bb1df9a15d1575e2af7b4c6ba020727fa78f5a9f887555971f30a2890cece9e4253a9d3a
|
||||
"@ctrl/tinycolor@npm:4.1.0":
|
||||
version: 4.1.0
|
||||
resolution: "@ctrl/tinycolor@npm:4.1.0"
|
||||
checksum: 10/e64569399139ef0abd2eb0ec9fb7267dfd7820f7ad7d4567a63e5fc35e5cfdcb8ecdb3bad65cb9244b47ba6c77bc51085826c00e981acf263a3221dc89343adc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1940,11 +1940,11 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@home-assistant/webawesome@npm:3.0.0-beta.4.ha.3":
|
||||
version: 3.0.0-beta.4.ha.3
|
||||
resolution: "@home-assistant/webawesome@npm:3.0.0-beta.4.ha.3"
|
||||
"@home-assistant/webawesome@npm:3.0.0-beta.6.ha.0":
|
||||
version: 3.0.0-beta.6.ha.0
|
||||
resolution: "@home-assistant/webawesome@npm:3.0.0-beta.6.ha.0"
|
||||
dependencies:
|
||||
"@ctrl/tinycolor": "npm:^4.1.0"
|
||||
"@ctrl/tinycolor": "npm:4.1.0"
|
||||
"@floating-ui/dom": "npm:^1.6.13"
|
||||
"@lit/react": "npm:^1.0.8"
|
||||
"@shoelace-style/animations": "npm:^1.2.0"
|
||||
@@ -1953,8 +1953,7 @@ __metadata:
|
||||
lit: "npm:^3.2.1"
|
||||
nanoid: "npm:^5.1.5"
|
||||
qr-creator: "npm:^1.0.0"
|
||||
style-observer: "npm:^0.0.7"
|
||||
checksum: 10/b9241821ed471ccbad86b0ea4697a2d41395f05fdc26f46e5edbc7f6b5eeab5d248251ef702326312ded00d5bf850ce0dcdcf7cd5e2e542b9d9cb9a84f3726da
|
||||
checksum: 10/ec9d74585b544e5755f7b2644a0d7f9318b5776bedf51430c8f8729918fddb6e54cce46acace674960383385362846cc4c0f2da5245fa622bce8c54733a31865
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -9195,7 +9194,7 @@ __metadata:
|
||||
"@fullcalendar/list": "npm:6.1.19"
|
||||
"@fullcalendar/luxon3": "npm:6.1.19"
|
||||
"@fullcalendar/timegrid": "npm:6.1.19"
|
||||
"@home-assistant/webawesome": "npm:3.0.0-beta.4.ha.3"
|
||||
"@home-assistant/webawesome": "npm:3.0.0-beta.6.ha.0"
|
||||
"@lezer/highlight": "npm:1.2.1"
|
||||
"@lit-labs/motion": "npm:1.0.9"
|
||||
"@lit-labs/observers": "npm:2.0.6"
|
||||
@@ -13725,13 +13724,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"style-observer@npm:^0.0.7":
|
||||
version: 0.0.7
|
||||
resolution: "style-observer@npm:0.0.7"
|
||||
checksum: 10/bb57f98bae4463c1e1b57234f8ffe72ec0de27fb08b032c1919910129c210aacd1ddd615432b9453d491e10d3b719cf6c2a68a97165ca55d6fc9b86c0fca37fb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"style-observer@npm:^0.0.8":
|
||||
version: 0.0.8
|
||||
resolution: "style-observer@npm:0.0.8"
|
||||
|
Reference in New Issue
Block a user