diff --git a/src/common/entity/timer_time_remaining.ts b/src/common/entity/timer_time_remaining.ts index cd7c90ef8f..5b2f54654d 100644 --- a/src/common/entity/timer_time_remaining.ts +++ b/src/common/entity/timer_time_remaining.ts @@ -1,7 +1,12 @@ import { HassEntity } from "home-assistant-js-websocket"; import durationToSeconds from "../datetime/duration_to_seconds"; -export const timerTimeRemaining = (stateObj: HassEntity) => { +export const timerTimeRemaining = ( + stateObj: HassEntity +): undefined | number => { + if (!stateObj.attributes.remaining) { + return undefined; + } let timeRemaining = durationToSeconds(stateObj.attributes.remaining); if (stateObj.state === "active") { diff --git a/src/components/ha-color-picker.js b/src/components/ha-color-picker.js index 49fce6c7f5..a50601c0ea 100644 --- a/src/components/ha-color-picker.js +++ b/src/components/ha-color-picker.js @@ -176,6 +176,11 @@ class HaColorPicker extends EventsMixin(PolymerElement) { this.drawColorWheel(); this.drawMarker(); + if (this.desiredHsColor) { + this.setMarkerOnColor(this.desiredHsColor); + this.applyColorToCanvas(this.desiredHsColor); + } + this.interactionLayer.addEventListener("mousedown", (ev) => this.onMouseDown(ev) ); @@ -319,6 +324,9 @@ class HaColorPicker extends EventsMixin(PolymerElement) { // set marker position to the given color setMarkerOnColor(hs) { + if (!this.marker || !this.tooltip) { + return; + } const dist = hs.s * this.radius; const theta = ((hs.h - 180) / 180) * Math.PI; const markerdX = -dist * Math.cos(theta); @@ -330,6 +338,9 @@ class HaColorPicker extends EventsMixin(PolymerElement) { // apply given color to interface elements applyColorToCanvas(hs) { + if (!this.interactionLayer) { + return; + } // we're not really converting hs to hsl here, but we keep it cheap // setting the color on the interactionLayer, the svg elements can inherit this.interactionLayer.style.color = `hsl(${hs.h}, 100%, ${ diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index 1226fffbc4..d02c7bbd60 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -322,7 +322,7 @@ class HaSidebar extends LitElement { )} href="#external-app-configuration" tabindex="-1" - @click=${this._handleExternalAppConfiguration} + @panel-tap=${this._handleExternalAppConfiguration} @mouseenter=${this._itemMouseEnter} @mouseleave=${this._itemMouseLeave} > @@ -479,7 +479,8 @@ class HaSidebar extends LitElement { } private async _handleAction(ev: CustomEvent) { - if (ev.detail.action !== "hold") { + if (ev.detail.action === "tap") { + fireEvent(ev.target as HTMLElement, "panel-tap"); return; } @@ -497,6 +498,10 @@ class HaSidebar extends LitElement { } this._editMode = true; + if (!this.expanded) { + fireEvent(this, "hass-toggle-menu"); + } + await this.updateComplete; this._createSortable(); @@ -655,8 +660,11 @@ class HaSidebar extends LitElement { ); } - private _handlePanelTap(ev: Event) { - navigate(this, (ev.currentTarget as HTMLAnchorElement).href); + private async _handlePanelTap(ev: Event) { + const path = __DEMO__ + ? (ev.currentTarget as HTMLAnchorElement).getAttribute("href")! + : (ev.currentTarget as HTMLAnchorElement).href; + navigate(this, path); } private _renderPanel( @@ -668,10 +676,10 @@ class HaSidebar extends LitElement { return html` @@ -980,4 +988,8 @@ declare global { interface HTMLElementTagNameMap { "ha-sidebar": HaSidebar; } + + interface HASSDomEvents { + "panel-tap": undefined; + } } diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts index 8f54e1204c..0d9cde1946 100644 --- a/src/components/media-player/ha-media-player-browse.ts +++ b/src/components/media-player/ha-media-player-browse.ts @@ -172,6 +172,7 @@ export class HaMediaPlayerBrowse extends LitElement {
@@ -543,6 +544,7 @@ export class HaMediaPlayerBrowse extends LitElement { .header { background-color: var(--card-background-color); position: sticky; + position: -webkit-sticky; top: 0; z-index: 5; padding: 20px 24px 10px; @@ -740,6 +742,10 @@ export class HaMediaPlayerBrowse extends LitElement { padding: 0; } + :host([narrow]) .header.no-dialog { + display: block; + } + :host([narrow]) .header_button { position: absolute; top: 14px; diff --git a/src/dialogs/more-info/controls/more-info-light.ts b/src/dialogs/more-info/controls/more-info-light.ts index a87316e874..605e3210f5 100644 --- a/src/dialogs/more-info/controls/more-info-light.ts +++ b/src/dialogs/more-info/controls/more-info-light.ts @@ -134,7 +134,7 @@ class MoreInfoLight extends LitElement { attr-for-selected="item-name" >${this.stateObj.attributes.effect_list.map( (effect: string) => html` - ${effect} ` @@ -170,7 +170,7 @@ class MoreInfoLight extends LitElement { } private _effectChanged(ev: CustomEvent) { - const newVal = ev.detail.value; + const newVal = ev.detail.item.itemName; if (!newVal || this.stateObj!.attributes.effect === newVal) { return; diff --git a/src/dialogs/more-info/controls/more-info-timer.ts b/src/dialogs/more-info/controls/more-info-timer.ts index 809d697c70..c06f549896 100644 --- a/src/dialogs/more-info/controls/more-info-timer.ts +++ b/src/dialogs/more-info/controls/more-info-timer.ts @@ -26,15 +26,12 @@ class MoreInfoTimer extends LitElement { return html`
${this.stateObj.state === "idle" || this.stateObj.state === "paused" ? html` - + ${this.hass!.localize("ui.card.timer.actions.start")} ` @@ -42,7 +39,7 @@ class MoreInfoTimer extends LitElement { ${this.stateObj.state === "active" ? html` ${this.hass!.localize("ui.card.timer.actions.pause")} @@ -52,13 +49,13 @@ class MoreInfoTimer extends LitElement { ${this.stateObj.state === "active" || this.stateObj.state === "paused" ? html` ${this.hass!.localize("ui.card.timer.actions.cancel")} ${this.hass!.localize("ui.card.timer.actions.finish")} diff --git a/src/dialogs/more-info/ha-more-info-dialog.ts b/src/dialogs/more-info/ha-more-info-dialog.ts index 086040ddef..7738ee7349 100644 --- a/src/dialogs/more-info/ha-more-info-dialog.ts +++ b/src/dialogs/more-info/ha-more-info-dialog.ts @@ -274,6 +274,7 @@ export class MoreInfoDialog extends LitElement { --mdc-theme-on-primary: var(--primary-text-color); --mdc-theme-primary: var(--mdc-theme-surface); flex-shrink: 0; + display: block; } @media all and (max-width: 450px), all and (max-height: 500px) { diff --git a/src/entrypoints/app.ts b/src/entrypoints/app.ts index bb4b54b6e7..a4dd8580d4 100644 --- a/src/entrypoints/app.ts +++ b/src/entrypoints/app.ts @@ -7,5 +7,3 @@ import "../util/legacy-support"; setPassiveTouchGestures(true); (window as any).frontendVersion = __VERSION__; - -import("../resources/html-import/polyfill"); diff --git a/src/html/index.html.template b/src/html/index.html.template index fe4271c0fb..f5d8be97d1 100644 --- a/src/html/index.html.template +++ b/src/html/index.html.template @@ -100,9 +100,5 @@ {% endfor -%} } - - {% for extra_url in extra_urls -%} - - {% endfor -%} diff --git a/src/panels/config/automation/action/ha-automation-action-row.ts b/src/panels/config/automation/action/ha-automation-action-row.ts index 420d339e28..d9cf65ce8c 100644 --- a/src/panels/config/automation/action/ha-automation-action-row.ts +++ b/src/panels/config/automation/action/ha-automation-action-row.ts @@ -173,7 +173,7 @@ export default class HaAutomationActionRow extends LitElement { "ui.panel.config.automation.editor.actions.duplicate" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.actions.delete" )} diff --git a/src/panels/config/automation/condition/ha-automation-condition-row.ts b/src/panels/config/automation/condition/ha-automation-condition-row.ts index 1f51b47f13..89bbfcab54 100644 --- a/src/panels/config/automation/condition/ha-automation-condition-row.ts +++ b/src/panels/config/automation/condition/ha-automation-condition-row.ts @@ -19,6 +19,7 @@ import { Condition } from "../../../../data/automation"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; import { HomeAssistant } from "../../../../types"; import "./ha-automation-condition-editor"; +import { haStyle } from "../../../../resources/styles"; export interface ConditionElement extends LitElement { condition: Condition; @@ -86,7 +87,7 @@ export default class HaAutomationConditionRow extends LitElement { "ui.panel.config.automation.editor.actions.duplicate" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.actions.delete" )} @@ -134,20 +135,23 @@ export default class HaAutomationConditionRow extends LitElement { this._yamlMode = !this._yamlMode; } - static get styles(): CSSResult { - return css` - .card-menu { - float: right; - z-index: 3; - --mdc-theme-text-primary-on-background: var(--primary-text-color); - } - .rtl .card-menu { - float: left; - } - mwc-list-item[disabled] { - --mdc-theme-text-primary-on-background: var(--disabled-text-color); - } - `; + static get styles(): CSSResult[] { + return [ + haStyle, + css` + .card-menu { + float: right; + z-index: 3; + --mdc-theme-text-primary-on-background: var(--primary-text-color); + } + .rtl .card-menu { + float: left; + } + mwc-list-item[disabled] { + --mdc-theme-text-primary-on-background: var(--disabled-text-color); + } + `, + ]; } } diff --git a/src/panels/config/automation/trigger/ha-automation-trigger-row.ts b/src/panels/config/automation/trigger/ha-automation-trigger-row.ts index feeda91773..aa80ff1a96 100644 --- a/src/panels/config/automation/trigger/ha-automation-trigger-row.ts +++ b/src/panels/config/automation/trigger/ha-automation-trigger-row.ts @@ -118,7 +118,7 @@ export default class HaAutomationTriggerRow extends LitElement { "ui.panel.config.automation.editor.actions.duplicate" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.actions.delete" )} diff --git a/src/panels/config/server_control/ha-config-server-control.ts b/src/panels/config/server_control/ha-config-server-control.ts index 7cd8e63160..04fbc5b237 100644 --- a/src/panels/config/server_control/ha-config-server-control.ts +++ b/src/panels/config/server_control/ha-config-server-control.ts @@ -23,6 +23,8 @@ import { HomeAssistant, Route } from "../../../types"; import "../ha-config-section"; import { configSections } from "../ha-panel-config"; +const platformsWithReload = ["template"]; + @customElement("ha-config-server-control") export class HaConfigServerControl extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -49,11 +51,13 @@ export class HaConfigServerControl extends LitElement { changedProperties.has("hass") && (!oldHass || oldHass.config.components !== this.hass.config.components) ) { - this._reloadableDomains = this.hass.config.components.filter( - (component) => - !component.includes(".") && - isServiceLoaded(this.hass, component, "reload") - ); + this._reloadableDomains = this.hass.config.components + .concat(platformsWithReload) + .filter( + (component) => + !component.includes(".") && + isServiceLoaded(this.hass, component, "reload") + ); } } diff --git a/src/panels/logbook/ha-logbook.ts b/src/panels/logbook/ha-logbook.ts index 1270db9619..cf49dd24ba 100644 --- a/src/panels/logbook/ha-logbook.ts +++ b/src/panels/logbook/ha-logbook.ts @@ -216,7 +216,7 @@ class HaLogbook extends LitElement { display: flex; justify-content: center; flex-direction: column; - width: 70px; + width: 75px; flex-shrink: 0; font-size: 12px; color: var(--secondary-text-color); diff --git a/src/panels/lovelace/cards/hui-calendar-card.ts b/src/panels/lovelace/cards/hui-calendar-card.ts index 2351454829..ee94fb807c 100644 --- a/src/panels/lovelace/cards/hui-calendar-card.ts +++ b/src/panels/lovelace/cards/hui-calendar-card.ts @@ -76,11 +76,11 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard { private _resizeObserver?: ResizeObserver; public setConfig(config: CalendarCardConfig): void { - if (!config.entities) { + if (!config.entities?.length) { throw new Error("Entities must be defined"); } - if (config.entities && !Array.isArray(config.entities)) { + if (!Array.isArray(config.entities)) { throw new Error("Entities need to be an array"); } diff --git a/src/panels/lovelace/common/directives/action-handler-directive.ts b/src/panels/lovelace/common/directives/action-handler-directive.ts index 0c245a4764..3b0ea378c8 100644 --- a/src/panels/lovelace/common/directives/action-handler-directive.ts +++ b/src/panels/lovelace/common/directives/action-handler-directive.ts @@ -154,6 +154,7 @@ class ActionHandler extends HTMLElement implements ActionHandler { if (["touchend", "touchcancel"].includes(ev.type) && this.cancelled) { return; } + const target = ev.target as HTMLElement; // Prevent mouse event if touch event if (ev.cancelable) { ev.preventDefault(); @@ -164,7 +165,7 @@ class ActionHandler extends HTMLElement implements ActionHandler { this.timer = undefined; } if (options.hasHold && this.held) { - fireEvent(element, "action", { action: "hold" }); + fireEvent(target, "action", { action: "hold" }); } else if (options.hasDoubleClick) { if ( (ev.type === "click" && (ev as MouseEvent).detail < 2) || @@ -172,15 +173,15 @@ class ActionHandler extends HTMLElement implements ActionHandler { ) { this.dblClickTimeout = window.setTimeout(() => { this.dblClickTimeout = undefined; - fireEvent(element, "action", { action: "tap" }); + fireEvent(target, "action", { action: "tap" }); }, 250); } else { clearTimeout(this.dblClickTimeout); this.dblClickTimeout = undefined; - fireEvent(element, "action", { action: "double_tap" }); + fireEvent(target, "action", { action: "double_tap" }); } } else { - fireEvent(element, "action", { action: "tap" }); + fireEvent(target, "action", { action: "tap" }); } }; diff --git a/src/panels/lovelace/common/load-resources.ts b/src/panels/lovelace/common/load-resources.ts index c996f25562..5b9fb6d316 100644 --- a/src/panels/lovelace/common/load-resources.ts +++ b/src/panels/lovelace/common/load-resources.ts @@ -30,12 +30,6 @@ export const loadLovelaceResources = ( loadModule(normalizedUrl); break; - case "html": - import( - /* webpackChunkName: "import-href-polyfill" */ "../../../resources/html-import/import-href" - ).then(({ importHref }) => importHref(normalizedUrl)); - break; - default: // eslint-disable-next-line console.warn(`Unknown resource type specified: ${resource.type}`); diff --git a/src/panels/lovelace/editor/types.ts b/src/panels/lovelace/editor/types.ts index 04a2755a4b..5d9a335a10 100644 --- a/src/panels/lovelace/editor/types.ts +++ b/src/panels/lovelace/editor/types.ts @@ -5,7 +5,7 @@ import { ShowViewConfig, } from "../../../data/lovelace"; import { EntityConfig } from "../entity-rows/types"; -import { optional, string, object, union } from "superstruct"; +import { optional, string, object, union, boolean } from "superstruct"; import { EntityId } from "../common/structs/is-entity-id"; import { Icon } from "../common/structs/is-icon"; @@ -81,6 +81,10 @@ export const entitiesConfigStruct = union([ entity: EntityId, name: optional(string()), icon: optional(Icon), + image: optional(string()), + secondary_info: optional(string()), + format: optional(string()), + state_color: optional(boolean()), }), EntityId, ]); diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts index e744313f26..b77225c28d 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -2,9 +2,9 @@ import { HassEntity } from "home-assistant-js-websocket"; import { customElement, html, + internalProperty, LitElement, property, - internalProperty, PropertyValues, TemplateResult, } from "lit-element"; @@ -125,7 +125,9 @@ class HuiTimerEntityRow extends LitElement { } if (stateObj.state === "idle" || this._timeRemaining === 0) { - return this.hass!.localize("state.timer." + stateObj.state); + return ( + this.hass!.localize(`state.timer.${stateObj.state}`) || stateObj.state + ); } let display = secondsToDuration(this._timeRemaining || 0); diff --git a/src/resources/ha-sortable-style.ts b/src/resources/ha-sortable-style.ts index aa5ffe7789..5751f54819 100644 --- a/src/resources/ha-sortable-style.ts +++ b/src/resources/ha-sortable-style.ts @@ -20,8 +20,6 @@ export const sortableStyles = css` #sortable { outline: none; - display: flex; - flex-direction: column; } .sortable-ghost { diff --git a/src/resources/html-import/import-href.js b/src/resources/html-import/import-href.js deleted file mode 100644 index 32083338c3..0000000000 --- a/src/resources/html-import/import-href.js +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-disable */ -import "./polyfill"; -/** -@license -Copyright (c) 2017 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ - -// run a callback when HTMLImports are ready or immediately if -// this api is not available. -function whenImportsReady(cb) { - if (window.HTMLImports) { - HTMLImports.whenReady(cb); - } else { - cb(); - } -} - -/** - * Convenience method for importing an HTML document imperatively. - * - * This method creates a new `` element with - * the provided URL and appends it to the document to start loading. - * In the `onload` callback, the `import` property of the `link` - * element will contain the imported document contents. - * - * @param {string} href URL to document to load. - * @param {?function(!Event):void=} onload Callback to notify when an import successfully - * loaded. - * @param {?function(!ErrorEvent):void=} onerror Callback to notify when an import - * unsuccessfully loaded. - * @param {boolean=} optAsync True if the import should be loaded `async`. - * Defaults to `false`. - * @return {!HTMLLinkElement} The link element for the URL to be loaded. - */ -export const importHref = function (href, onload, onerror, optAsync) { - let link /** @type {HTMLLinkElement} */ = document.head.querySelector( - 'link[href="' + href + '"][import-href]' - ); - if (!link) { - link = /** @type {HTMLLinkElement} */ (document.createElement("link")); - link.rel = "import"; - link.href = href; - link.setAttribute("import-href", ""); - } - // always ensure link has `async` attribute if user specified one, - // even if it was previously not async. This is considered less confusing. - if (optAsync) { - link.setAttribute("async", ""); - } - // NOTE: the link may now be in 3 states: (1) pending insertion, - // (2) inflight, (3) already loaded. In each case, we need to add - // event listeners to process callbacks. - const cleanup = function () { - link.removeEventListener("load", loadListener); - link.removeEventListener("error", errorListener); - }; - let loadListener = function (event) { - cleanup(); - // In case of a successful load, cache the load event on the link so - // that it can be used to short-circuit this method in the future when - // it is called with the same href param. - link.__dynamicImportLoaded = true; - if (onload) { - whenImportsReady(() => { - onload(event); - }); - } - }; - let errorListener = function (event) { - cleanup(); - // In case of an error, remove the link from the document so that it - // will be automatically created again the next time `importHref` is - // called. - if (link.parentNode) { - link.parentNode.removeChild(link); - } - if (onerror) { - whenImportsReady(() => { - onerror(event); - }); - } - }; - link.addEventListener("load", loadListener); - link.addEventListener("error", errorListener); - if (link.parentNode == null) { - document.head.appendChild(link); - // if the link already loaded, dispatch a fake load event - // so that listeners are called and get a proper event argument. - } else if (link.__dynamicImportLoaded) { - link.dispatchEvent(new Event("load")); - } - return link; -}; - -export const importHrefPromise = (href) => - new Promise((resolve, reject) => importHref(href, resolve, reject)); diff --git a/src/resources/html-import/polyfill.js b/src/resources/html-import/polyfill.js deleted file mode 100644 index 51844ed272..0000000000 --- a/src/resources/html-import/polyfill.js +++ /dev/null @@ -1,451 +0,0 @@ -/* eslint-disable */ -/* - Copyright (c) 2016 The Polymer Project Authors. All rights reserved. - This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - Code distributed by Google as part of the polymer project is also - subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ -(function (q) { - function y(a, b) { - if ("function" === typeof window.CustomEvent) return new CustomEvent(a, b); - var c = document.createEvent("CustomEvent"); - c.initCustomEvent(a, !!b.bubbles, !!b.cancelable, b.detail); - return c; - } - function m(a) { - if (u) return a.ownerDocument !== document ? a.ownerDocument : null; - var b = a.__importDoc; - if (!b && a.parentNode) { - b = a.parentNode; - if ("function" === typeof b.closest) b = b.closest("link[rel=import]"); - else for (; !r(b) && (b = b.parentNode); ); - a.__importDoc = b; - } - return b; - } - function D(a) { - var b = k(document, "link[rel=import]:not([import-dependency])"), - c = b.length; - c - ? g(b, function (b) { - return t(b, function () { - 0 === --c && a(); - }); - }) - : a(); - } - function z(a) { - function b() { - "loading" !== document.readyState && - document.body && - (document.removeEventListener("readystatechange", b), a()); - } - document.addEventListener("readystatechange", b); - b(); - } - function A(a) { - z(function () { - return D(function () { - return a && a(); - }); - }); - } - function t(a, b) { - if (a.__loaded) b && b(); - else if ( - ("script" === a.localName && !a.src) || - ("style" === a.localName && !a.firstChild) - ) - (a.__loaded = !0), b && b(); - else { - var c = function (d) { - a.removeEventListener(d.type, c); - a.__loaded = !0; - b && b(); - }; - a.addEventListener("load", c); - (v && "style" === a.localName) || a.addEventListener("error", c); - } - } - function r(a) { - return ( - a.nodeType === Node.ELEMENT_NODE && - "link" === a.localName && - "import" === a.rel - ); - } - function h() { - var a = this; - this.a = {}; - this.b = 0; - this.g = new MutationObserver(function (b) { - return a.w(b); - }); - this.g.observe(document.head, { childList: !0, subtree: !0 }); - this.loadImports(document); - } - function B(a) { - g(k(a, "template"), function (a) { - g( - k( - a.content, - 'script:not([type]),script[type="application/javascript"],script[type="text/javascript"]' - ), - function (a) { - var b = document.createElement("script"); - g(a.attributes, function (a) { - return b.setAttribute(a.name, a.value); - }); - b.textContent = a.textContent; - a.parentNode.replaceChild(b, a); - } - ); - B(a.content); - }); - } - function k(a, b) { - return a.childNodes.length ? a.querySelectorAll(b) : E; - } - function g(a, b, c) { - var d = a ? a.length : 0, - f = c ? -1 : 1; - for (c = c ? d - 1 : 0; c < d && 0 <= c; c += f) b(a[c], c); - } - var n = document.createElement("link"), - u = "import" in n, - E = n.querySelectorAll("*"), - w = null; - !1 === "currentScript" in document && - Object.defineProperty(document, "currentScript", { - get: function () { - return ( - w || - ("complete" !== document.readyState - ? document.scripts[document.scripts.length - 1] - : null) - ); - }, - configurable: !0, - }); - var F = /(url\()([^)]*)(\))/g, - G = /(@import[\s]+(?!url\())([^;]*)(;)/g, - H = /(]*)(rel=['|"]?stylesheet['|"]?[^>]*>)/g, - e = { - u: function (a, b) { - a.href && a.setAttribute("href", e.c(a.getAttribute("href"), b)); - a.src && a.setAttribute("src", e.c(a.getAttribute("src"), b)); - if ("style" === a.localName) { - var c = e.o(a.textContent, b, F); - a.textContent = e.o(c, b, G); - } - }, - o: function (a, b, c) { - return a.replace(c, function (a, c, l, g) { - a = l.replace(/["']/g, ""); - b && (a = e.c(a, b)); - return c + "'" + a + "'" + g; - }); - }, - c: function (a, b) { - if (void 0 === e.f) { - e.f = !1; - try { - var c = new URL("b", "http://a"); - c.pathname = "c%20d"; - e.f = "http://a/c%20d" === c.href; - } catch (d) {} - } - if (e.f) return new URL(a, b).href; - c = e.s; - c || - ((c = document.implementation.createHTMLDocument("temp")), - (e.s = c), - (c.i = c.createElement("base")), - c.head.appendChild(c.i), - (c.h = c.createElement("a"))); - c.i.href = b; - c.h.href = a; - return c.h.href || a; - }, - }, - C = { - async: !0, - load: function (a, b, c) { - if (a) - if (a.match(/^data:/)) { - a = a.split(","); - var d = a[1]; - d = -1 < a[0].indexOf(";base64") ? atob(d) : decodeURIComponent(d); - b(d); - } else { - var f = new XMLHttpRequest(); - f.open("GET", a, C.async); - f.onload = function () { - var a = f.responseURL || f.getResponseHeader("Location"); - a && - 0 === a.indexOf("/") && - (a = - (location.origin || - location.protocol + "//" + location.host) + a); - var d = f.response || f.responseText; - 304 === f.status || - 0 === f.status || - (200 <= f.status && 300 > f.status) - ? b(d, a) - : c(d); - }; - f.send(); - } - else c("error: href must be specified"); - }, - }, - v = - /Trident/.test(navigator.userAgent) || - /Edge\/\d./i.test(navigator.userAgent); - h.prototype.loadImports = function (a) { - var b = this; - g(k(a, "link[rel=import]"), function (a) { - return b.l(a); - }); - }; - h.prototype.l = function (a) { - var b = this, - c = a.href; - if (void 0 !== this.a[c]) { - var d = this.a[c]; - d && d.__loaded && ((a.__import = d), this.j(a)); - } else - this.b++, - (this.a[c] = "pending"), - C.load( - c, - function (a, d) { - a = b.A(a, d || c); - b.a[c] = a; - b.b--; - b.loadImports(a); - b.m(); - }, - function () { - b.a[c] = null; - b.b--; - b.m(); - } - ); - }; - h.prototype.A = function (a, b) { - if (!a) return document.createDocumentFragment(); - v && - (a = a.replace(H, function (a, b, c) { - return -1 === a.indexOf("type=") ? b + " type=import-disable " + c : a; - })); - var c = document.createElement("template"); - c.innerHTML = a; - if (c.content) (a = c.content), B(a); - else - for (a = document.createDocumentFragment(); c.firstChild; ) - a.appendChild(c.firstChild); - if ((c = a.querySelector("base"))) - (b = e.c(c.getAttribute("href"), b)), c.removeAttribute("href"); - var d = 0; - g( - k( - a, - 'link[rel=import],link[rel=stylesheet][href][type=import-disable],style:not([type]),link[rel=stylesheet][href]:not([type]),script:not([type]),script[type="application/javascript"],script[type="text/javascript"]' - ), - function (a) { - t(a); - e.u(a, b); - a.setAttribute("import-dependency", ""); - "script" === a.localName && - !a.src && - a.textContent && - (a.setAttribute( - "src", - "data:text/javascript;charset=utf-8," + - encodeURIComponent( - a.textContent + - ("\n//# sourceURL=" + b + (d ? "-" + d : "") + ".js\n") - ) - ), - (a.textContent = ""), - d++); - } - ); - return a; - }; - h.prototype.m = function () { - var a = this; - if (!this.b) { - this.g.disconnect(); - this.flatten(document); - var b = !1, - c = !1, - d = function () { - c && - b && - (a.loadImports(document), - a.b || - (a.g.observe(document.head, { childList: !0, subtree: !0 }), - a.v())); - }; - this.C(function () { - c = !0; - d(); - }); - this.B(function () { - b = !0; - d(); - }); - } - }; - h.prototype.flatten = function (a) { - var b = this; - g(k(a, "link[rel=import]"), function (a) { - var c = b.a[a.href]; - (a.__import = c) && - c.nodeType === Node.DOCUMENT_FRAGMENT_NODE && - ((b.a[a.href] = a), - (a.readyState = "loading"), - (a.__import = a), - b.flatten(c), - a.appendChild(c)); - }); - }; - h.prototype.B = function (a) { - function b(f) { - if (f < d) { - var l = c[f], - e = document.createElement("script"); - l.removeAttribute("import-dependency"); - g(l.attributes, function (a) { - return e.setAttribute(a.name, a.value); - }); - w = e; - l.parentNode.replaceChild(e, l); - t(e, function () { - w = null; - b(f + 1); - }); - } else a(); - } - var c = k(document, "script[import-dependency]"), - d = c.length; - b(0); - }; - h.prototype.C = function (a) { - var b = k( - document, - "style[import-dependency],link[rel=stylesheet][import-dependency]" - ), - c = b.length; - if (c) { - var d = - v && - !!document.querySelector( - "link[rel=stylesheet][href][type=import-disable]" - ); - g(b, function (b) { - t(b, function () { - b.removeAttribute("import-dependency"); - 0 === --c && a(); - }); - if (d && b.parentNode !== document.head) { - var e = document.createElement(b.localName); - e.__appliedElement = b; - e.setAttribute("type", "import-placeholder"); - b.parentNode.insertBefore(e, b.nextSibling); - for (e = m(b); e && m(e); ) e = m(e); - e.parentNode !== document.head && (e = null); - document.head.insertBefore(b, e); - b.removeAttribute("type"); - } - }); - } else a(); - }; - h.prototype.v = function () { - var a = this; - g( - k(document, "link[rel=import]"), - function (b) { - return a.j(b); - }, - !0 - ); - }; - h.prototype.j = function (a) { - a.__loaded || - ((a.__loaded = !0), - a.import && (a.import.readyState = "complete"), - a.dispatchEvent( - y(a.import ? "load" : "error", { - bubbles: !1, - cancelable: !1, - detail: void 0, - }) - )); - }; - h.prototype.w = function (a) { - var b = this; - g(a, function (a) { - return g(a.addedNodes, function (a) { - a && - a.nodeType === Node.ELEMENT_NODE && - (r(a) ? b.l(a) : b.loadImports(a)); - }); - }); - }; - var x = null; - if (u) - g(k(document, "link[rel=import]"), function (a) { - (a.import && "loading" === a.import.readyState) || (a.__loaded = !0); - }), - (n = function (a) { - a = a.target; - r(a) && (a.__loaded = !0); - }), - document.addEventListener("load", n, !0), - document.addEventListener("error", n, !0); - else { - var p = Object.getOwnPropertyDescriptor(Node.prototype, "baseURI"); - Object.defineProperty( - (!p || p.configurable ? Node : Element).prototype, - "baseURI", - { - get: function () { - var a = r(this) ? this : m(this); - return a - ? a.href - : p && p.get - ? p.get.call(this) - : (document.querySelector("base") || window.location).href; - }, - configurable: !0, - enumerable: !0, - } - ); - Object.defineProperty(HTMLLinkElement.prototype, "import", { - get: function () { - return this.__import || null; - }, - configurable: !0, - enumerable: !0, - }); - z(function () { - x = new h(); - }); - } - A(function () { - return document.dispatchEvent( - y("HTMLImportsLoaded", { cancelable: !0, bubbles: !0, detail: void 0 }) - ); - }); - q.useNative = u; - q.whenReady = A; - q.importForElement = m; - q.loadImports = function (a) { - x && x.loadImports(a); - }; -})((window.HTMLImports = window.HTMLImports || {})); diff --git a/src/state-summary/state-card-timer.js b/src/state-summary/state-card-timer.js index 96586e8804..17d39fde5c 100644 --- a/src/state-summary/state-card-timer.js +++ b/src/state-summary/state-card-timer.js @@ -23,7 +23,7 @@ class StateCardTimer extends PolymerElement {
${this.stateInfoTemplate} -
[[_secondsToDuration(timeRemaining)]]
+
[[_displayState(timeRemaining, stateObj)]]
`; } @@ -90,8 +90,10 @@ class StateCardTimer extends PolymerElement { this.timeRemaining = timerTimeRemaining(stateObj); } - _secondsToDuration(time) { - return secondsToDuration(time); + _displayState(time, stateObj) { + return time + ? secondsToDuration(time) + : this.hass.localize(`state.timer.${stateObj.state}`) || stateObj.state; } } customElements.define("state-card-timer", StateCardTimer); diff --git a/src/util/custom-panel/load-custom-panel.ts b/src/util/custom-panel/load-custom-panel.ts index c674e0f4ed..1286b6588f 100644 --- a/src/util/custom-panel/load-custom-panel.ts +++ b/src/util/custom-panel/load-custom-panel.ts @@ -47,17 +47,6 @@ export const loadCustomPanel = ( ): Promise => { const panelSource = getUrl(panelConfig); - if (panelSource.type === "html") { - const toLoad = [ - import( - /* webpackChunkName: "import-href-polyfill" */ "../../resources/html-import/import-href" - ), - ]; - - return Promise.all(toLoad).then(([{ importHrefPromise }]) => - importHrefPromise(panelSource.url) - ); - } if (panelSource.type === "js") { if (!(panelSource.url in JS_CACHE)) { JS_CACHE[panelSource.url] = loadJS(panelSource.url);