diff --git a/custom_components/houseplan/frontend/houseplan-card.js b/custom_components/houseplan/frontend/houseplan-card.js index 9d8ef24f..fe4dbdb8 100755 --- a/custom_components/houseplan/frontend/houseplan-card.js +++ b/custom_components/houseplan/frontend/houseplan-card.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="51295f426e16fc7696178d532a79c35dea2cdcf9a545c39f02c529aa2dbc5cd9";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const i=this.t;if(e&&void 0===t){const e=void 0!==i&&1===i.length;e&&(t=s.get(i)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&s.set(i,t))}return t}toString(){return this.cssText}};const o=(t,...e)=>{const s=1===t.length?t[0]:e.reduce((e,i,s)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[s+1],t[0]);return new n(s,t,i)},a=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new n("string"==typeof t?t:t+"",void 0,i))(e)})(t):t,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.reactiveElementPolyfillSupport,f=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?g:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!r(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),u.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=b){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&l(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:n}=c(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const o=s?.call(this);n?.call(this,e),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const t=p(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const t=this.properties,e=[...h(t),...d(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(a(t))}else void 0!==t&&e.push(a(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(e)i.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of s){const s=document.createElement("style"),n=t.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=e.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),n="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=s;const o=n.fromAttribute(e,t.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(t,e,i,s=!1,n){if(void 0!==t){const o=this.constructor;if(!1===s&&(n=this[t]),i??=o.getPropertyOptions(t),!((i.hasChanged??y)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),!0!==n||void 0!==o)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,m?.({ReactiveElement:w}),(u.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=t=>t,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:t=>t}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,P=`<${D}>`,T=document,R=()=>T.createComment(""),I=t=>null===t||"object"!=typeof t&&"function"!=typeof t,A=Array.isArray,F="[ \t\n\f\r]",z=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,E=/-->/g,O=/>/g,N=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),W=q(1),j=q(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=T.createTreeWalker(T,129);function Y(t,e){if(!A(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(e):e}const X=(t,e)=>{const i=t.length-1,s=[];let n,o=2===e?"":3===e?"":"",a=z;for(let e=0;e"===l[0]?(a=n??z,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?N:'"'===l[3]?L:H):a===L||a===H?a=N:a===E||a===O?a=z:(a=N,n=void 0);const d=a===N&&t[e+1].startsWith("/>")?" ":"";o+=a===z?i+P:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?e:d)}return[Y(t,o+(t[i]||"")+(2===e?"":3===e?"":"")),s]};class J{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let n=0,o=0;const a=t.length-1,r=this.parts,[l,c]=X(t,e);if(this.el=J.createElement(l,i),K.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==G&&I(this._$AH)?this._$AA.nextSibling.data=t:this.T(T.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=J.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new Q(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=V.get(t.strings);return void 0===e&&V.set(t.strings,e=new J(t)),e}k(t){A(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const n of t)s===e.length?e.push(i=new tt(this.O(R()),this.O(R()),this,this.options)):i=e[s],i._$AI(n),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=G}_$AI(t,e=this,i,s){const n=this.strings;let o=!1;if(void 0===n)t=Z(this,t,e,0),o=!I(t)||t!==this._$AH&&t!==U,o&&(this._$AH=t);else{const s=t;let a,r;for(t=n[0],a=0;a{const s=i?.renderBefore??e;let n=s._$litPart$;if(void 0===n){const t=i?.renderBefore??null;s._$litPart$=n=new tt(e.insertBefore(R(),t),t,void 0,i??{})}return n._$AI(t),n},ct=globalThis;let ht=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=lt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};ht._$litElement$=!0,ht.finalized=!0,ct.litElementHydrateSupport?.({LitElement:ht});const dt=ct.litElementPolyfillSupport;dt?.({LitElement:ht}),(ct.litElementVersions??=[]).push("4.2.2");const pt=2,ut=t=>(...e)=>({_$litDirective$:t,values:e});let _t=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};const gt={},mt=ut(class extends _t{constructor(){super(...arguments),this.ot=gt}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return U}else if(this.ot===e)return U;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}}),{I:ft}=at,vt=t=>t,yt=()=>document.createComment(""),bt=(t,e,i)=>{const s=t._$AA.parentNode,n=void 0===e?t._$AB:e._$AA;if(void 0===i){const e=s.insertBefore(yt(),n),o=s.insertBefore(yt(),n);i=new ft(e,o,t,t.options)}else{const e=i._$AB.nextSibling,o=i._$AM,a=o!==t;if(a){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||a){let t=i._$AA;for(;t!==e;){const e=vt(t).nextSibling;vt(s).insertBefore(t,n),t=e}}}return i},wt=(t,e,i=t)=>(t._$AI(e,i),t),kt={},xt=(t,e=kt)=>t._$AH=e,$t=t=>{t._$AR(),t._$AA.remove()},St=(t,e,i)=>{const s=new Map;for(let n=e;n<=i;n++)s.set(t[n],n);return s},Mt=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)throw Error("repeat() can only be used in text expressions")}dt(t,e,i){let s;void 0===i?i=e:void 0!==e&&(s=e);const n=[],o=[];let a=0;for(const e of t)n[a]=s?s(e,a):a,o[a]=i(e,a),a++;return{values:o,keys:n}}render(t,e,i){return this.dt(t,e,i).values}update(t,[e,i,s]){const n=(t=>t._$AH)(t),{values:o,keys:a}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=a,o;const r=this.ut??=[],l=[];let c,h,d=0,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(r[d]===a[u])l[u]=wt(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=wt(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(a,u,_),h=St(r,d,p)),c.has(r[d]))if(c.has(r[p])){const e=h.get(a[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){const t=n[d++];null!==t&&$t(t)}return this.ut=a,xt(t,l),U}}),Ct=new WeakMap;let Dt=0;class Pt extends ht{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Dt,this._focusInitial=()=>{const t=this._focusableElements(),e=t.find(t=>t.hasAttribute("autofocus"))||t[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");e?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=t=>{if("Escape"===t.key){t.preventDefault(),t.stopImmediatePropagation(),this._pruneOverlays();const e=this._overlays[this._overlays.length-1];return e?void this._closeOverlay(e,"escape"):void this._requestClose()}if("Tab"!==t.key||this._useHaDialog)return;const e=this.renderRoot.querySelector(".close"),i=e?[e,...this._focusableElements()]:this._focusableElements();if(!i.length)return t.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!t.shiftKey||s!==n&&i.includes(s)?t.shiftKey||s!==o||(t.preventDefault(),n.focus()):(t.preventDefault(),o.focus())},this._onFallbackCancel=t=>{t.preventDefault(),this._requestClose()},this._onFallbackClick=t=>{this.dismissOnScrim&&t.target===t.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const t=this.getRootNode();this._focusRoot=t;const e=Ct.get(t)||{dialogs:new Set,opener:this._opener};e.dialogs.add(this),Ct.set(t,e),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const t=[...this._overlays];this._overlays=[];for(const e of t.reverse())e.close("disconnect");const e=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=e?Ct.get(e):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),e&&s&&requestAnimationFrame(()=>{const t=Ct.get(e);if(!t)return;if(!t.dialogs.size)return t.opener?.isConnected&&t.opener.focus({preventScroll:!0}),void Ct.delete(e);const s=i?.closest("hp-dialog");i?.isConnected&&s&&t.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(t){if(super.firstUpdated(t),!this._useHaDialog){const t=this.renderRoot.querySelector("dialog");t&&!t.open&&t.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let t=document.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return t&&t!==document.body?t:null}_focusableElements(){const t=["[autofocus]","a[href]","button:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])","textarea:not([disabled])",'[contenteditable="true"]','[tabindex]:not([tabindex="-1"])'].join(","),e=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(t)&&e.push(n),n instanceof HTMLSlotElement){for(const t of n.assignedNodes({flatten:!0}))s(t);return}if(n.shadowRoot){for(const t of n.shadowRoot.childNodes)s(t);return}}for(const t of n.childNodes)s(t)}};for(const t of this.childNodes)s(t);const n=this.overlayPortal();return n&&s(n),e.filter(t=>{let e=t;for(;e;){const t=getComputedStyle(e);if(e.hidden||e.inert||"true"===e.getAttribute("aria-hidden")||"none"===t.display||"hidden"===t.visibility)return!1;if(e=e.assignedSlot||e.parentElement||(e.getRootNode()instanceof ShadowRoot?e.getRootNode().host:null),e===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(t=>t.owner.isConnected)}_closeOverlay(t,e){const i=this._overlays.findIndex(e=>e.token===t.token);i>=0&&this._overlays.splice(i,1),t.close(e)}registerOverlay(t){this._pruneOverlays();const e=this._overlays.find(e=>e.owner===t.owner);e&&this._overlays.splice(this._overlays.indexOf(e),1);const i=t.group||"transient";for(const t of[...this._overlays].reverse())t.group===i&&this._closeOverlay(t,"exclusive");const s={...t,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const t=this._overlays.findIndex(t=>t.token===s.token);t>=0&&this._overlays.splice(t,1)}}closeTransientOverlays(t="outside"){this._pruneOverlays();const e=[...this._overlays].filter(t=>"transient"===(t.group||"transient"));for(const i of e.reverse())this._closeOverlay(i,t);return e.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const t=W` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="e3aff3b20e29c35f36dd0015fc3ebac8b751cbe72b369f3c0de29eae7eaeb48e";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const i=this.t;if(e&&void 0===t){const e=void 0!==i&&1===i.length;e&&(t=s.get(i)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&s.set(i,t))}return t}toString(){return this.cssText}};const o=(t,...e)=>{const s=1===t.length?t[0]:e.reduce((e,i,s)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[s+1],t[0]);return new n(s,t,i)},a=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new n("string"==typeof t?t:t+"",void 0,i))(e)})(t):t,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.reactiveElementPolyfillSupport,f=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?g:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!r(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),u.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=b){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&l(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:n}=c(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const o=s?.call(this);n?.call(this,e),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const t=p(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const t=this.properties,e=[...h(t),...d(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(a(t))}else void 0!==t&&e.push(a(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(e)i.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of s){const s=document.createElement("style"),n=t.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=e.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),n="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=s;const o=n.fromAttribute(e,t.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(t,e,i,s=!1,n){if(void 0!==t){const o=this.constructor;if(!1===s&&(n=this[t]),i??=o.getPropertyOptions(t),!((i.hasChanged??y)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),!0!==n||void 0!==o)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,m?.({ReactiveElement:w}),(u.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=t=>t,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:t=>t}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,P=`<${D}>`,T=document,R=()=>T.createComment(""),I=t=>null===t||"object"!=typeof t&&"function"!=typeof t,A=Array.isArray,F="[ \t\n\f\r]",z=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,E=/-->/g,O=/>/g,N=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),W=q(1),j=q(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=T.createTreeWalker(T,129);function Y(t,e){if(!A(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(e):e}const X=(t,e)=>{const i=t.length-1,s=[];let n,o=2===e?"":3===e?"":"",a=z;for(let e=0;e"===l[0]?(a=n??z,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?N:'"'===l[3]?L:H):a===L||a===H?a=N:a===E||a===O?a=z:(a=N,n=void 0);const d=a===N&&t[e+1].startsWith("/>")?" ":"";o+=a===z?i+P:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?e:d)}return[Y(t,o+(t[i]||"")+(2===e?"":3===e?"":"")),s]};class J{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let n=0,o=0;const a=t.length-1,r=this.parts,[l,c]=X(t,e);if(this.el=J.createElement(l,i),K.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==G&&I(this._$AH)?this._$AA.nextSibling.data=t:this.T(T.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=J.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new Q(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=V.get(t.strings);return void 0===e&&V.set(t.strings,e=new J(t)),e}k(t){A(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const n of t)s===e.length?e.push(i=new tt(this.O(R()),this.O(R()),this,this.options)):i=e[s],i._$AI(n),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=G}_$AI(t,e=this,i,s){const n=this.strings;let o=!1;if(void 0===n)t=Z(this,t,e,0),o=!I(t)||t!==this._$AH&&t!==U,o&&(this._$AH=t);else{const s=t;let a,r;for(t=n[0],a=0;a{const s=i?.renderBefore??e;let n=s._$litPart$;if(void 0===n){const t=i?.renderBefore??null;s._$litPart$=n=new tt(e.insertBefore(R(),t),t,void 0,i??{})}return n._$AI(t),n},ct=globalThis;let ht=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=lt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};ht._$litElement$=!0,ht.finalized=!0,ct.litElementHydrateSupport?.({LitElement:ht});const dt=ct.litElementPolyfillSupport;dt?.({LitElement:ht}),(ct.litElementVersions??=[]).push("4.2.2");const pt=2,ut=t=>(...e)=>({_$litDirective$:t,values:e});let _t=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};const gt={},mt=ut(class extends _t{constructor(){super(...arguments),this.ot=gt}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return U}else if(this.ot===e)return U;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}}),{I:ft}=at,vt=t=>t,yt=()=>document.createComment(""),bt=(t,e,i)=>{const s=t._$AA.parentNode,n=void 0===e?t._$AB:e._$AA;if(void 0===i){const e=s.insertBefore(yt(),n),o=s.insertBefore(yt(),n);i=new ft(e,o,t,t.options)}else{const e=i._$AB.nextSibling,o=i._$AM,a=o!==t;if(a){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||a){let t=i._$AA;for(;t!==e;){const e=vt(t).nextSibling;vt(s).insertBefore(t,n),t=e}}}return i},wt=(t,e,i=t)=>(t._$AI(e,i),t),kt={},xt=(t,e=kt)=>t._$AH=e,$t=t=>{t._$AR(),t._$AA.remove()},St=(t,e,i)=>{const s=new Map;for(let n=e;n<=i;n++)s.set(t[n],n);return s},Mt=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)throw Error("repeat() can only be used in text expressions")}dt(t,e,i){let s;void 0===i?i=e:void 0!==e&&(s=e);const n=[],o=[];let a=0;for(const e of t)n[a]=s?s(e,a):a,o[a]=i(e,a),a++;return{values:o,keys:n}}render(t,e,i){return this.dt(t,e,i).values}update(t,[e,i,s]){const n=(t=>t._$AH)(t),{values:o,keys:a}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=a,o;const r=this.ut??=[],l=[];let c,h,d=0,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(r[d]===a[u])l[u]=wt(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=wt(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(a,u,_),h=St(r,d,p)),c.has(r[d]))if(c.has(r[p])){const e=h.get(a[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){const t=n[d++];null!==t&&$t(t)}return this.ut=a,xt(t,l),U}}),Ct=new WeakMap;let Dt=0;class Pt extends ht{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Dt,this._focusInitial=()=>{const t=this._focusableElements(),e=t.find(t=>t.hasAttribute("autofocus"))||t[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");e?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=t=>{if("Escape"===t.key){t.preventDefault(),t.stopImmediatePropagation(),this._pruneOverlays();const e=this._overlays[this._overlays.length-1];return e?void this._closeOverlay(e,"escape"):void this._requestClose()}if("Tab"!==t.key||this._useHaDialog)return;const e=this.renderRoot.querySelector(".close"),i=e?[e,...this._focusableElements()]:this._focusableElements();if(!i.length)return t.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!t.shiftKey||s!==n&&i.includes(s)?t.shiftKey||s!==o||(t.preventDefault(),n.focus()):(t.preventDefault(),o.focus())},this._onFallbackCancel=t=>{t.preventDefault(),this._requestClose()},this._onFallbackClick=t=>{this.dismissOnScrim&&t.target===t.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const t=this.getRootNode();this._focusRoot=t;const e=Ct.get(t)||{dialogs:new Set,opener:this._opener};e.dialogs.add(this),Ct.set(t,e),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const t=[...this._overlays];this._overlays=[];for(const e of t.reverse())e.close("disconnect");const e=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=e?Ct.get(e):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),e&&s&&requestAnimationFrame(()=>{const t=Ct.get(e);if(!t)return;if(!t.dialogs.size)return t.opener?.isConnected&&t.opener.focus({preventScroll:!0}),void Ct.delete(e);const s=i?.closest("hp-dialog");i?.isConnected&&s&&t.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(t){if(super.firstUpdated(t),!this._useHaDialog){const t=this.renderRoot.querySelector("dialog");t&&!t.open&&t.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let t=document.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return t&&t!==document.body?t:null}_focusableElements(){const t=["[autofocus]","a[href]","button:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])","textarea:not([disabled])",'[contenteditable="true"]','[tabindex]:not([tabindex="-1"])'].join(","),e=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(t)&&e.push(n),n instanceof HTMLSlotElement){for(const t of n.assignedNodes({flatten:!0}))s(t);return}if(n.shadowRoot){for(const t of n.shadowRoot.childNodes)s(t);return}}for(const t of n.childNodes)s(t)}};for(const t of this.childNodes)s(t);const n=this.overlayPortal();return n&&s(n),e.filter(t=>{let e=t;for(;e;){const t=getComputedStyle(e);if(e.hidden||e.inert||"true"===e.getAttribute("aria-hidden")||"none"===t.display||"hidden"===t.visibility)return!1;if(e=e.assignedSlot||e.parentElement||(e.getRootNode()instanceof ShadowRoot?e.getRootNode().host:null),e===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(t=>t.owner.isConnected)}_closeOverlay(t,e){const i=this._overlays.findIndex(e=>e.token===t.token);i>=0&&this._overlays.splice(i,1),t.close(e)}registerOverlay(t){this._pruneOverlays();const e=this._overlays.find(e=>e.owner===t.owner);e&&this._overlays.splice(this._overlays.indexOf(e),1);const i=t.group||"transient";for(const t of[...this._overlays].reverse())t.group===i&&this._closeOverlay(t,"exclusive");const s={...t,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const t=this._overlays.findIndex(t=>t.token===s.token);t>=0&&this._overlays.splice(t,1)}}closeTransientOverlays(t="outside"){this._pruneOverlays();const e=[...this._overlays].filter(t=>"transient"===(t.group||"transient"));for(const i of e.reverse())this._closeOverlay(i,t);return e.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const t=W` ${this.icon?W``:G} ${this.title} `;return this._useHaDialog?W` ${c} - `}function Vp(t){return t<=40?"low":t<180?"mid":"high"}function Kp(t){return ai(t)}function Yp(t){return"static_icon"===t.display?"neutral":"alarm"===t.visual.status?"alarm":"unavailable"===t.visual.availability?"unavailable":t.lockState?t.lockState:"working"===t.visual.status?"working":"open"===t.visual.status?"open":"neutral"}jp.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",jp);const Xp={sourceKind:"none",visualSources:[],criticalSources:[],samples:[]};function Jp(t,e){const i=t?.entities?.[e],s=t?.states?.[e];return String(i?.name||i?.original_name||s?.attributes?.friendly_name||e)}function Zp(t,e){const i=t?.states?.[e];if(!i)return"";if("function"==typeof t?.formatEntityState)try{const e=t.formatEntityState(i);if("string"==typeof e&&e)return e}catch{}return String(i.state??"")}function Qp(t,e){if(e.virtual||"virtual"===e.bindingKind||"virtual"===e.marker?.binding)return"available";return(e.entities||[]).some(e=>{const i=String(t?.states?.[e]?.state??"").trim().toLowerCase();return""!==i&&"unknown"!==i&&"unavailable"!==i})?"available":"unavailable"}function tu(t,e,i,s){return{eid:e,role:i,name:Jp(t,e),state:String(t?.states?.[e]?.state??""),stateText:Zp(t,e),integrationDomain:t?.entities?.[e]?.platform||null,sample:s||cn(t,e)}}function eu(t,e,i=[e],s,n=t){const o=e.hidden&&e.userHidden?{...e,hidden:!1}:e;let a="none",r=[];const l=[...o.entities,...o.allEntities||[]].some(t=>t.startsWith("cover."))?{...o,tapAction:"cover"}:o,c=(h=Sd({hass:t,devices:i,device:l,lightSources:s,registryHass:n}),"cover"!==h?.semantics?null:h.targets[0]?.entityId||h.skippedTargets[0]?.entityId||null);var h;const d=ho(t,[o]),p=Zn(o.marker?.binding,o.marker?.controls??o.controls,o.entities),u=new Set(p.filter(t=>t.startsWith("marker:"))),_=!0===o.marker?.is_light||u.size>0?s||ho(t,i):d,g=_.filter(t=>t.device.id===o.id&&"controls"!==t.via),m=d.filter(t=>"controls"!==t.via),f=g.length?g:m,v=yn(o.marker),y=v?[...f]:[...d.filter(t=>"controls"===t.via),...f];if(u.size)for(const t of _){if(!u.has(t.key))continue;t.stateEids.length>0&&y.some(e=>e.stateEids.some(e=>t.stateEids.includes(e)))||y.some(e=>e.key===t.key)||y.push({...t,via:"controls",castsGlow:!1})}const b=Yn(n,o.entities);if(!!c&&("cover"===o.tapAction||o.primary?.startsWith("cover.")||b.some(t=>t.startsWith("cover."))))a="cover",r=[tu(t,c,"cover")];else if(y.length)a=!v&&y.some(t=>"controls"===t.via)?"controls":"light",r=y.map(i=>{const s="controls"===i.via?"control":"forced"===i.via?"forced_light":"light";if(!i.passive)return tu(t,i.eid,s);const n=i.on?"on":"off";return{eid:i.key,role:s,name:e.name,state:n,stateText:n,integrationDomain:null,sample:{eid:i.key,state:n,availability:"available",status:i.on?"working":"neutral",activity:"none",edge:"none"}}});else{const e=Yn(n,o.entities),i=e.length?e:o.entities.filter(e=>!!t?.states?.[e]);if(i.length){a="device_role";const e=hn(n===t?t:{...n,states:t?.states||{}},i,o.entities),s=i.some(t=>an(n,t));r=e.map(e=>{const i=s?rn(n,e.eid)?"power_gate":an(n,e.eid)?"lifecycle":"device_role":"device_role";return tu(t,e.eid,i,e)})}else o.primary&&(a="primary",r=[tu(t,o.primary,"primary")])}const w=[];for(const e of o.entities||[]){const i=cn(t,e);"alarm"!==i.status||r.some(t=>t.eid===e)||w.push(tu(t,e,"critical",i))}return{sourceKind:a,visualSources:r,criticalSources:w,samples:[...r,...w].map(t=>t.sample)}}function iu(t,e,i,s){if(e.virtual)return{source:null,text:null,fallback:"value_virtual"};if(s){const i=function(t,e){if(!0!==e.marker?.use_climate_temp)return null;for(const i of e.entities){if(!i.startsWith("climate."))continue;const e=Number(t?.states?.[i]?.attributes?.current_temperature);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(i)return{source:{kind:"temperature",eid:i.eid,attribute:"current_temperature",text:i.text},text:i.text,fallback:null};const s=function(t,e){if("mdi:thermometer"!==e.icon&&"mdi:air-filter"!==e.icon)return null;for(const i of e.entities){if(!Gn(t,i))continue;const e=Number(t?.states?.[i]?.state);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(s)return{source:{kind:"temperature",eid:s.eid,text:s.text},text:s.text,fallback:null};const n=function(t,e){if(!e.primary||!fo(t,e.primary))return null;const i=Number(t?.states?.[e.primary]?.state);return Number.isFinite(i)?{eid:e.primary,text:`${Math.round(i)}%`}:null}(t,e);if(n)return{source:{kind:"humidity",eid:n.eid,text:n.text},text:n.text,fallback:null}}const n=i.visualSources.filter(t=>!t.eid.startsWith("marker:"));let o=n.map(t=>t.eid);const a=n.find(t=>"power_gate"===t.role);if(a&&(o=[a.eid]),!o.length&&i.visualSources.some(t=>t.eid.startsWith("marker:"))&&(o=Yn(t,e.entities),!o.length&&e.primary&&t?.states?.[e.primary]&&(o=[e.primary])),o=[...new Set(o)],1!==o.length)return{source:null,text:null,fallback:o.length?"value_ambiguous_sources":"value_no_state"};const r=o[0],l=function(t,e){const i=t?.states?.[e];if(!i||null==i.state||""===String(i.state).trim())return{text:"",fallback:"value_no_state"};const s=i.state;if(!["string","number","boolean"].includes(typeof s))return{text:"",fallback:"value_non_scalar"};const n=String(s).trim().toLowerCase();if("unknown"===n||"unavailable"===n)return{text:"",fallback:"value_no_state"};const o=Ji(t,e);return o?{text:Zi(o,String(i.attributes?.unit_of_measurement||"")),fallback:null}:{text:"",fallback:"value_no_state"}}(t,r);return l.fallback?{source:null,text:null,fallback:l.fallback}:{source:{kind:"entity",eid:r,text:l.text},text:l.text,fallback:null}}function su(t,e,i){const s=t.marker?.binding||(t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:t.virtual?"virtual":""),n=[...e.visualSources.map(t=>`${t.role}:${t.eid}`),...e.criticalSources.map(t=>`critical:${t.eid}`)].sort(),o=i?`${i.kind}:${i.eid}:${i.attribute||""}`:"none";return[s,e.sourceKind,...n,`value:${o}`].join("\n")}function nu(t,e,i){return su(e,i||eu(t,e),null).replace(/\nvalue:none$/,"")}function ou(t){if(t.effectiveHidden)return[];if("static_icon"===t.display)return["static-icon"];const e=[],{visual:i}=t;return"alarm"===t.pulse.kind?e.push("alarm"):"unavailable"===i.availability?e.push("unavail"):"working"===i.status?e.push("on"):"open"===i.status&&e.push("open"),t.lockState&&e.push(`lock-${t.lockState}`),"none"!==t.pulse.reason&&"alarm"!==t.pulse.reason&&e.push("activity-"+t.pulse.reason),t.pulse.generation%2==0&&(e.push("pulse-gen2"),"short"===t.pulse.kind&&e.push("activity-gen2")),e}function au(t,e,i){const s=Bi(e.marker?.display),n="static_icon"===s,o=n&&!1===i.sourceDetails?Xp:eu(t,e,i.lightDevices||[e],i.lightSources,i.registryHass||t),a=e.bindingStatus,r="ha_disabled"===a?.kind,l="orphaned"===a?.kind,c=!0===e.userHidden||!0===e.marker?.hidden,h=r||c&&!i.designPreview,d=dn(o.samples),p=o.visualSources.find(t=>t.eid.startsWith("lock.")),u=p?["unlocked","open"].includes(p.state.toLowerCase())?"unlocked":"locked"===p.state.toLowerCase()?"locked":null:null;let _="controls"===o.sourceKind?{...d,availability:Qp(t,e)}:d;h||n?_={availability:"available",status:"neutral",activity:"none"}:"alarm"===d.status||i.liveStates||(_={availability:"available",status:"neutral",activity:"none"});const g=n&&!1===i.sourceDetails?{source:null,text:null,fallback:null}:iu(t,e,o,i.showTemperature),m=su(e,o,g.source),f=nu(t,e,o),v=i.activityRuntime,y=i.now??Date.now(),b=v?.expiresAt||(v?.flashTs?v.flashTs+3300:0);!n&&!h&&i.liveStates&&"alarm"!==d.status&&v?.sources===f&&v.flashTs&&v.flashKind&&b>y&&(_={..._,activity:v.flashKind});const w="icon_ripple"===s&&!h&&i.liveStates&&"alarm"!==_.status?_.activity:"none",k=n||h||!i.showTemperature?null:!0===e.marker?.use_climate_temp?mo(t,e.entities):"mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon?go(t,e.entities):null,x=!n&&!h&&i.showTemperature&&e.primary&&fo(t,e.primary)?vo(t,e.entities):null,$=n||h||!i.showSignal||e.virtual?null:_o(t,e.entities),S=i.lightSources||("derived_marker_state"===e.marker?.value_badge?.source?.kind?ho(t,i.lightDevices||[e]):[]),M=function(t,e,i){const s=null!=e.marker?.value_badge;if(i.effectiveHidden||"static_icon"===i.display)return null;const n=e.marker?.value_badge;if(s)return n?.enabled?n.source?{configured:!0,enabled:!0,position:n.position||"right",...Ho(t,e,n.source,i.markerStates)}:{configured:!0,enabled:!0,source:null,sourceLabel:"",text:"—",fullText:t?.localize?.("state.default.unavailable")||"Unavailable",position:n.position||"right",availability:"missing",isLqi:!1,tone:"default"}:null;if(!i.showTemperature||"value"===i.display)return null;const o=Lo(t,e);if(!o)return null;let a=null,r="default";if("entity_attribute"===o.kind&&"current_temperature"===o.attribute){const i=mo(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else if("mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon){const i=go(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else{const i=vo(t,e.entities);null!=i&&(a=`${i}%`),r="humidity"}return null==a?null:{configured:!1,enabled:!0,source:o,position:"right",sourceLabel:"entity_attribute"===o.kind?`${Eo(o.attribute)} · ${zo(t,o.entity_id)}`:"entity_state"===o.kind?zo(t,o.entity_id):"",text:a,fullText:a,availability:"available",isLqi:!1,tone:r}}(t,e,{showTemperature:i.showTemperature,showSignal:i.showSignal,display:s,effectiveHidden:h,markerStates:S.filter(t=>t.key.startsWith("marker:")).map(t=>({ref:t.key,on:t.on,name:t.device.name}))}),C=o.visualSources.find(t=>!t.eid.startsWith("marker:")),D="cover"===o.sourceKind?C?.eid:e.primary||C?.eid,P=D?t?.states?.[D]:null,T=!i.liveStates||n||h?e.icon:vs(e.icon,D?.split(".")[0],P?.attributes?.device_class,P?.state,!!e.marker?.icon),R=!i.liveStates||n||h?null:o.visualSources.filter(t=>!t.eid.startsWith("marker:")).map(e=>function(t){return t&&"on"===t.state?Ft(t.attributes?.rgb_color):null}(t?.states?.[e.eid])).find(t=>!!t)||null,I=Number(e.marker?.size)>0?Number(e.marker.size):1,A=Number(e.marker?.angle)||0,F=Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,z=Rt(e.marker?.ripple_color,null),E=n?null:z||R||null,O=function(t){const{display:e,visual:i,semanticActivity:s,liveStates:n,effectiveHidden:o,bindingUnavailable:a=!1,reducedMotion:r=!1}=t,l=Math.max(1,Math.trunc(t.shortGeneration||1)),c=Number.isFinite(t.diameterScale)?Math.max(1,Number(t.diameterScale)):1.5,h=t.color||function(t,e){return"presence"===e?"#1DC21D":"running"===e||"working"===t.status||"open"===t.status?"#F0A00C":"#0C82F0"}(i,s);if(o||a||"unavailable"===i.availability||"static_icon"===e)return Yo(l,h,c);if("alarm"===i.status)return{kind:"alarm",reason:"alarm",generation:l,expiresAt:null,color:"#F0410C",diameterScale:1.5,animated:!r,reducedMotionIndicator:"none"};if(!n||"icon_ripple"!==e)return Yo(l,h,c);const d=t.now??Date.now(),p=t.shortExpiresAt||null;return t.shortReason&&null!=p&&p>d?{kind:"short",reason:t.shortReason,generation:l,expiresAt:p,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:"presence"===s||"transition"===s||"running"===s?{kind:"continuous",reason:s,generation:l,expiresAt:null,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:Yo(l,h,c)}({display:s,visual:_,semanticActivity:d.activity,shortReason:v?.sources===f?v?.flashKind:null,shortGeneration:v?.gen,shortExpiresAt:v?.sources===f?b:null,now:y,liveStates:i.liveStates,effectiveHidden:h,bindingUnavailable:r||l,reducedMotion:i.reducedMotion,color:E,diameterScale:F}),N="value"!==s||h?null:g.text,H="ha_disabled"===a?.kind?a.reason:null,L=function(t,e,i,s,n,o,a,r){return o?"ha_disabled":a?"orphaned":"static_icon"===r?"static_icon":"alarm"===e.status?"alarm":n?"unavailable"===e.availability?"unavailable":"cover"===s?"cover_icon_state":"presence"===i?"presence":"event"===i?"event":"transition"===i?"transition":"working"===e.status?"icon_ripple"===r&&"none"!==i?"working_activity":"working":"open"===e.status?"open":(t.primary||"").startsWith("media_player.")?"media_neutral":"neutral":"live_states_disabled"}(e,_,w,o.sourceKind,i.liveStates,r,l,s),B=[];i.designPreview&&c&&B.push("hidden_design_preview"),n||!0!==e.marker?.vacuum?.live||B.push("vacuum_live_plan_only");const q=o.visualSources.some(e=>"power_gate"===e.role||rn(t,e.eid)),W=e.entities.filter(e=>e.startsWith("switch.")&&!t?.entities?.[e]?.entity_category).length;q&&W>1&&B.push("composite_power_source"),"icon_ripple"!==s&&"static_icon"!==s&&"alarm"!==d.status&&"none"!==d.activity&&B.push("activity_display_disabled");const j={binding:e.marker?.binding||(e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:e.virtual?"virtual":""),sourceKind:o.sourceKind,visualSources:o.visualSources,criticalSources:o.criticalSources,valueSource:g.source,sourceSignature:m,visual:_,lockState:u,display:s,icon:T,valueText:N,valueFullText:N,fallbackReason:"value"!==s||N?null:g.fallback,activity:w,activityGeneration:v?.gen||1,pulse:O,classes:[],tempText:null==k?null:String(k),humText:null==x?null:String(x),valueBadge:M,lqiText:null==$||M?.isLqi?null:String($),lqiColor:null==$?null:Kp($),lqiBand:null==$?null:Vp($),lightColor:R,scale:I,angle:A,rippleScale:F,rippleColor:E,userHidden:c,effectiveHidden:h,haDisabled:r,disabledReason:H,orphaned:l,vacuumLive:!n&&!0===e.marker?.vacuum?.live,explanation:{reason:L,notices:B}};return{...j,classes:ou(j)}}function ru(t,e=new WeakMap){if(null===t||"object"!=typeof t)return t;const i=t,s=e.get(i);if(s)return s;if(Array.isArray(t)){const s=[];e.set(i,s);for(const i of t)s.push(ru(i,e));return Object.freeze(s)}const n={};e.set(i,n);for(const[i,s]of Object.entries(t))"function"!=typeof s&&(n[i]=ru(s,e));return Object.freeze(n)}function lu(t){const e=new Map(t);let i;return i=Object.freeze({get size(){return e.size},get:t=>e.get(t),has:t=>e.has(t),entries:()=>e.entries(),keys:()=>e.keys(),values:()=>e.values(),forEach:(t,s)=>e.forEach((e,n)=>t.call(s,e,n,i)),[Symbol.iterator]:()=>e[Symbol.iterator]()}),i}function cu(t){const e=new Set(t.entityIds||[]),i=new Set(t.deviceIds||[]),s=new Set(t.areaIds||[]);for(const s of t.devices){for(const t of s.entities||[])e.add(t);s.primary&&e.add(s.primary);for(const t of s.controls||[])e.add(t);s.marker?.vacuum?.source&&e.add(s.marker.vacuum.source),"device"===s.bindingKind&&s.bindingRef&&i.add(s.bindingRef),"entity"===s.bindingKind&&s.bindingRef&&e.add(s.bindingRef)}const n={},o={};for(const[o,a]of Object.entries(t.hass?.entities||{})){const r=a?.device_id?t.hass?.devices?.[a.device_id]:null;(e.has(o)||a?.device_id&&i.has(a.device_id)||s.has(a?.area_id)||s.has(r?.area_id))&&(e.add(o),n[o]=a,a?.device_id&&i.add(a.device_id))}for(const e of i){const i=t.hass?.devices?.[e];i&&(o[e]=i)}const a={};for(const i of e){const e=t.hass?.states?.[i];e&&(a[i]=e)}const r=Object.freeze({states:ru(a),entities:ru(n),devices:ru(o),config:ru(t.hass?.config),locale:ru(t.hass?.locale),themes:ru(t.hass?.themes)});return Object.freeze({sourceSequence:t.sourceSequence,capturedAt:t.capturedAt??Date.now(),hass:r,devices:ru([...t.devices]),positions:lu([...t.positions||[]].map(([t,e])=>[t,Object.freeze({x:e.x,y:e.y})])),presentations:lu([...t.presentations].map(([t,e])=>[t,ru(e)])),facts:lu([...t.facts||[]].map(([t,e])=>[t,ru(e)]))})}const hu=(t,e)=>`${t}:${e?1:0}`;function du(t){return!Number.isFinite(t)||t<=0?2.25:t/2.5*2.25}function pu({openings:t,geometries:e,fillsByRoomId:i,idPrefix:s="data",groupClass:n="opening-tunnels",dataLayer:o="data"}){const a=t.map((t,n)=>{const o=e[n];if(!o)return G;const a=o.faces.find(t=>-1===t.side),r=o.faces.find(t=>1===t.side);if(!a||!r)return G;const l=i.get(a.roomId)||null,c=i.get(r.roomId)||null;if(!l&&!c)return G;const h=`${a.d} ${r.d}`,d=!!l&&!!c&&l.color===c.color&&l.opacity===c.opacity,p=`translate(${t.rx} ${t.ry}) rotate(${t.angle})`;if(d)return j``}function Vp(t){return t<=40?"low":t<180?"mid":"high"}function Kp(t){return ai(t)}function Yp(t){return"static_icon"===t.display?"neutral":"alarm"===t.visual.status?"alarm":"unavailable"===t.visual.availability?"unavailable":t.lockState?t.lockState:"working"===t.visual.status?"working":"open"===t.visual.status?"open":"neutral"}jp.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",jp);const Xp={sourceKind:"none",visualSources:[],criticalSources:[],samples:[]};function Jp(t,e){const i=t?.entities?.[e],s=t?.states?.[e];return String(i?.name||i?.original_name||s?.attributes?.friendly_name||e)}function Zp(t,e){const i=t?.states?.[e];if(!i)return"";if("function"==typeof t?.formatEntityState)try{const e=t.formatEntityState(i);if("string"==typeof e&&e)return e}catch{}return String(i.state??"")}function Qp(t,e){if(e.virtual||"virtual"===e.bindingKind||"virtual"===e.marker?.binding)return"available";return(e.entities||[]).some(e=>{const i=String(t?.states?.[e]?.state??"").trim().toLowerCase();return""!==i&&"unknown"!==i&&"unavailable"!==i})?"available":"unavailable"}function tu(t,e,i,s){return{eid:e,role:i,name:Jp(t,e),state:String(t?.states?.[e]?.state??""),stateText:Zp(t,e),integrationDomain:t?.entities?.[e]?.platform||null,sample:s||cn(t,e)}}function eu(t,e,i=[e],s,n=t){const o=e.hidden&&e.userHidden?{...e,hidden:!1}:e;let a="none",r=[];const l=[...o.entities,...o.allEntities||[]].some(t=>t.startsWith("cover."))?{...o,tapAction:"cover"}:o,c=(h=Sd({hass:t,devices:i,device:l,lightSources:s,registryHass:n}),"cover"!==h?.semantics?null:h.targets[0]?.entityId||h.skippedTargets[0]?.entityId||null);var h;const d=ho(t,[o]),p=Zn(o.marker?.binding,o.marker?.controls??o.controls,o.entities),u=new Set(p.filter(t=>t.startsWith("marker:"))),_=!0===o.marker?.is_light||u.size>0?s||ho(t,i):d,g=_.filter(t=>t.device.id===o.id&&"controls"!==t.via),m=d.filter(t=>"controls"!==t.via),f=g.length?g:m,v=yn(o.marker),y=v?[...f]:[...d.filter(t=>"controls"===t.via),...f];if(u.size)for(const t of _){if(!u.has(t.key))continue;t.stateEids.length>0&&y.some(e=>e.stateEids.some(e=>t.stateEids.includes(e)))||y.some(e=>e.key===t.key)||y.push({...t,via:"controls",castsGlow:!1})}const b=Yn(n,o.entities);if(!!c&&("cover"===o.tapAction||o.primary?.startsWith("cover.")||b.some(t=>t.startsWith("cover."))))a="cover",r=[tu(t,c,"cover")];else if(y.length)a=!v&&y.some(t=>"controls"===t.via)?"controls":"light",r=y.map(i=>{const s="controls"===i.via?"control":"forced"===i.via?"forced_light":"light";if(!i.passive)return tu(t,i.eid,s);const n=i.on?"on":"off";return{eid:i.key,role:s,name:e.name,state:n,stateText:n,integrationDomain:null,sample:{eid:i.key,state:n,availability:"available",status:i.on?"working":"neutral",activity:"none",edge:"none"}}});else{const e=Yn(n,o.entities),i=e.length?e:o.entities.filter(e=>!!t?.states?.[e]);if(i.length){a="device_role";const e=hn(n===t?t:{...n,states:t?.states||{}},i,o.entities),s=i.some(t=>an(n,t));r=e.map(e=>{const i=s?rn(n,e.eid)?"power_gate":an(n,e.eid)?"lifecycle":"device_role":"device_role";return tu(t,e.eid,i,e)})}else o.primary&&(a="primary",r=[tu(t,o.primary,"primary")])}const w=[];for(const e of o.entities||[]){const i=cn(t,e);"alarm"!==i.status||r.some(t=>t.eid===e)||w.push(tu(t,e,"critical",i))}return{sourceKind:a,visualSources:r,criticalSources:w,samples:[...r,...w].map(t=>t.sample)}}function iu(t,e,i,s){if(e.virtual)return{source:null,text:null,fallback:"value_virtual"};if(s){const i=function(t,e){if(!0!==e.marker?.use_climate_temp)return null;for(const i of e.entities){if(!i.startsWith("climate."))continue;const e=Number(t?.states?.[i]?.attributes?.current_temperature);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(i)return{source:{kind:"temperature",eid:i.eid,attribute:"current_temperature",text:i.text},text:i.text,fallback:null};const s=function(t,e){if("mdi:thermometer"!==e.icon&&"mdi:air-filter"!==e.icon)return null;for(const i of e.entities){if(!Gn(t,i))continue;const e=Number(t?.states?.[i]?.state);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(s)return{source:{kind:"temperature",eid:s.eid,text:s.text},text:s.text,fallback:null};const n=function(t,e){if(!e.primary||!fo(t,e.primary))return null;const i=Number(t?.states?.[e.primary]?.state);return Number.isFinite(i)?{eid:e.primary,text:`${Math.round(i)}%`}:null}(t,e);if(n)return{source:{kind:"humidity",eid:n.eid,text:n.text},text:n.text,fallback:null}}const n=i.visualSources.filter(t=>!t.eid.startsWith("marker:"));let o=n.map(t=>t.eid);const a=n.find(t=>"power_gate"===t.role);if(a&&(o=[a.eid]),!o.length&&i.visualSources.some(t=>t.eid.startsWith("marker:"))&&(o=Yn(t,e.entities),!o.length&&e.primary&&t?.states?.[e.primary]&&(o=[e.primary])),o=[...new Set(o)],1!==o.length)return{source:null,text:null,fallback:o.length?"value_ambiguous_sources":"value_no_state"};const r=o[0],l=function(t,e){const i=t?.states?.[e];if(!i||null==i.state||""===String(i.state).trim())return{text:"",fallback:"value_no_state"};const s=i.state;if(!["string","number","boolean"].includes(typeof s))return{text:"",fallback:"value_non_scalar"};const n=String(s).trim().toLowerCase();if("unknown"===n||"unavailable"===n)return{text:"",fallback:"value_no_state"};const o=Ji(t,e);return o?{text:Zi(o,String(i.attributes?.unit_of_measurement||"")),fallback:null}:{text:"",fallback:"value_no_state"}}(t,r);return l.fallback?{source:null,text:null,fallback:l.fallback}:{source:{kind:"entity",eid:r,text:l.text},text:l.text,fallback:null}}function su(t,e,i){const s=t.marker?.binding||(t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:t.virtual?"virtual":""),n=[...e.visualSources.map(t=>`${t.role}:${t.eid}`),...e.criticalSources.map(t=>`critical:${t.eid}`)].sort(),o=i?`${i.kind}:${i.eid}:${i.attribute||""}`:"none";return[s,e.sourceKind,...n,`value:${o}`].join("\n")}function nu(t,e,i){return su(e,i||eu(t,e),null).replace(/\nvalue:none$/,"")}function ou(t){if(t.effectiveHidden)return[];if("static_icon"===t.display)return["static-icon"];const e=[],{visual:i}=t;return"alarm"===t.pulse.kind?e.push("alarm"):"unavailable"===i.availability?e.push("unavail"):"working"===i.status?e.push("on"):"open"===i.status&&e.push("open"),t.lockState&&e.push(`lock-${t.lockState}`),"none"!==t.pulse.reason&&"alarm"!==t.pulse.reason&&e.push("activity-"+t.pulse.reason),t.pulse.generation%2==0&&(e.push("pulse-gen2"),"short"===t.pulse.kind&&e.push("activity-gen2")),e}function au(t,e,i){const s=Bi(e.marker?.display),n="static_icon"===s,o=n&&!1===i.sourceDetails?Xp:eu(t,e,i.lightDevices||[e],i.lightSources,i.registryHass||t),a=e.bindingStatus,r="ha_disabled"===a?.kind,l="orphaned"===a?.kind,c=!0===e.userHidden||!0===e.marker?.hidden,h=r||c&&!i.designPreview,d=dn(o.samples),p=o.visualSources.find(t=>t.eid.startsWith("lock.")),u=p?["unlocked","open"].includes(p.state.toLowerCase())?"unlocked":"locked"===p.state.toLowerCase()?"locked":null:null,_=!yn(e.marker)&&Zn(e.marker?.binding,e.marker?.controls??e.controls,e.entities).length>0;let g="controls"===o.sourceKind||_&&"light"!==o.sourceKind&&"cover"!==o.sourceKind?{...d,availability:Qp(t,e)}:d;h||n?g={availability:"available",status:"neutral",activity:"none"}:"alarm"===d.status||i.liveStates||(g={availability:"available",status:"neutral",activity:"none"});const m=n&&!1===i.sourceDetails?{source:null,text:null,fallback:null}:iu(t,e,o,i.showTemperature),f=su(e,o,m.source),v=nu(t,e,o),y=i.activityRuntime,b=i.now??Date.now(),w=y?.expiresAt||(y?.flashTs?y.flashTs+3300:0);!n&&!h&&i.liveStates&&"alarm"!==d.status&&y?.sources===v&&y.flashTs&&y.flashKind&&w>b&&(g={...g,activity:y.flashKind});const k="icon_ripple"===s&&!h&&i.liveStates&&"alarm"!==g.status?g.activity:"none",x=n||h||!i.showTemperature?null:!0===e.marker?.use_climate_temp?mo(t,e.entities):"mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon?go(t,e.entities):null,$=!n&&!h&&i.showTemperature&&e.primary&&fo(t,e.primary)?vo(t,e.entities):null,S=n||h||!i.showSignal||e.virtual?null:_o(t,e.entities),M=i.lightSources||("derived_marker_state"===e.marker?.value_badge?.source?.kind?ho(t,i.lightDevices||[e]):[]),C=function(t,e,i){const s=null!=e.marker?.value_badge;if(i.effectiveHidden||"static_icon"===i.display)return null;const n=e.marker?.value_badge;if(s)return n?.enabled?n.source?{configured:!0,enabled:!0,position:n.position||"right",...Ho(t,e,n.source,i.markerStates)}:{configured:!0,enabled:!0,source:null,sourceLabel:"",text:"—",fullText:t?.localize?.("state.default.unavailable")||"Unavailable",position:n.position||"right",availability:"missing",isLqi:!1,tone:"default"}:null;if(!i.showTemperature||"value"===i.display)return null;const o=Lo(t,e);if(!o)return null;let a=null,r="default";if("entity_attribute"===o.kind&&"current_temperature"===o.attribute){const i=mo(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else if("mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon){const i=go(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else{const i=vo(t,e.entities);null!=i&&(a=`${i}%`),r="humidity"}return null==a?null:{configured:!1,enabled:!0,source:o,position:"right",sourceLabel:"entity_attribute"===o.kind?`${Eo(o.attribute)} · ${zo(t,o.entity_id)}`:"entity_state"===o.kind?zo(t,o.entity_id):"",text:a,fullText:a,availability:"available",isLqi:!1,tone:r}}(t,e,{showTemperature:i.showTemperature,showSignal:i.showSignal,display:s,effectiveHidden:h,markerStates:M.filter(t=>t.key.startsWith("marker:")).map(t=>({ref:t.key,on:t.on,name:t.device.name}))}),D=o.visualSources.find(t=>!t.eid.startsWith("marker:")),P="cover"===o.sourceKind?D?.eid:e.primary||D?.eid,T=P?t?.states?.[P]:null,R=!i.liveStates||n||h?e.icon:vs(e.icon,P?.split(".")[0],T?.attributes?.device_class,T?.state,!!e.marker?.icon),I=!i.liveStates||n||h?null:o.visualSources.filter(t=>!t.eid.startsWith("marker:")).map(e=>function(t){return t&&"on"===t.state?Ft(t.attributes?.rgb_color):null}(t?.states?.[e.eid])).find(t=>!!t)||null,A=Number(e.marker?.size)>0?Number(e.marker.size):1,F=Number(e.marker?.angle)||0,z=Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,E=Rt(e.marker?.ripple_color,null),O=n?null:E||I||null,N=function(t){const{display:e,visual:i,semanticActivity:s,liveStates:n,effectiveHidden:o,bindingUnavailable:a=!1,reducedMotion:r=!1}=t,l=Math.max(1,Math.trunc(t.shortGeneration||1)),c=Number.isFinite(t.diameterScale)?Math.max(1,Number(t.diameterScale)):1.5,h=t.color||function(t,e){return"presence"===e?"#1DC21D":"running"===e||"working"===t.status||"open"===t.status?"#F0A00C":"#0C82F0"}(i,s);if(o||a||"unavailable"===i.availability||"static_icon"===e)return Yo(l,h,c);if("alarm"===i.status)return{kind:"alarm",reason:"alarm",generation:l,expiresAt:null,color:"#F0410C",diameterScale:1.5,animated:!r,reducedMotionIndicator:"none"};if(!n||"icon_ripple"!==e)return Yo(l,h,c);const d=t.now??Date.now(),p=t.shortExpiresAt||null;return t.shortReason&&null!=p&&p>d?{kind:"short",reason:t.shortReason,generation:l,expiresAt:p,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:"presence"===s||"transition"===s||"running"===s?{kind:"continuous",reason:s,generation:l,expiresAt:null,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:Yo(l,h,c)}({display:s,visual:g,semanticActivity:d.activity,shortReason:y?.sources===v?y?.flashKind:null,shortGeneration:y?.gen,shortExpiresAt:y?.sources===v?w:null,now:b,liveStates:i.liveStates,effectiveHidden:h,bindingUnavailable:r||l,reducedMotion:i.reducedMotion,color:O,diameterScale:z}),H="value"!==s||h?null:m.text,L="ha_disabled"===a?.kind?a.reason:null,B=function(t,e,i,s,n,o,a,r){return o?"ha_disabled":a?"orphaned":"static_icon"===r?"static_icon":"alarm"===e.status?"alarm":n?"unavailable"===e.availability?"unavailable":"cover"===s?"cover_icon_state":"presence"===i?"presence":"event"===i?"event":"transition"===i?"transition":"working"===e.status?"icon_ripple"===r&&"none"!==i?"working_activity":"working":"open"===e.status?"open":(t.primary||"").startsWith("media_player.")?"media_neutral":"neutral":"live_states_disabled"}(e,g,k,o.sourceKind,i.liveStates,r,l,s),q=[];i.designPreview&&c&&q.push("hidden_design_preview"),n||!0!==e.marker?.vacuum?.live||q.push("vacuum_live_plan_only");const W=o.visualSources.some(e=>"power_gate"===e.role||rn(t,e.eid)),j=e.entities.filter(e=>e.startsWith("switch.")&&!t?.entities?.[e]?.entity_category).length;W&&j>1&&q.push("composite_power_source"),"icon_ripple"!==s&&"static_icon"!==s&&"alarm"!==d.status&&"none"!==d.activity&&q.push("activity_display_disabled");const U={binding:e.marker?.binding||(e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:e.virtual?"virtual":""),sourceKind:o.sourceKind,visualSources:o.visualSources,criticalSources:o.criticalSources,valueSource:m.source,sourceSignature:f,visual:g,lockState:u,display:s,icon:R,valueText:H,valueFullText:H,fallbackReason:"value"!==s||H?null:m.fallback,activity:k,activityGeneration:y?.gen||1,pulse:N,classes:[],tempText:null==x?null:String(x),humText:null==$?null:String($),valueBadge:C,lqiText:null==S||C?.isLqi?null:String(S),lqiColor:null==S?null:Kp(S),lqiBand:null==S?null:Vp(S),lightColor:I,scale:A,angle:F,rippleScale:z,rippleColor:O,userHidden:c,effectiveHidden:h,haDisabled:r,disabledReason:L,orphaned:l,vacuumLive:!n&&!0===e.marker?.vacuum?.live,explanation:{reason:B,notices:q}};return{...U,classes:ou(U)}}function ru(t,e=new WeakMap){if(null===t||"object"!=typeof t)return t;const i=t,s=e.get(i);if(s)return s;if(Array.isArray(t)){const s=[];e.set(i,s);for(const i of t)s.push(ru(i,e));return Object.freeze(s)}const n={};e.set(i,n);for(const[i,s]of Object.entries(t))"function"!=typeof s&&(n[i]=ru(s,e));return Object.freeze(n)}function lu(t){const e=new Map(t);let i;return i=Object.freeze({get size(){return e.size},get:t=>e.get(t),has:t=>e.has(t),entries:()=>e.entries(),keys:()=>e.keys(),values:()=>e.values(),forEach:(t,s)=>e.forEach((e,n)=>t.call(s,e,n,i)),[Symbol.iterator]:()=>e[Symbol.iterator]()}),i}function cu(t){const e=new Set(t.entityIds||[]),i=new Set(t.deviceIds||[]),s=new Set(t.areaIds||[]);for(const s of t.devices){for(const t of s.entities||[])e.add(t);s.primary&&e.add(s.primary);for(const t of s.controls||[])e.add(t);s.marker?.vacuum?.source&&e.add(s.marker.vacuum.source),"device"===s.bindingKind&&s.bindingRef&&i.add(s.bindingRef),"entity"===s.bindingKind&&s.bindingRef&&e.add(s.bindingRef)}const n={},o={};for(const[o,a]of Object.entries(t.hass?.entities||{})){const r=a?.device_id?t.hass?.devices?.[a.device_id]:null;(e.has(o)||a?.device_id&&i.has(a.device_id)||s.has(a?.area_id)||s.has(r?.area_id))&&(e.add(o),n[o]=a,a?.device_id&&i.add(a.device_id))}for(const e of i){const i=t.hass?.devices?.[e];i&&(o[e]=i)}const a={};for(const i of e){const e=t.hass?.states?.[i];e&&(a[i]=e)}const r=Object.freeze({states:ru(a),entities:ru(n),devices:ru(o),config:ru(t.hass?.config),locale:ru(t.hass?.locale),themes:ru(t.hass?.themes)});return Object.freeze({sourceSequence:t.sourceSequence,capturedAt:t.capturedAt??Date.now(),hass:r,devices:ru([...t.devices]),positions:lu([...t.positions||[]].map(([t,e])=>[t,Object.freeze({x:e.x,y:e.y})])),presentations:lu([...t.presentations].map(([t,e])=>[t,ru(e)])),facts:lu([...t.facts||[]].map(([t,e])=>[t,ru(e)]))})}const hu=(t,e)=>`${t}:${e?1:0}`;function du(t){return!Number.isFinite(t)||t<=0?2.25:t/2.5*2.25}function pu({openings:t,geometries:e,fillsByRoomId:i,idPrefix:s="data",groupClass:n="opening-tunnels",dataLayer:o="data"}){const a=t.map((t,n)=>{const o=e[n];if(!o)return G;const a=o.faces.find(t=>-1===t.side),r=o.faces.find(t=>1===t.side);if(!a||!r)return G;const l=i.get(a.roomId)||null,c=i.get(r.roomId)||null;if(!l&&!c)return G;const h=`${a.d} ${r.d}`,d=!!l&&!!c&&l.color===c.color&&l.opacity===c.opacity,p=`translate(${t.rx} ${t.ry}) rotate(${t.angle})`;if(d)return j``;const u=o.maxY-o.minY;if(!(u>0))return G;const _=`${(100*Math.max(0,Math.min(1,-o.minY/u))).toFixed(6)}%`,g=l||{color:"#000000",opacity:0},m=c||{color:"#000000",opacity:0},f=`hp-opening-tunnel-${s.replace(/[^a-zA-Z0-9_-]/g,"-")}-${n}`;return j`${this._t("btn.close")} - `}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=zi(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),a={id:i,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=im(t.glowRadius);return null==e||e<=0?null:Math.round(this._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:t.hideFromPlan,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(a.space=e?.space||("virtual"===t.binding?this._space:null),a.area=e?.area||null,a.room_id=e?.roomId||null),a}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,...i}=t;return So({...i,markers:[e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return Sd({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Cd(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:wd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),a=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!a,valueBadgeSource:a,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),a=this._effectiveMarkerTapAction(t,o),r=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===a&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?au(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:r?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),P=o?to(o):[],T=o&&eo(o)||"",R=!!t.lightEntity&&!P.includes(t.lightEntity),I=o?md(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===a?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,z=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",E=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W``}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=zi(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),a={id:i,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=im(t.glowRadius);return null==e||e<=0?null:Math.round(this._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:t.hideFromPlan,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(a.space=e?.space||("virtual"===t.binding?this._space:null),a.area=e?.area||null,a.room_id=e?.roomId||null),a}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${Ph(this._markers)}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,siblingMarkers:i=[],...s}=t;return So({...s,markers:[...i.filter(t=>t.id!==e.id),e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,siblingMarkers:this._markers,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return Sd({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Cd(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:wd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),a=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!a,valueBadgeSource:a,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),a=this._effectiveMarkerTapAction(t,o),r=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===a&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?au(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:r?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),P=o?to(o):[],T=o&&eo(o)||"",R=!!t.lightEntity&&!P.includes(t.lightEntity),I=o?md(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===a?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,z=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",E=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W`this._markerDialog=null}>
diff --git a/demo/smoke_wireless_controller_parity.mjs b/demo/smoke_wireless_controller_parity.mjs new file mode 100644 index 00000000..0ba41bf0 --- /dev/null +++ b/demo/smoke_wireless_controller_parity.mjs @@ -0,0 +1,162 @@ +// #274: a wireless controller whose event is `unknown` still has live +// battery/LQI/update siblings. A deleted standalone marker for its display +// source used to constrain the saved plan roster but disappear from +// deviceFromMarkerDraft(), so plan and preview classified the same marker +// differently and controllerAvailability() was skipped on the saved face. +import { launch, checkAll, finish } from './serve.mjs'; + +const { page, browser } = await launch(); +const out = await page.evaluate(async () => { + const result = {}; + const c = window.__card; + const sr = () => c.shadowRoot || c.renderRoot; + const room = c._spaceModel().rooms.find((item) => item.id && item.area); + const deviceId = 'issue-274-wireless'; + const markerId = 'issue-274-marker'; + const tombstoneId = 'issue-274-target-tombstone'; + const target = 'light.floor_lamp'; + const own = [ + 'event.issue_274_action', + 'sensor.issue_274_battery', + 'sensor.issue_274_linkquality', + 'update.issue_274', + ]; + const marker = { + id: markerId, + binding: `device:${deviceId}`, + name: 'Issue 274 wireless switch', + icon: 'mdi:light-switch', + tap_action: 'toggle', + controls: [target], + space: c._space, + area: room.area, + }; + const tombstone = { + id: tombstoneId, + binding: `entity:${target}`, + removed: true, + hidden: true, + }; + + c.hass = { + ...c.hass, + devices: { + ...c.hass.devices, + [deviceId]: { + id: deviceId, + name: 'Issue 274 wireless switch', + model: 'Wireless switch', + area_id: room.area, + identifiers: [['demo', deviceId]], + entry_type: null, + via_device_id: null, + }, + }, + entities: { + ...c.hass.entities, + [own[0]]: { entity_id: own[0], device_id: deviceId, platform: 'demo' }, + [own[1]]: { + entity_id: own[1], device_id: deviceId, platform: 'demo', + entity_category: 'diagnostic', + }, + [own[2]]: { + entity_id: own[2], device_id: deviceId, platform: 'demo', + entity_category: 'diagnostic', + }, + [own[3]]: { + entity_id: own[3], device_id: deviceId, platform: 'demo', + entity_category: 'config', + }, + }, + states: { + ...c.hass.states, + [own[0]]: { entity_id: own[0], state: 'unknown', attributes: {} }, + [own[1]]: { + entity_id: own[1], state: '100', + attributes: { device_class: 'battery', unit_of_measurement: '%' }, + }, + [own[2]]: { + entity_id: own[2], state: '164', + attributes: { unit_of_measurement: 'lqi' }, + }, + [own[3]]: { entity_id: own[3], state: 'off', attributes: {} }, + [target]: { ...c.hass.states[target], state: 'off' }, + }, + }; + c._serverCfg = { + ...c._serverCfg, + markers: [ + ...(c._serverCfg.markers || []).filter((item) => + ![markerId, tombstoneId].includes(item.id)), + marker, + tombstone, + ], + }; + c._layout = { + ...c._layout, + [markerId]: { s: c._space, x: 0.5, y: 0.5 }, + }; + c._regSignature = ''; + c._maybeRebuildDevices(); + c.requestUpdate(); + await c.updateComplete; + + const controller = () => c._devices.find((item) => item.id === markerId); + result.savedControllerBuilt = !!controller(); + result.savedRosterHasAllSiblings = JSON.stringify(controller()?.entities) === JSON.stringify(own); + result.deletedStandaloneTargetIsRuntimeFiltered = controller()?.controls?.length === 0; + + c._setMode('view'); + await c.updateComplete; + const savedPresentation = c._devicePresentation(controller(), true); + const planElement = sr().querySelector(`.dev[data-id="${markerId}"]`); + result.planAvailableNeutral = savedPresentation.visual.availability === 'available' + && savedPresentation.visual.status === 'neutral' + && !savedPresentation.classes.includes('unavail'); + result.planKeepsLiveLqi = savedPresentation.lqiText === '164' + && planElement?.textContent?.includes('164'); + result.planDomAgrees = planElement?.getAttribute('data-state') === 'neutral' + && !planElement?.classList.contains('unavail'); + + c._setMode('devices'); + await c.updateComplete; + c._openMarkerDialog(controller()); + await c.updateComplete; + const previewDevice = c._markerPreviewDevice(c._markerDialog); + const preview = sr().querySelector('hp-device-preview'); + await preview?.updateComplete; + result.previewHonoursFullMarkerRoster = previewDevice?.controls?.length === 0; + result.previewMatchesPlan = preview?.presentation?.sourceKind === savedPresentation.sourceKind + && JSON.stringify(preview?.presentation?.visual) === JSON.stringify(savedPresentation.visual) + && JSON.stringify(preview?.presentation?.classes) === JSON.stringify(savedPresentation.classes) + && preview?.presentation?.lqiText === savedPresentation.lqiText; + result.previewTextIsNotUnavailable = !preview?.shadowRoot?.textContent?.includes('Unavailable'); + + // Remove only the standalone marker tombstone: the configured group is now + // active again, and both surfaces must follow its working state together. + c._serverCfg = { + ...c._serverCfg, + markers: c._serverCfg.markers.filter((item) => item.id !== tombstoneId), + }; + c.hass = { + ...c.hass, + states: { ...c.hass.states, [target]: { ...c.hass.states[target], state: 'on' } }, + }; + c._regSignature = ''; + c._maybeRebuildDevices(); + c.requestUpdate(); + await c.updateComplete; + const activePresentation = c._devicePresentation(controller(), true, true); + const activePreviewDevice = c._markerPreviewDevice(c._markerDialog); + const activePreview = sr().querySelector('hp-device-preview'); + await activePreview?.updateComplete; + result.activeTargetRestoredOnBothRosters = JSON.stringify(controller()?.controls) === JSON.stringify([target]) + && JSON.stringify(activePreviewDevice?.controls) === JSON.stringify([target]); + result.activeTargetWorksOnBothSurfaces = activePresentation.visual.status === 'working' + && activePreview?.presentation?.visual?.status === 'working'; + + return result; +}); + +checkAll(out); +await finish(browser, out); diff --git a/dist/houseplan-card.js b/dist/houseplan-card.js index 9d8ef24f..fe4dbdb8 100755 --- a/dist/houseplan-card.js +++ b/dist/houseplan-card.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="51295f426e16fc7696178d532a79c35dea2cdcf9a545c39f02c529aa2dbc5cd9";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const i=this.t;if(e&&void 0===t){const e=void 0!==i&&1===i.length;e&&(t=s.get(i)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&s.set(i,t))}return t}toString(){return this.cssText}};const o=(t,...e)=>{const s=1===t.length?t[0]:e.reduce((e,i,s)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[s+1],t[0]);return new n(s,t,i)},a=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new n("string"==typeof t?t:t+"",void 0,i))(e)})(t):t,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.reactiveElementPolyfillSupport,f=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?g:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!r(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),u.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=b){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&l(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:n}=c(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const o=s?.call(this);n?.call(this,e),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const t=p(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const t=this.properties,e=[...h(t),...d(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(a(t))}else void 0!==t&&e.push(a(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(e)i.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of s){const s=document.createElement("style"),n=t.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=e.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),n="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=s;const o=n.fromAttribute(e,t.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(t,e,i,s=!1,n){if(void 0!==t){const o=this.constructor;if(!1===s&&(n=this[t]),i??=o.getPropertyOptions(t),!((i.hasChanged??y)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),!0!==n||void 0!==o)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,m?.({ReactiveElement:w}),(u.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=t=>t,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:t=>t}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,P=`<${D}>`,T=document,R=()=>T.createComment(""),I=t=>null===t||"object"!=typeof t&&"function"!=typeof t,A=Array.isArray,F="[ \t\n\f\r]",z=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,E=/-->/g,O=/>/g,N=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),W=q(1),j=q(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=T.createTreeWalker(T,129);function Y(t,e){if(!A(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(e):e}const X=(t,e)=>{const i=t.length-1,s=[];let n,o=2===e?"":3===e?"":"",a=z;for(let e=0;e"===l[0]?(a=n??z,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?N:'"'===l[3]?L:H):a===L||a===H?a=N:a===E||a===O?a=z:(a=N,n=void 0);const d=a===N&&t[e+1].startsWith("/>")?" ":"";o+=a===z?i+P:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?e:d)}return[Y(t,o+(t[i]||"")+(2===e?"":3===e?"":"")),s]};class J{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let n=0,o=0;const a=t.length-1,r=this.parts,[l,c]=X(t,e);if(this.el=J.createElement(l,i),K.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==G&&I(this._$AH)?this._$AA.nextSibling.data=t:this.T(T.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=J.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new Q(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=V.get(t.strings);return void 0===e&&V.set(t.strings,e=new J(t)),e}k(t){A(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const n of t)s===e.length?e.push(i=new tt(this.O(R()),this.O(R()),this,this.options)):i=e[s],i._$AI(n),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=G}_$AI(t,e=this,i,s){const n=this.strings;let o=!1;if(void 0===n)t=Z(this,t,e,0),o=!I(t)||t!==this._$AH&&t!==U,o&&(this._$AH=t);else{const s=t;let a,r;for(t=n[0],a=0;a{const s=i?.renderBefore??e;let n=s._$litPart$;if(void 0===n){const t=i?.renderBefore??null;s._$litPart$=n=new tt(e.insertBefore(R(),t),t,void 0,i??{})}return n._$AI(t),n},ct=globalThis;let ht=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=lt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};ht._$litElement$=!0,ht.finalized=!0,ct.litElementHydrateSupport?.({LitElement:ht});const dt=ct.litElementPolyfillSupport;dt?.({LitElement:ht}),(ct.litElementVersions??=[]).push("4.2.2");const pt=2,ut=t=>(...e)=>({_$litDirective$:t,values:e});let _t=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};const gt={},mt=ut(class extends _t{constructor(){super(...arguments),this.ot=gt}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return U}else if(this.ot===e)return U;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}}),{I:ft}=at,vt=t=>t,yt=()=>document.createComment(""),bt=(t,e,i)=>{const s=t._$AA.parentNode,n=void 0===e?t._$AB:e._$AA;if(void 0===i){const e=s.insertBefore(yt(),n),o=s.insertBefore(yt(),n);i=new ft(e,o,t,t.options)}else{const e=i._$AB.nextSibling,o=i._$AM,a=o!==t;if(a){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||a){let t=i._$AA;for(;t!==e;){const e=vt(t).nextSibling;vt(s).insertBefore(t,n),t=e}}}return i},wt=(t,e,i=t)=>(t._$AI(e,i),t),kt={},xt=(t,e=kt)=>t._$AH=e,$t=t=>{t._$AR(),t._$AA.remove()},St=(t,e,i)=>{const s=new Map;for(let n=e;n<=i;n++)s.set(t[n],n);return s},Mt=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)throw Error("repeat() can only be used in text expressions")}dt(t,e,i){let s;void 0===i?i=e:void 0!==e&&(s=e);const n=[],o=[];let a=0;for(const e of t)n[a]=s?s(e,a):a,o[a]=i(e,a),a++;return{values:o,keys:n}}render(t,e,i){return this.dt(t,e,i).values}update(t,[e,i,s]){const n=(t=>t._$AH)(t),{values:o,keys:a}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=a,o;const r=this.ut??=[],l=[];let c,h,d=0,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(r[d]===a[u])l[u]=wt(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=wt(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(a,u,_),h=St(r,d,p)),c.has(r[d]))if(c.has(r[p])){const e=h.get(a[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){const t=n[d++];null!==t&&$t(t)}return this.ut=a,xt(t,l),U}}),Ct=new WeakMap;let Dt=0;class Pt extends ht{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Dt,this._focusInitial=()=>{const t=this._focusableElements(),e=t.find(t=>t.hasAttribute("autofocus"))||t[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");e?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=t=>{if("Escape"===t.key){t.preventDefault(),t.stopImmediatePropagation(),this._pruneOverlays();const e=this._overlays[this._overlays.length-1];return e?void this._closeOverlay(e,"escape"):void this._requestClose()}if("Tab"!==t.key||this._useHaDialog)return;const e=this.renderRoot.querySelector(".close"),i=e?[e,...this._focusableElements()]:this._focusableElements();if(!i.length)return t.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!t.shiftKey||s!==n&&i.includes(s)?t.shiftKey||s!==o||(t.preventDefault(),n.focus()):(t.preventDefault(),o.focus())},this._onFallbackCancel=t=>{t.preventDefault(),this._requestClose()},this._onFallbackClick=t=>{this.dismissOnScrim&&t.target===t.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const t=this.getRootNode();this._focusRoot=t;const e=Ct.get(t)||{dialogs:new Set,opener:this._opener};e.dialogs.add(this),Ct.set(t,e),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const t=[...this._overlays];this._overlays=[];for(const e of t.reverse())e.close("disconnect");const e=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=e?Ct.get(e):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),e&&s&&requestAnimationFrame(()=>{const t=Ct.get(e);if(!t)return;if(!t.dialogs.size)return t.opener?.isConnected&&t.opener.focus({preventScroll:!0}),void Ct.delete(e);const s=i?.closest("hp-dialog");i?.isConnected&&s&&t.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(t){if(super.firstUpdated(t),!this._useHaDialog){const t=this.renderRoot.querySelector("dialog");t&&!t.open&&t.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let t=document.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return t&&t!==document.body?t:null}_focusableElements(){const t=["[autofocus]","a[href]","button:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])","textarea:not([disabled])",'[contenteditable="true"]','[tabindex]:not([tabindex="-1"])'].join(","),e=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(t)&&e.push(n),n instanceof HTMLSlotElement){for(const t of n.assignedNodes({flatten:!0}))s(t);return}if(n.shadowRoot){for(const t of n.shadowRoot.childNodes)s(t);return}}for(const t of n.childNodes)s(t)}};for(const t of this.childNodes)s(t);const n=this.overlayPortal();return n&&s(n),e.filter(t=>{let e=t;for(;e;){const t=getComputedStyle(e);if(e.hidden||e.inert||"true"===e.getAttribute("aria-hidden")||"none"===t.display||"hidden"===t.visibility)return!1;if(e=e.assignedSlot||e.parentElement||(e.getRootNode()instanceof ShadowRoot?e.getRootNode().host:null),e===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(t=>t.owner.isConnected)}_closeOverlay(t,e){const i=this._overlays.findIndex(e=>e.token===t.token);i>=0&&this._overlays.splice(i,1),t.close(e)}registerOverlay(t){this._pruneOverlays();const e=this._overlays.find(e=>e.owner===t.owner);e&&this._overlays.splice(this._overlays.indexOf(e),1);const i=t.group||"transient";for(const t of[...this._overlays].reverse())t.group===i&&this._closeOverlay(t,"exclusive");const s={...t,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const t=this._overlays.findIndex(t=>t.token===s.token);t>=0&&this._overlays.splice(t,1)}}closeTransientOverlays(t="outside"){this._pruneOverlays();const e=[...this._overlays].filter(t=>"transient"===(t.group||"transient"));for(const i of e.reverse())this._closeOverlay(i,t);return e.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const t=W` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="e3aff3b20e29c35f36dd0015fc3ebac8b751cbe72b369f3c0de29eae7eaeb48e";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const i=this.t;if(e&&void 0===t){const e=void 0!==i&&1===i.length;e&&(t=s.get(i)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&s.set(i,t))}return t}toString(){return this.cssText}};const o=(t,...e)=>{const s=1===t.length?t[0]:e.reduce((e,i,s)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[s+1],t[0]);return new n(s,t,i)},a=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new n("string"==typeof t?t:t+"",void 0,i))(e)})(t):t,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.reactiveElementPolyfillSupport,f=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?g:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!r(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),u.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=b){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&l(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:n}=c(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const o=s?.call(this);n?.call(this,e),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const t=p(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const t=this.properties,e=[...h(t),...d(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(a(t))}else void 0!==t&&e.push(a(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(e)i.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of s){const s=document.createElement("style"),n=t.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=e.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),n="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=s;const o=n.fromAttribute(e,t.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(t,e,i,s=!1,n){if(void 0!==t){const o=this.constructor;if(!1===s&&(n=this[t]),i??=o.getPropertyOptions(t),!((i.hasChanged??y)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),!0!==n||void 0!==o)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,m?.({ReactiveElement:w}),(u.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=t=>t,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:t=>t}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,P=`<${D}>`,T=document,R=()=>T.createComment(""),I=t=>null===t||"object"!=typeof t&&"function"!=typeof t,A=Array.isArray,F="[ \t\n\f\r]",z=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,E=/-->/g,O=/>/g,N=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),W=q(1),j=q(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=T.createTreeWalker(T,129);function Y(t,e){if(!A(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(e):e}const X=(t,e)=>{const i=t.length-1,s=[];let n,o=2===e?"":3===e?"":"",a=z;for(let e=0;e"===l[0]?(a=n??z,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?N:'"'===l[3]?L:H):a===L||a===H?a=N:a===E||a===O?a=z:(a=N,n=void 0);const d=a===N&&t[e+1].startsWith("/>")?" ":"";o+=a===z?i+P:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?e:d)}return[Y(t,o+(t[i]||"")+(2===e?"":3===e?"":"")),s]};class J{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let n=0,o=0;const a=t.length-1,r=this.parts,[l,c]=X(t,e);if(this.el=J.createElement(l,i),K.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==G&&I(this._$AH)?this._$AA.nextSibling.data=t:this.T(T.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=J.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new Q(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=V.get(t.strings);return void 0===e&&V.set(t.strings,e=new J(t)),e}k(t){A(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const n of t)s===e.length?e.push(i=new tt(this.O(R()),this.O(R()),this,this.options)):i=e[s],i._$AI(n),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=G}_$AI(t,e=this,i,s){const n=this.strings;let o=!1;if(void 0===n)t=Z(this,t,e,0),o=!I(t)||t!==this._$AH&&t!==U,o&&(this._$AH=t);else{const s=t;let a,r;for(t=n[0],a=0;a{const s=i?.renderBefore??e;let n=s._$litPart$;if(void 0===n){const t=i?.renderBefore??null;s._$litPart$=n=new tt(e.insertBefore(R(),t),t,void 0,i??{})}return n._$AI(t),n},ct=globalThis;let ht=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=lt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};ht._$litElement$=!0,ht.finalized=!0,ct.litElementHydrateSupport?.({LitElement:ht});const dt=ct.litElementPolyfillSupport;dt?.({LitElement:ht}),(ct.litElementVersions??=[]).push("4.2.2");const pt=2,ut=t=>(...e)=>({_$litDirective$:t,values:e});let _t=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};const gt={},mt=ut(class extends _t{constructor(){super(...arguments),this.ot=gt}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return U}else if(this.ot===e)return U;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}}),{I:ft}=at,vt=t=>t,yt=()=>document.createComment(""),bt=(t,e,i)=>{const s=t._$AA.parentNode,n=void 0===e?t._$AB:e._$AA;if(void 0===i){const e=s.insertBefore(yt(),n),o=s.insertBefore(yt(),n);i=new ft(e,o,t,t.options)}else{const e=i._$AB.nextSibling,o=i._$AM,a=o!==t;if(a){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||a){let t=i._$AA;for(;t!==e;){const e=vt(t).nextSibling;vt(s).insertBefore(t,n),t=e}}}return i},wt=(t,e,i=t)=>(t._$AI(e,i),t),kt={},xt=(t,e=kt)=>t._$AH=e,$t=t=>{t._$AR(),t._$AA.remove()},St=(t,e,i)=>{const s=new Map;for(let n=e;n<=i;n++)s.set(t[n],n);return s},Mt=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)throw Error("repeat() can only be used in text expressions")}dt(t,e,i){let s;void 0===i?i=e:void 0!==e&&(s=e);const n=[],o=[];let a=0;for(const e of t)n[a]=s?s(e,a):a,o[a]=i(e,a),a++;return{values:o,keys:n}}render(t,e,i){return this.dt(t,e,i).values}update(t,[e,i,s]){const n=(t=>t._$AH)(t),{values:o,keys:a}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=a,o;const r=this.ut??=[],l=[];let c,h,d=0,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(r[d]===a[u])l[u]=wt(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=wt(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(a,u,_),h=St(r,d,p)),c.has(r[d]))if(c.has(r[p])){const e=h.get(a[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){const t=n[d++];null!==t&&$t(t)}return this.ut=a,xt(t,l),U}}),Ct=new WeakMap;let Dt=0;class Pt extends ht{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Dt,this._focusInitial=()=>{const t=this._focusableElements(),e=t.find(t=>t.hasAttribute("autofocus"))||t[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");e?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=t=>{if("Escape"===t.key){t.preventDefault(),t.stopImmediatePropagation(),this._pruneOverlays();const e=this._overlays[this._overlays.length-1];return e?void this._closeOverlay(e,"escape"):void this._requestClose()}if("Tab"!==t.key||this._useHaDialog)return;const e=this.renderRoot.querySelector(".close"),i=e?[e,...this._focusableElements()]:this._focusableElements();if(!i.length)return t.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!t.shiftKey||s!==n&&i.includes(s)?t.shiftKey||s!==o||(t.preventDefault(),n.focus()):(t.preventDefault(),o.focus())},this._onFallbackCancel=t=>{t.preventDefault(),this._requestClose()},this._onFallbackClick=t=>{this.dismissOnScrim&&t.target===t.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const t=this.getRootNode();this._focusRoot=t;const e=Ct.get(t)||{dialogs:new Set,opener:this._opener};e.dialogs.add(this),Ct.set(t,e),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const t=[...this._overlays];this._overlays=[];for(const e of t.reverse())e.close("disconnect");const e=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=e?Ct.get(e):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),e&&s&&requestAnimationFrame(()=>{const t=Ct.get(e);if(!t)return;if(!t.dialogs.size)return t.opener?.isConnected&&t.opener.focus({preventScroll:!0}),void Ct.delete(e);const s=i?.closest("hp-dialog");i?.isConnected&&s&&t.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(t){if(super.firstUpdated(t),!this._useHaDialog){const t=this.renderRoot.querySelector("dialog");t&&!t.open&&t.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let t=document.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return t&&t!==document.body?t:null}_focusableElements(){const t=["[autofocus]","a[href]","button:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])","textarea:not([disabled])",'[contenteditable="true"]','[tabindex]:not([tabindex="-1"])'].join(","),e=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(t)&&e.push(n),n instanceof HTMLSlotElement){for(const t of n.assignedNodes({flatten:!0}))s(t);return}if(n.shadowRoot){for(const t of n.shadowRoot.childNodes)s(t);return}}for(const t of n.childNodes)s(t)}};for(const t of this.childNodes)s(t);const n=this.overlayPortal();return n&&s(n),e.filter(t=>{let e=t;for(;e;){const t=getComputedStyle(e);if(e.hidden||e.inert||"true"===e.getAttribute("aria-hidden")||"none"===t.display||"hidden"===t.visibility)return!1;if(e=e.assignedSlot||e.parentElement||(e.getRootNode()instanceof ShadowRoot?e.getRootNode().host:null),e===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(t=>t.owner.isConnected)}_closeOverlay(t,e){const i=this._overlays.findIndex(e=>e.token===t.token);i>=0&&this._overlays.splice(i,1),t.close(e)}registerOverlay(t){this._pruneOverlays();const e=this._overlays.find(e=>e.owner===t.owner);e&&this._overlays.splice(this._overlays.indexOf(e),1);const i=t.group||"transient";for(const t of[...this._overlays].reverse())t.group===i&&this._closeOverlay(t,"exclusive");const s={...t,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const t=this._overlays.findIndex(t=>t.token===s.token);t>=0&&this._overlays.splice(t,1)}}closeTransientOverlays(t="outside"){this._pruneOverlays();const e=[...this._overlays].filter(t=>"transient"===(t.group||"transient"));for(const i of e.reverse())this._closeOverlay(i,t);return e.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const t=W` ${this.icon?W``:G} ${this.title} `;return this._useHaDialog?W` ${c} - `}function Vp(t){return t<=40?"low":t<180?"mid":"high"}function Kp(t){return ai(t)}function Yp(t){return"static_icon"===t.display?"neutral":"alarm"===t.visual.status?"alarm":"unavailable"===t.visual.availability?"unavailable":t.lockState?t.lockState:"working"===t.visual.status?"working":"open"===t.visual.status?"open":"neutral"}jp.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",jp);const Xp={sourceKind:"none",visualSources:[],criticalSources:[],samples:[]};function Jp(t,e){const i=t?.entities?.[e],s=t?.states?.[e];return String(i?.name||i?.original_name||s?.attributes?.friendly_name||e)}function Zp(t,e){const i=t?.states?.[e];if(!i)return"";if("function"==typeof t?.formatEntityState)try{const e=t.formatEntityState(i);if("string"==typeof e&&e)return e}catch{}return String(i.state??"")}function Qp(t,e){if(e.virtual||"virtual"===e.bindingKind||"virtual"===e.marker?.binding)return"available";return(e.entities||[]).some(e=>{const i=String(t?.states?.[e]?.state??"").trim().toLowerCase();return""!==i&&"unknown"!==i&&"unavailable"!==i})?"available":"unavailable"}function tu(t,e,i,s){return{eid:e,role:i,name:Jp(t,e),state:String(t?.states?.[e]?.state??""),stateText:Zp(t,e),integrationDomain:t?.entities?.[e]?.platform||null,sample:s||cn(t,e)}}function eu(t,e,i=[e],s,n=t){const o=e.hidden&&e.userHidden?{...e,hidden:!1}:e;let a="none",r=[];const l=[...o.entities,...o.allEntities||[]].some(t=>t.startsWith("cover."))?{...o,tapAction:"cover"}:o,c=(h=Sd({hass:t,devices:i,device:l,lightSources:s,registryHass:n}),"cover"!==h?.semantics?null:h.targets[0]?.entityId||h.skippedTargets[0]?.entityId||null);var h;const d=ho(t,[o]),p=Zn(o.marker?.binding,o.marker?.controls??o.controls,o.entities),u=new Set(p.filter(t=>t.startsWith("marker:"))),_=!0===o.marker?.is_light||u.size>0?s||ho(t,i):d,g=_.filter(t=>t.device.id===o.id&&"controls"!==t.via),m=d.filter(t=>"controls"!==t.via),f=g.length?g:m,v=yn(o.marker),y=v?[...f]:[...d.filter(t=>"controls"===t.via),...f];if(u.size)for(const t of _){if(!u.has(t.key))continue;t.stateEids.length>0&&y.some(e=>e.stateEids.some(e=>t.stateEids.includes(e)))||y.some(e=>e.key===t.key)||y.push({...t,via:"controls",castsGlow:!1})}const b=Yn(n,o.entities);if(!!c&&("cover"===o.tapAction||o.primary?.startsWith("cover.")||b.some(t=>t.startsWith("cover."))))a="cover",r=[tu(t,c,"cover")];else if(y.length)a=!v&&y.some(t=>"controls"===t.via)?"controls":"light",r=y.map(i=>{const s="controls"===i.via?"control":"forced"===i.via?"forced_light":"light";if(!i.passive)return tu(t,i.eid,s);const n=i.on?"on":"off";return{eid:i.key,role:s,name:e.name,state:n,stateText:n,integrationDomain:null,sample:{eid:i.key,state:n,availability:"available",status:i.on?"working":"neutral",activity:"none",edge:"none"}}});else{const e=Yn(n,o.entities),i=e.length?e:o.entities.filter(e=>!!t?.states?.[e]);if(i.length){a="device_role";const e=hn(n===t?t:{...n,states:t?.states||{}},i,o.entities),s=i.some(t=>an(n,t));r=e.map(e=>{const i=s?rn(n,e.eid)?"power_gate":an(n,e.eid)?"lifecycle":"device_role":"device_role";return tu(t,e.eid,i,e)})}else o.primary&&(a="primary",r=[tu(t,o.primary,"primary")])}const w=[];for(const e of o.entities||[]){const i=cn(t,e);"alarm"!==i.status||r.some(t=>t.eid===e)||w.push(tu(t,e,"critical",i))}return{sourceKind:a,visualSources:r,criticalSources:w,samples:[...r,...w].map(t=>t.sample)}}function iu(t,e,i,s){if(e.virtual)return{source:null,text:null,fallback:"value_virtual"};if(s){const i=function(t,e){if(!0!==e.marker?.use_climate_temp)return null;for(const i of e.entities){if(!i.startsWith("climate."))continue;const e=Number(t?.states?.[i]?.attributes?.current_temperature);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(i)return{source:{kind:"temperature",eid:i.eid,attribute:"current_temperature",text:i.text},text:i.text,fallback:null};const s=function(t,e){if("mdi:thermometer"!==e.icon&&"mdi:air-filter"!==e.icon)return null;for(const i of e.entities){if(!Gn(t,i))continue;const e=Number(t?.states?.[i]?.state);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(s)return{source:{kind:"temperature",eid:s.eid,text:s.text},text:s.text,fallback:null};const n=function(t,e){if(!e.primary||!fo(t,e.primary))return null;const i=Number(t?.states?.[e.primary]?.state);return Number.isFinite(i)?{eid:e.primary,text:`${Math.round(i)}%`}:null}(t,e);if(n)return{source:{kind:"humidity",eid:n.eid,text:n.text},text:n.text,fallback:null}}const n=i.visualSources.filter(t=>!t.eid.startsWith("marker:"));let o=n.map(t=>t.eid);const a=n.find(t=>"power_gate"===t.role);if(a&&(o=[a.eid]),!o.length&&i.visualSources.some(t=>t.eid.startsWith("marker:"))&&(o=Yn(t,e.entities),!o.length&&e.primary&&t?.states?.[e.primary]&&(o=[e.primary])),o=[...new Set(o)],1!==o.length)return{source:null,text:null,fallback:o.length?"value_ambiguous_sources":"value_no_state"};const r=o[0],l=function(t,e){const i=t?.states?.[e];if(!i||null==i.state||""===String(i.state).trim())return{text:"",fallback:"value_no_state"};const s=i.state;if(!["string","number","boolean"].includes(typeof s))return{text:"",fallback:"value_non_scalar"};const n=String(s).trim().toLowerCase();if("unknown"===n||"unavailable"===n)return{text:"",fallback:"value_no_state"};const o=Ji(t,e);return o?{text:Zi(o,String(i.attributes?.unit_of_measurement||"")),fallback:null}:{text:"",fallback:"value_no_state"}}(t,r);return l.fallback?{source:null,text:null,fallback:l.fallback}:{source:{kind:"entity",eid:r,text:l.text},text:l.text,fallback:null}}function su(t,e,i){const s=t.marker?.binding||(t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:t.virtual?"virtual":""),n=[...e.visualSources.map(t=>`${t.role}:${t.eid}`),...e.criticalSources.map(t=>`critical:${t.eid}`)].sort(),o=i?`${i.kind}:${i.eid}:${i.attribute||""}`:"none";return[s,e.sourceKind,...n,`value:${o}`].join("\n")}function nu(t,e,i){return su(e,i||eu(t,e),null).replace(/\nvalue:none$/,"")}function ou(t){if(t.effectiveHidden)return[];if("static_icon"===t.display)return["static-icon"];const e=[],{visual:i}=t;return"alarm"===t.pulse.kind?e.push("alarm"):"unavailable"===i.availability?e.push("unavail"):"working"===i.status?e.push("on"):"open"===i.status&&e.push("open"),t.lockState&&e.push(`lock-${t.lockState}`),"none"!==t.pulse.reason&&"alarm"!==t.pulse.reason&&e.push("activity-"+t.pulse.reason),t.pulse.generation%2==0&&(e.push("pulse-gen2"),"short"===t.pulse.kind&&e.push("activity-gen2")),e}function au(t,e,i){const s=Bi(e.marker?.display),n="static_icon"===s,o=n&&!1===i.sourceDetails?Xp:eu(t,e,i.lightDevices||[e],i.lightSources,i.registryHass||t),a=e.bindingStatus,r="ha_disabled"===a?.kind,l="orphaned"===a?.kind,c=!0===e.userHidden||!0===e.marker?.hidden,h=r||c&&!i.designPreview,d=dn(o.samples),p=o.visualSources.find(t=>t.eid.startsWith("lock.")),u=p?["unlocked","open"].includes(p.state.toLowerCase())?"unlocked":"locked"===p.state.toLowerCase()?"locked":null:null;let _="controls"===o.sourceKind?{...d,availability:Qp(t,e)}:d;h||n?_={availability:"available",status:"neutral",activity:"none"}:"alarm"===d.status||i.liveStates||(_={availability:"available",status:"neutral",activity:"none"});const g=n&&!1===i.sourceDetails?{source:null,text:null,fallback:null}:iu(t,e,o,i.showTemperature),m=su(e,o,g.source),f=nu(t,e,o),v=i.activityRuntime,y=i.now??Date.now(),b=v?.expiresAt||(v?.flashTs?v.flashTs+3300:0);!n&&!h&&i.liveStates&&"alarm"!==d.status&&v?.sources===f&&v.flashTs&&v.flashKind&&b>y&&(_={..._,activity:v.flashKind});const w="icon_ripple"===s&&!h&&i.liveStates&&"alarm"!==_.status?_.activity:"none",k=n||h||!i.showTemperature?null:!0===e.marker?.use_climate_temp?mo(t,e.entities):"mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon?go(t,e.entities):null,x=!n&&!h&&i.showTemperature&&e.primary&&fo(t,e.primary)?vo(t,e.entities):null,$=n||h||!i.showSignal||e.virtual?null:_o(t,e.entities),S=i.lightSources||("derived_marker_state"===e.marker?.value_badge?.source?.kind?ho(t,i.lightDevices||[e]):[]),M=function(t,e,i){const s=null!=e.marker?.value_badge;if(i.effectiveHidden||"static_icon"===i.display)return null;const n=e.marker?.value_badge;if(s)return n?.enabled?n.source?{configured:!0,enabled:!0,position:n.position||"right",...Ho(t,e,n.source,i.markerStates)}:{configured:!0,enabled:!0,source:null,sourceLabel:"",text:"—",fullText:t?.localize?.("state.default.unavailable")||"Unavailable",position:n.position||"right",availability:"missing",isLqi:!1,tone:"default"}:null;if(!i.showTemperature||"value"===i.display)return null;const o=Lo(t,e);if(!o)return null;let a=null,r="default";if("entity_attribute"===o.kind&&"current_temperature"===o.attribute){const i=mo(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else if("mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon){const i=go(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else{const i=vo(t,e.entities);null!=i&&(a=`${i}%`),r="humidity"}return null==a?null:{configured:!1,enabled:!0,source:o,position:"right",sourceLabel:"entity_attribute"===o.kind?`${Eo(o.attribute)} · ${zo(t,o.entity_id)}`:"entity_state"===o.kind?zo(t,o.entity_id):"",text:a,fullText:a,availability:"available",isLqi:!1,tone:r}}(t,e,{showTemperature:i.showTemperature,showSignal:i.showSignal,display:s,effectiveHidden:h,markerStates:S.filter(t=>t.key.startsWith("marker:")).map(t=>({ref:t.key,on:t.on,name:t.device.name}))}),C=o.visualSources.find(t=>!t.eid.startsWith("marker:")),D="cover"===o.sourceKind?C?.eid:e.primary||C?.eid,P=D?t?.states?.[D]:null,T=!i.liveStates||n||h?e.icon:vs(e.icon,D?.split(".")[0],P?.attributes?.device_class,P?.state,!!e.marker?.icon),R=!i.liveStates||n||h?null:o.visualSources.filter(t=>!t.eid.startsWith("marker:")).map(e=>function(t){return t&&"on"===t.state?Ft(t.attributes?.rgb_color):null}(t?.states?.[e.eid])).find(t=>!!t)||null,I=Number(e.marker?.size)>0?Number(e.marker.size):1,A=Number(e.marker?.angle)||0,F=Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,z=Rt(e.marker?.ripple_color,null),E=n?null:z||R||null,O=function(t){const{display:e,visual:i,semanticActivity:s,liveStates:n,effectiveHidden:o,bindingUnavailable:a=!1,reducedMotion:r=!1}=t,l=Math.max(1,Math.trunc(t.shortGeneration||1)),c=Number.isFinite(t.diameterScale)?Math.max(1,Number(t.diameterScale)):1.5,h=t.color||function(t,e){return"presence"===e?"#1DC21D":"running"===e||"working"===t.status||"open"===t.status?"#F0A00C":"#0C82F0"}(i,s);if(o||a||"unavailable"===i.availability||"static_icon"===e)return Yo(l,h,c);if("alarm"===i.status)return{kind:"alarm",reason:"alarm",generation:l,expiresAt:null,color:"#F0410C",diameterScale:1.5,animated:!r,reducedMotionIndicator:"none"};if(!n||"icon_ripple"!==e)return Yo(l,h,c);const d=t.now??Date.now(),p=t.shortExpiresAt||null;return t.shortReason&&null!=p&&p>d?{kind:"short",reason:t.shortReason,generation:l,expiresAt:p,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:"presence"===s||"transition"===s||"running"===s?{kind:"continuous",reason:s,generation:l,expiresAt:null,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:Yo(l,h,c)}({display:s,visual:_,semanticActivity:d.activity,shortReason:v?.sources===f?v?.flashKind:null,shortGeneration:v?.gen,shortExpiresAt:v?.sources===f?b:null,now:y,liveStates:i.liveStates,effectiveHidden:h,bindingUnavailable:r||l,reducedMotion:i.reducedMotion,color:E,diameterScale:F}),N="value"!==s||h?null:g.text,H="ha_disabled"===a?.kind?a.reason:null,L=function(t,e,i,s,n,o,a,r){return o?"ha_disabled":a?"orphaned":"static_icon"===r?"static_icon":"alarm"===e.status?"alarm":n?"unavailable"===e.availability?"unavailable":"cover"===s?"cover_icon_state":"presence"===i?"presence":"event"===i?"event":"transition"===i?"transition":"working"===e.status?"icon_ripple"===r&&"none"!==i?"working_activity":"working":"open"===e.status?"open":(t.primary||"").startsWith("media_player.")?"media_neutral":"neutral":"live_states_disabled"}(e,_,w,o.sourceKind,i.liveStates,r,l,s),B=[];i.designPreview&&c&&B.push("hidden_design_preview"),n||!0!==e.marker?.vacuum?.live||B.push("vacuum_live_plan_only");const q=o.visualSources.some(e=>"power_gate"===e.role||rn(t,e.eid)),W=e.entities.filter(e=>e.startsWith("switch.")&&!t?.entities?.[e]?.entity_category).length;q&&W>1&&B.push("composite_power_source"),"icon_ripple"!==s&&"static_icon"!==s&&"alarm"!==d.status&&"none"!==d.activity&&B.push("activity_display_disabled");const j={binding:e.marker?.binding||(e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:e.virtual?"virtual":""),sourceKind:o.sourceKind,visualSources:o.visualSources,criticalSources:o.criticalSources,valueSource:g.source,sourceSignature:m,visual:_,lockState:u,display:s,icon:T,valueText:N,valueFullText:N,fallbackReason:"value"!==s||N?null:g.fallback,activity:w,activityGeneration:v?.gen||1,pulse:O,classes:[],tempText:null==k?null:String(k),humText:null==x?null:String(x),valueBadge:M,lqiText:null==$||M?.isLqi?null:String($),lqiColor:null==$?null:Kp($),lqiBand:null==$?null:Vp($),lightColor:R,scale:I,angle:A,rippleScale:F,rippleColor:E,userHidden:c,effectiveHidden:h,haDisabled:r,disabledReason:H,orphaned:l,vacuumLive:!n&&!0===e.marker?.vacuum?.live,explanation:{reason:L,notices:B}};return{...j,classes:ou(j)}}function ru(t,e=new WeakMap){if(null===t||"object"!=typeof t)return t;const i=t,s=e.get(i);if(s)return s;if(Array.isArray(t)){const s=[];e.set(i,s);for(const i of t)s.push(ru(i,e));return Object.freeze(s)}const n={};e.set(i,n);for(const[i,s]of Object.entries(t))"function"!=typeof s&&(n[i]=ru(s,e));return Object.freeze(n)}function lu(t){const e=new Map(t);let i;return i=Object.freeze({get size(){return e.size},get:t=>e.get(t),has:t=>e.has(t),entries:()=>e.entries(),keys:()=>e.keys(),values:()=>e.values(),forEach:(t,s)=>e.forEach((e,n)=>t.call(s,e,n,i)),[Symbol.iterator]:()=>e[Symbol.iterator]()}),i}function cu(t){const e=new Set(t.entityIds||[]),i=new Set(t.deviceIds||[]),s=new Set(t.areaIds||[]);for(const s of t.devices){for(const t of s.entities||[])e.add(t);s.primary&&e.add(s.primary);for(const t of s.controls||[])e.add(t);s.marker?.vacuum?.source&&e.add(s.marker.vacuum.source),"device"===s.bindingKind&&s.bindingRef&&i.add(s.bindingRef),"entity"===s.bindingKind&&s.bindingRef&&e.add(s.bindingRef)}const n={},o={};for(const[o,a]of Object.entries(t.hass?.entities||{})){const r=a?.device_id?t.hass?.devices?.[a.device_id]:null;(e.has(o)||a?.device_id&&i.has(a.device_id)||s.has(a?.area_id)||s.has(r?.area_id))&&(e.add(o),n[o]=a,a?.device_id&&i.add(a.device_id))}for(const e of i){const i=t.hass?.devices?.[e];i&&(o[e]=i)}const a={};for(const i of e){const e=t.hass?.states?.[i];e&&(a[i]=e)}const r=Object.freeze({states:ru(a),entities:ru(n),devices:ru(o),config:ru(t.hass?.config),locale:ru(t.hass?.locale),themes:ru(t.hass?.themes)});return Object.freeze({sourceSequence:t.sourceSequence,capturedAt:t.capturedAt??Date.now(),hass:r,devices:ru([...t.devices]),positions:lu([...t.positions||[]].map(([t,e])=>[t,Object.freeze({x:e.x,y:e.y})])),presentations:lu([...t.presentations].map(([t,e])=>[t,ru(e)])),facts:lu([...t.facts||[]].map(([t,e])=>[t,ru(e)]))})}const hu=(t,e)=>`${t}:${e?1:0}`;function du(t){return!Number.isFinite(t)||t<=0?2.25:t/2.5*2.25}function pu({openings:t,geometries:e,fillsByRoomId:i,idPrefix:s="data",groupClass:n="opening-tunnels",dataLayer:o="data"}){const a=t.map((t,n)=>{const o=e[n];if(!o)return G;const a=o.faces.find(t=>-1===t.side),r=o.faces.find(t=>1===t.side);if(!a||!r)return G;const l=i.get(a.roomId)||null,c=i.get(r.roomId)||null;if(!l&&!c)return G;const h=`${a.d} ${r.d}`,d=!!l&&!!c&&l.color===c.color&&l.opacity===c.opacity,p=`translate(${t.rx} ${t.ry}) rotate(${t.angle})`;if(d)return j``}function Vp(t){return t<=40?"low":t<180?"mid":"high"}function Kp(t){return ai(t)}function Yp(t){return"static_icon"===t.display?"neutral":"alarm"===t.visual.status?"alarm":"unavailable"===t.visual.availability?"unavailable":t.lockState?t.lockState:"working"===t.visual.status?"working":"open"===t.visual.status?"open":"neutral"}jp.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",jp);const Xp={sourceKind:"none",visualSources:[],criticalSources:[],samples:[]};function Jp(t,e){const i=t?.entities?.[e],s=t?.states?.[e];return String(i?.name||i?.original_name||s?.attributes?.friendly_name||e)}function Zp(t,e){const i=t?.states?.[e];if(!i)return"";if("function"==typeof t?.formatEntityState)try{const e=t.formatEntityState(i);if("string"==typeof e&&e)return e}catch{}return String(i.state??"")}function Qp(t,e){if(e.virtual||"virtual"===e.bindingKind||"virtual"===e.marker?.binding)return"available";return(e.entities||[]).some(e=>{const i=String(t?.states?.[e]?.state??"").trim().toLowerCase();return""!==i&&"unknown"!==i&&"unavailable"!==i})?"available":"unavailable"}function tu(t,e,i,s){return{eid:e,role:i,name:Jp(t,e),state:String(t?.states?.[e]?.state??""),stateText:Zp(t,e),integrationDomain:t?.entities?.[e]?.platform||null,sample:s||cn(t,e)}}function eu(t,e,i=[e],s,n=t){const o=e.hidden&&e.userHidden?{...e,hidden:!1}:e;let a="none",r=[];const l=[...o.entities,...o.allEntities||[]].some(t=>t.startsWith("cover."))?{...o,tapAction:"cover"}:o,c=(h=Sd({hass:t,devices:i,device:l,lightSources:s,registryHass:n}),"cover"!==h?.semantics?null:h.targets[0]?.entityId||h.skippedTargets[0]?.entityId||null);var h;const d=ho(t,[o]),p=Zn(o.marker?.binding,o.marker?.controls??o.controls,o.entities),u=new Set(p.filter(t=>t.startsWith("marker:"))),_=!0===o.marker?.is_light||u.size>0?s||ho(t,i):d,g=_.filter(t=>t.device.id===o.id&&"controls"!==t.via),m=d.filter(t=>"controls"!==t.via),f=g.length?g:m,v=yn(o.marker),y=v?[...f]:[...d.filter(t=>"controls"===t.via),...f];if(u.size)for(const t of _){if(!u.has(t.key))continue;t.stateEids.length>0&&y.some(e=>e.stateEids.some(e=>t.stateEids.includes(e)))||y.some(e=>e.key===t.key)||y.push({...t,via:"controls",castsGlow:!1})}const b=Yn(n,o.entities);if(!!c&&("cover"===o.tapAction||o.primary?.startsWith("cover.")||b.some(t=>t.startsWith("cover."))))a="cover",r=[tu(t,c,"cover")];else if(y.length)a=!v&&y.some(t=>"controls"===t.via)?"controls":"light",r=y.map(i=>{const s="controls"===i.via?"control":"forced"===i.via?"forced_light":"light";if(!i.passive)return tu(t,i.eid,s);const n=i.on?"on":"off";return{eid:i.key,role:s,name:e.name,state:n,stateText:n,integrationDomain:null,sample:{eid:i.key,state:n,availability:"available",status:i.on?"working":"neutral",activity:"none",edge:"none"}}});else{const e=Yn(n,o.entities),i=e.length?e:o.entities.filter(e=>!!t?.states?.[e]);if(i.length){a="device_role";const e=hn(n===t?t:{...n,states:t?.states||{}},i,o.entities),s=i.some(t=>an(n,t));r=e.map(e=>{const i=s?rn(n,e.eid)?"power_gate":an(n,e.eid)?"lifecycle":"device_role":"device_role";return tu(t,e.eid,i,e)})}else o.primary&&(a="primary",r=[tu(t,o.primary,"primary")])}const w=[];for(const e of o.entities||[]){const i=cn(t,e);"alarm"!==i.status||r.some(t=>t.eid===e)||w.push(tu(t,e,"critical",i))}return{sourceKind:a,visualSources:r,criticalSources:w,samples:[...r,...w].map(t=>t.sample)}}function iu(t,e,i,s){if(e.virtual)return{source:null,text:null,fallback:"value_virtual"};if(s){const i=function(t,e){if(!0!==e.marker?.use_climate_temp)return null;for(const i of e.entities){if(!i.startsWith("climate."))continue;const e=Number(t?.states?.[i]?.attributes?.current_temperature);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(i)return{source:{kind:"temperature",eid:i.eid,attribute:"current_temperature",text:i.text},text:i.text,fallback:null};const s=function(t,e){if("mdi:thermometer"!==e.icon&&"mdi:air-filter"!==e.icon)return null;for(const i of e.entities){if(!Gn(t,i))continue;const e=Number(t?.states?.[i]?.state);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(s)return{source:{kind:"temperature",eid:s.eid,text:s.text},text:s.text,fallback:null};const n=function(t,e){if(!e.primary||!fo(t,e.primary))return null;const i=Number(t?.states?.[e.primary]?.state);return Number.isFinite(i)?{eid:e.primary,text:`${Math.round(i)}%`}:null}(t,e);if(n)return{source:{kind:"humidity",eid:n.eid,text:n.text},text:n.text,fallback:null}}const n=i.visualSources.filter(t=>!t.eid.startsWith("marker:"));let o=n.map(t=>t.eid);const a=n.find(t=>"power_gate"===t.role);if(a&&(o=[a.eid]),!o.length&&i.visualSources.some(t=>t.eid.startsWith("marker:"))&&(o=Yn(t,e.entities),!o.length&&e.primary&&t?.states?.[e.primary]&&(o=[e.primary])),o=[...new Set(o)],1!==o.length)return{source:null,text:null,fallback:o.length?"value_ambiguous_sources":"value_no_state"};const r=o[0],l=function(t,e){const i=t?.states?.[e];if(!i||null==i.state||""===String(i.state).trim())return{text:"",fallback:"value_no_state"};const s=i.state;if(!["string","number","boolean"].includes(typeof s))return{text:"",fallback:"value_non_scalar"};const n=String(s).trim().toLowerCase();if("unknown"===n||"unavailable"===n)return{text:"",fallback:"value_no_state"};const o=Ji(t,e);return o?{text:Zi(o,String(i.attributes?.unit_of_measurement||"")),fallback:null}:{text:"",fallback:"value_no_state"}}(t,r);return l.fallback?{source:null,text:null,fallback:l.fallback}:{source:{kind:"entity",eid:r,text:l.text},text:l.text,fallback:null}}function su(t,e,i){const s=t.marker?.binding||(t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:t.virtual?"virtual":""),n=[...e.visualSources.map(t=>`${t.role}:${t.eid}`),...e.criticalSources.map(t=>`critical:${t.eid}`)].sort(),o=i?`${i.kind}:${i.eid}:${i.attribute||""}`:"none";return[s,e.sourceKind,...n,`value:${o}`].join("\n")}function nu(t,e,i){return su(e,i||eu(t,e),null).replace(/\nvalue:none$/,"")}function ou(t){if(t.effectiveHidden)return[];if("static_icon"===t.display)return["static-icon"];const e=[],{visual:i}=t;return"alarm"===t.pulse.kind?e.push("alarm"):"unavailable"===i.availability?e.push("unavail"):"working"===i.status?e.push("on"):"open"===i.status&&e.push("open"),t.lockState&&e.push(`lock-${t.lockState}`),"none"!==t.pulse.reason&&"alarm"!==t.pulse.reason&&e.push("activity-"+t.pulse.reason),t.pulse.generation%2==0&&(e.push("pulse-gen2"),"short"===t.pulse.kind&&e.push("activity-gen2")),e}function au(t,e,i){const s=Bi(e.marker?.display),n="static_icon"===s,o=n&&!1===i.sourceDetails?Xp:eu(t,e,i.lightDevices||[e],i.lightSources,i.registryHass||t),a=e.bindingStatus,r="ha_disabled"===a?.kind,l="orphaned"===a?.kind,c=!0===e.userHidden||!0===e.marker?.hidden,h=r||c&&!i.designPreview,d=dn(o.samples),p=o.visualSources.find(t=>t.eid.startsWith("lock.")),u=p?["unlocked","open"].includes(p.state.toLowerCase())?"unlocked":"locked"===p.state.toLowerCase()?"locked":null:null,_=!yn(e.marker)&&Zn(e.marker?.binding,e.marker?.controls??e.controls,e.entities).length>0;let g="controls"===o.sourceKind||_&&"light"!==o.sourceKind&&"cover"!==o.sourceKind?{...d,availability:Qp(t,e)}:d;h||n?g={availability:"available",status:"neutral",activity:"none"}:"alarm"===d.status||i.liveStates||(g={availability:"available",status:"neutral",activity:"none"});const m=n&&!1===i.sourceDetails?{source:null,text:null,fallback:null}:iu(t,e,o,i.showTemperature),f=su(e,o,m.source),v=nu(t,e,o),y=i.activityRuntime,b=i.now??Date.now(),w=y?.expiresAt||(y?.flashTs?y.flashTs+3300:0);!n&&!h&&i.liveStates&&"alarm"!==d.status&&y?.sources===v&&y.flashTs&&y.flashKind&&w>b&&(g={...g,activity:y.flashKind});const k="icon_ripple"===s&&!h&&i.liveStates&&"alarm"!==g.status?g.activity:"none",x=n||h||!i.showTemperature?null:!0===e.marker?.use_climate_temp?mo(t,e.entities):"mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon?go(t,e.entities):null,$=!n&&!h&&i.showTemperature&&e.primary&&fo(t,e.primary)?vo(t,e.entities):null,S=n||h||!i.showSignal||e.virtual?null:_o(t,e.entities),M=i.lightSources||("derived_marker_state"===e.marker?.value_badge?.source?.kind?ho(t,i.lightDevices||[e]):[]),C=function(t,e,i){const s=null!=e.marker?.value_badge;if(i.effectiveHidden||"static_icon"===i.display)return null;const n=e.marker?.value_badge;if(s)return n?.enabled?n.source?{configured:!0,enabled:!0,position:n.position||"right",...Ho(t,e,n.source,i.markerStates)}:{configured:!0,enabled:!0,source:null,sourceLabel:"",text:"—",fullText:t?.localize?.("state.default.unavailable")||"Unavailable",position:n.position||"right",availability:"missing",isLqi:!1,tone:"default"}:null;if(!i.showTemperature||"value"===i.display)return null;const o=Lo(t,e);if(!o)return null;let a=null,r="default";if("entity_attribute"===o.kind&&"current_temperature"===o.attribute){const i=mo(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else if("mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon){const i=go(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else{const i=vo(t,e.entities);null!=i&&(a=`${i}%`),r="humidity"}return null==a?null:{configured:!1,enabled:!0,source:o,position:"right",sourceLabel:"entity_attribute"===o.kind?`${Eo(o.attribute)} · ${zo(t,o.entity_id)}`:"entity_state"===o.kind?zo(t,o.entity_id):"",text:a,fullText:a,availability:"available",isLqi:!1,tone:r}}(t,e,{showTemperature:i.showTemperature,showSignal:i.showSignal,display:s,effectiveHidden:h,markerStates:M.filter(t=>t.key.startsWith("marker:")).map(t=>({ref:t.key,on:t.on,name:t.device.name}))}),D=o.visualSources.find(t=>!t.eid.startsWith("marker:")),P="cover"===o.sourceKind?D?.eid:e.primary||D?.eid,T=P?t?.states?.[P]:null,R=!i.liveStates||n||h?e.icon:vs(e.icon,P?.split(".")[0],T?.attributes?.device_class,T?.state,!!e.marker?.icon),I=!i.liveStates||n||h?null:o.visualSources.filter(t=>!t.eid.startsWith("marker:")).map(e=>function(t){return t&&"on"===t.state?Ft(t.attributes?.rgb_color):null}(t?.states?.[e.eid])).find(t=>!!t)||null,A=Number(e.marker?.size)>0?Number(e.marker.size):1,F=Number(e.marker?.angle)||0,z=Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,E=Rt(e.marker?.ripple_color,null),O=n?null:E||I||null,N=function(t){const{display:e,visual:i,semanticActivity:s,liveStates:n,effectiveHidden:o,bindingUnavailable:a=!1,reducedMotion:r=!1}=t,l=Math.max(1,Math.trunc(t.shortGeneration||1)),c=Number.isFinite(t.diameterScale)?Math.max(1,Number(t.diameterScale)):1.5,h=t.color||function(t,e){return"presence"===e?"#1DC21D":"running"===e||"working"===t.status||"open"===t.status?"#F0A00C":"#0C82F0"}(i,s);if(o||a||"unavailable"===i.availability||"static_icon"===e)return Yo(l,h,c);if("alarm"===i.status)return{kind:"alarm",reason:"alarm",generation:l,expiresAt:null,color:"#F0410C",diameterScale:1.5,animated:!r,reducedMotionIndicator:"none"};if(!n||"icon_ripple"!==e)return Yo(l,h,c);const d=t.now??Date.now(),p=t.shortExpiresAt||null;return t.shortReason&&null!=p&&p>d?{kind:"short",reason:t.shortReason,generation:l,expiresAt:p,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:"presence"===s||"transition"===s||"running"===s?{kind:"continuous",reason:s,generation:l,expiresAt:null,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:Yo(l,h,c)}({display:s,visual:g,semanticActivity:d.activity,shortReason:y?.sources===v?y?.flashKind:null,shortGeneration:y?.gen,shortExpiresAt:y?.sources===v?w:null,now:b,liveStates:i.liveStates,effectiveHidden:h,bindingUnavailable:r||l,reducedMotion:i.reducedMotion,color:O,diameterScale:z}),H="value"!==s||h?null:m.text,L="ha_disabled"===a?.kind?a.reason:null,B=function(t,e,i,s,n,o,a,r){return o?"ha_disabled":a?"orphaned":"static_icon"===r?"static_icon":"alarm"===e.status?"alarm":n?"unavailable"===e.availability?"unavailable":"cover"===s?"cover_icon_state":"presence"===i?"presence":"event"===i?"event":"transition"===i?"transition":"working"===e.status?"icon_ripple"===r&&"none"!==i?"working_activity":"working":"open"===e.status?"open":(t.primary||"").startsWith("media_player.")?"media_neutral":"neutral":"live_states_disabled"}(e,g,k,o.sourceKind,i.liveStates,r,l,s),q=[];i.designPreview&&c&&q.push("hidden_design_preview"),n||!0!==e.marker?.vacuum?.live||q.push("vacuum_live_plan_only");const W=o.visualSources.some(e=>"power_gate"===e.role||rn(t,e.eid)),j=e.entities.filter(e=>e.startsWith("switch.")&&!t?.entities?.[e]?.entity_category).length;W&&j>1&&q.push("composite_power_source"),"icon_ripple"!==s&&"static_icon"!==s&&"alarm"!==d.status&&"none"!==d.activity&&q.push("activity_display_disabled");const U={binding:e.marker?.binding||(e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:e.virtual?"virtual":""),sourceKind:o.sourceKind,visualSources:o.visualSources,criticalSources:o.criticalSources,valueSource:m.source,sourceSignature:f,visual:g,lockState:u,display:s,icon:R,valueText:H,valueFullText:H,fallbackReason:"value"!==s||H?null:m.fallback,activity:k,activityGeneration:y?.gen||1,pulse:N,classes:[],tempText:null==x?null:String(x),humText:null==$?null:String($),valueBadge:C,lqiText:null==S||C?.isLqi?null:String(S),lqiColor:null==S?null:Kp(S),lqiBand:null==S?null:Vp(S),lightColor:I,scale:A,angle:F,rippleScale:z,rippleColor:O,userHidden:c,effectiveHidden:h,haDisabled:r,disabledReason:L,orphaned:l,vacuumLive:!n&&!0===e.marker?.vacuum?.live,explanation:{reason:B,notices:q}};return{...U,classes:ou(U)}}function ru(t,e=new WeakMap){if(null===t||"object"!=typeof t)return t;const i=t,s=e.get(i);if(s)return s;if(Array.isArray(t)){const s=[];e.set(i,s);for(const i of t)s.push(ru(i,e));return Object.freeze(s)}const n={};e.set(i,n);for(const[i,s]of Object.entries(t))"function"!=typeof s&&(n[i]=ru(s,e));return Object.freeze(n)}function lu(t){const e=new Map(t);let i;return i=Object.freeze({get size(){return e.size},get:t=>e.get(t),has:t=>e.has(t),entries:()=>e.entries(),keys:()=>e.keys(),values:()=>e.values(),forEach:(t,s)=>e.forEach((e,n)=>t.call(s,e,n,i)),[Symbol.iterator]:()=>e[Symbol.iterator]()}),i}function cu(t){const e=new Set(t.entityIds||[]),i=new Set(t.deviceIds||[]),s=new Set(t.areaIds||[]);for(const s of t.devices){for(const t of s.entities||[])e.add(t);s.primary&&e.add(s.primary);for(const t of s.controls||[])e.add(t);s.marker?.vacuum?.source&&e.add(s.marker.vacuum.source),"device"===s.bindingKind&&s.bindingRef&&i.add(s.bindingRef),"entity"===s.bindingKind&&s.bindingRef&&e.add(s.bindingRef)}const n={},o={};for(const[o,a]of Object.entries(t.hass?.entities||{})){const r=a?.device_id?t.hass?.devices?.[a.device_id]:null;(e.has(o)||a?.device_id&&i.has(a.device_id)||s.has(a?.area_id)||s.has(r?.area_id))&&(e.add(o),n[o]=a,a?.device_id&&i.add(a.device_id))}for(const e of i){const i=t.hass?.devices?.[e];i&&(o[e]=i)}const a={};for(const i of e){const e=t.hass?.states?.[i];e&&(a[i]=e)}const r=Object.freeze({states:ru(a),entities:ru(n),devices:ru(o),config:ru(t.hass?.config),locale:ru(t.hass?.locale),themes:ru(t.hass?.themes)});return Object.freeze({sourceSequence:t.sourceSequence,capturedAt:t.capturedAt??Date.now(),hass:r,devices:ru([...t.devices]),positions:lu([...t.positions||[]].map(([t,e])=>[t,Object.freeze({x:e.x,y:e.y})])),presentations:lu([...t.presentations].map(([t,e])=>[t,ru(e)])),facts:lu([...t.facts||[]].map(([t,e])=>[t,ru(e)]))})}const hu=(t,e)=>`${t}:${e?1:0}`;function du(t){return!Number.isFinite(t)||t<=0?2.25:t/2.5*2.25}function pu({openings:t,geometries:e,fillsByRoomId:i,idPrefix:s="data",groupClass:n="opening-tunnels",dataLayer:o="data"}){const a=t.map((t,n)=>{const o=e[n];if(!o)return G;const a=o.faces.find(t=>-1===t.side),r=o.faces.find(t=>1===t.side);if(!a||!r)return G;const l=i.get(a.roomId)||null,c=i.get(r.roomId)||null;if(!l&&!c)return G;const h=`${a.d} ${r.d}`,d=!!l&&!!c&&l.color===c.color&&l.opacity===c.opacity,p=`translate(${t.rx} ${t.ry}) rotate(${t.angle})`;if(d)return j``;const u=o.maxY-o.minY;if(!(u>0))return G;const _=`${(100*Math.max(0,Math.min(1,-o.minY/u))).toFixed(6)}%`,g=l||{color:"#000000",opacity:0},m=c||{color:"#000000",opacity:0},f=`hp-opening-tunnel-${s.replace(/[^a-zA-Z0-9_-]/g,"-")}-${n}`;return j`${this._t("btn.close")}
-
`}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=zi(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),a={id:i,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=im(t.glowRadius);return null==e||e<=0?null:Math.round(this._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:t.hideFromPlan,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(a.space=e?.space||("virtual"===t.binding?this._space:null),a.area=e?.area||null,a.room_id=e?.roomId||null),a}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,...i}=t;return So({...i,markers:[e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return Sd({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Cd(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:wd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),a=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!a,valueBadgeSource:a,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),a=this._effectiveMarkerTapAction(t,o),r=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===a&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?au(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:r?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),P=o?to(o):[],T=o&&eo(o)||"",R=!!t.lightEntity&&!P.includes(t.lightEntity),I=o?md(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===a?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,z=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",E=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W``}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=zi(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),a={id:i,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=im(t.glowRadius);return null==e||e<=0?null:Math.round(this._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:t.hideFromPlan,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(a.space=e?.space||("virtual"===t.binding?this._space:null),a.area=e?.area||null,a.room_id=e?.roomId||null),a}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${Ph(this._markers)}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,siblingMarkers:i=[],...s}=t;return So({...s,markers:[...i.filter(t=>t.id!==e.id),e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,siblingMarkers:this._markers,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return Sd({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Cd(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:wd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),a=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!a,valueBadgeSource:a,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),a=this._effectiveMarkerTapAction(t,o),r=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===a&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?au(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:r?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),P=o?to(o):[],T=o&&eo(o)||"",R=!!t.lightEntity&&!P.includes(t.lightEntity),I=o?md(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===a?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,z=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",E=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W`this._markerDialog=null}>
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 3332f4a8..9bc56330 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1132,6 +1132,13 @@ its configured space. group has no executable unavailable/missing/HA-disabled target produces the card's standard local explanatory toast and no service/press feedback; partial groups keep executing their available subset. + The persisted external-target list also keeps the physical-controller role + when every runtime target was filtered by another marker's deletion + tombstone: own live diagnostics still decide availability instead of an + event-primary fallback. Marker-dialog drafts are projected through + `buildDevices` with the complete persisted marker roster, replacing only the + edited marker. Consequently target ownership/tombstones and controller + presentation are identical on the committed plan and in preview. - **Universal device action** (#94): `src/device-toggle.ts` is the only authority for toggle origin, exact target, capability/security filtering, next effect and service command. The dialog hint, click path, confirmation re-resolution diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 20b48e99..14a45316 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +- Wireless controllers now keep the same available/working state on the plan + and in the device-dialog preview when a separately deleted target marker + filters the configured light from the runtime roster. Live controller + battery/LQI/update diagnostics continue to prove that the controller is + online, while only an active controlled target makes it yellow + ([#274](https://github.com/Matysh/houseplan-card/issues/274)). - “Optimize plans” now removes a microscopic wall-thickness step beside a T-junction when the short fragment is bounded by two equal-thickness pieces of the same straight wall. The T-node and its perpendicular wall stay in diff --git a/docs/CHANGELOG.ru.md b/docs/CHANGELOG.ru.md index 8e400fab..ab042e65 100755 --- a/docs/CHANGELOG.ru.md +++ b/docs/CHANGELOG.ru.md @@ -8,6 +8,12 @@ ## Не выпущено +- Беспроводной контроллер теперь одинаково показывает доступность и работу на + плане и в preview диалога устройства, даже если отдельно удалённый маркер + цели отфильтровывает настроенный свет из runtime-реестра. Живые диагностические + сущности battery/LQI/update по-прежнему подтверждают связь с контроллером, а + жёлтым его делает только активная управляемая цель + ([#274](https://github.com/Matysh/houseplan-card/issues/274)). - «Оптимизировать планы» теперь удаляет микроскопическую ступень толщины рядом с T-стыком, если короткий фрагмент ограничен двумя участками одинаковой толщины одной прямой стены. T-узел и перпендикулярная стена остаются на diff --git a/docs/TESTING.md b/docs/TESTING.md index c59872a1..bf3c30c4 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -1369,15 +1369,22 @@ separately promised workflows: controller is encountered first. Controller availability is independent (#251): live battery/LQI/update keeps it neutral and opaque when every target is unavailable, all unavailable own entities fade it even if a - target is on, and a virtual controller remains available. A fully + target is on, and a virtual controller remains available. A separately + deleted target marker also cannot turn a live wireless controller into + `unavailable` or make dialog preview disagree with the saved plan (#274): + both projections consume the complete marker roster, preserve the live + LQI value and become yellow only after an active target returns. A fully unavailable configured group shows the named singular/plural local toast without service, confirmation or press feedback; partial groups still execute silently, and a target lost after confirmation uses the same unavailable toast [auto: smoke_controls; unit: devices.test.mjs, device-presentation.test.mjs, device-toggle.test.mjs; golden: device-icon-state-table light/dark; mutation: controller-availability-follows-target, - controller-diagnostics-do-not-prove-online, unavailable-toggle-stays-silent, - partial-group-shows-noop-toast] + controller-diagnostics-do-not-prove-online, + wireless-controller-loses-filtered-target-role, + wireless-controller-preview-drops-sibling-markers, + unavailable-toggle-stays-silent, partial-group-shows-noop-toast; #274: + smoke_wireless_controller_parity] - [ ] Linked manual virtual light (#174): an exact #107 virtual Always-light with an incoming controller follows the real HA driver despite a saved manual off-bit. Clicking either marker operates the real relay and one HA diff --git a/docs/USER-GUIDE.md b/docs/USER-GUIDE.md index 0bf9381e..df322332 100644 --- a/docs/USER-GUIDE.md +++ b/docs/USER-GUIDE.md @@ -500,6 +500,9 @@ but only the controller's own active entities decide whether it fades. A live battery, Zigbee LQI or update entity therefore keeps a wireless switch neutral and opaque when all of its lamps are unavailable. A controller with no live own entity fades even if a target is on; a virtual controller is always available. +This remains true when the same target was separately removed from the plan: +the removed marker is not restored, but it cannot make the controller look +offline or make its editor preview disagree with the plan. For a composite appliance with a dedicated Power switch, Power=`on` alone remains neutral. If Home Assistant also exposes a strict lifecycle entity such diff --git a/docs/USER-GUIDE.ru.md b/docs/USER-GUIDE.ru.md index 317d7666..d53908e0 100644 --- a/docs/USER-GUIDE.ru.md +++ b/docs/USER-GUIDE.ru.md @@ -884,6 +884,9 @@ hover → состояние → нейтрально**. Если все сущ собственная сущность не имеет живого состояния, контроллер бледнеет даже при включённой цели. Виртуальный контроллер не имеет физического HA-устройства и считается доступным. +То же правило действует, если маркер этой цели отдельно удалён с плана: +удалённый маркер не возвращается, но он не может сделать контроллер визуально +недоступным или вызвать расхождение плана и preview в редакторе устройства. Hover включается только после события от настоящей мыши на устройстве, которое поддерживает точный hover. Касание пальцем или пером сразу снимает подсказку и diff --git a/docs/images/01-view-desktop.png b/docs/images/01-view-desktop.png index 3f959b61..d1947abb 100644 Binary files a/docs/images/01-view-desktop.png and b/docs/images/01-view-desktop.png differ diff --git a/docs/images/02-view-touch.png b/docs/images/02-view-touch.png index fbc37414..8d4589d8 100644 Binary files a/docs/images/02-view-touch.png and b/docs/images/02-view-touch.png differ diff --git a/docs/images/03-space-create.png b/docs/images/03-space-create.png index 1e683d3a..09ceed64 100644 Binary files a/docs/images/03-space-create.png and b/docs/images/03-space-create.png differ diff --git a/docs/images/04-room-contour-close.png b/docs/images/04-room-contour-close.png index 792e207e..45639865 100644 Binary files a/docs/images/04-room-contour-close.png and b/docs/images/04-room-contour-close.png differ diff --git a/docs/images/05-plan-context-tray.png b/docs/images/05-plan-context-tray.png index 53c160d1..3d3ee26c 100644 Binary files a/docs/images/05-plan-context-tray.png and b/docs/images/05-plan-context-tray.png differ diff --git a/docs/images/06-device-display-preview.png b/docs/images/06-device-display-preview.png index 7ebc07a2..e97464df 100644 Binary files a/docs/images/06-device-display-preview.png and b/docs/images/06-device-display-preview.png differ diff --git a/docs/images/06-device-editor.png b/docs/images/06-device-editor.png index 27e45eb7..42398476 100644 Binary files a/docs/images/06-device-editor.png and b/docs/images/06-device-editor.png differ diff --git a/docs/images/07-background-editor.png b/docs/images/07-background-editor.png index ec9fb8f5..c14479c0 100644 Binary files a/docs/images/07-background-editor.png and b/docs/images/07-background-editor.png differ diff --git a/docs/images/08-room-card.png b/docs/images/08-room-card.png index a50b3912..179689ce 100644 Binary files a/docs/images/08-room-card.png and b/docs/images/08-room-card.png differ diff --git a/docs/images/09-device-info.png b/docs/images/09-device-info.png index 8767664f..e2c9d1e0 100644 Binary files a/docs/images/09-device-info.png and b/docs/images/09-device-info.png differ diff --git a/docs/images/screenshots.json b/docs/images/screenshots.json index 1456b559..29d3f958 100644 --- a/docs/images/screenshots.json +++ b/docs/images/screenshots.json @@ -2,7 +2,7 @@ "version": 1, "fixture": "synthetic-only", "chromium": "151.0.7922.34", - "sourceFingerprint": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", + "sourceFingerprint": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", "captureScriptSha256": "ce2e9542fed9dade3085be87d16f69adb2ac8262893ad78ad966b1b9673f2983", "command": "npm run build && node demo/docs/capture.mjs", "scenarios": { @@ -14,8 +14,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "abc6ca91ef76fe4892b95414c24b5d4452a403aaa42de89c7f8559cf3cf60ec6" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "aaab24546dac767fc434c627c0aaecd69458b97872cf7a97ce417686946902d1" }, "view-touch": { "file": "02-view-touch.png", @@ -25,8 +25,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "367d0ff05c14f945d60ff6ab1369a8747fc72dac5f2d599266ac0a2e848587bb" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "3cbdf7aa2105d72b2dea0d644862f36118e268d8c8d2e285f1edcffc49648a93" }, "space-create": { "file": "03-space-create.png", @@ -36,8 +36,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "6df7753f00b7d87cd35fd18fb8fbac0a2a7fa2e549902b3afee38f38c93a2ac0" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "c33a7279165a4cec6fa6fadb6fd08cd967e082a17fe101ef442d27d36ae59b6b" }, "room-contour-close": { "file": "04-room-contour-close.png", @@ -47,8 +47,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "24ff960f77cd79e0d760dabab93d52f0df5d22cadaeabd3228e6ec4e3db0d59a" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "2c67fe47a3627e7c4fef3202630dd40ac975cfbe36766b5b4264f22fe43cc49a" }, "plan-context-tray": { "file": "05-plan-context-tray.png", @@ -58,8 +58,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "5b9ecd237a141a50538bb3a41a0d6416947a41fb3e88aca29a93238224a739ff" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "c21bdc2e92da0aaba27a909b0c00d9aeca3ab075ccef5f94bb074cf85d173757" }, "device-editor": { "file": "06-device-editor.png", @@ -69,8 +69,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "25b0e13e28ec406b0202440d10fb51b48ad9889269533e5789812ec0011a2da3" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "b68e560bbc3744a911cbf9d37b0eee765d1ef437b27fe65402c38b13921da1fe" }, "device-display-preview": { "file": "06-device-display-preview.png", @@ -80,8 +80,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "4dcd28f886af304219d4ad6762c398cfdf3af85c1cb2aec31a5fa9c12d8033be" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "7393c93fd60666703531f8882fac9b421452aaf04e47f1a12997afae39cfb7e7" }, "background-editor": { "file": "07-background-editor.png", @@ -91,8 +91,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "7f3595184ada0ebbaab49e73124eaccde93ba21c5b4513a99a3182c43ad60ef9" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "01b6245826e70b256312ffb20219e61a8246bdcace87f848419dd9246df297ba" }, "room-card": { "file": "08-room-card.png", @@ -102,8 +102,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "66d8b0a509909822ff6b891a483bad9d2c72b20f08e287355883aa5205c6cee0" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "029a3e69ec647a8a370d99e6bb7f9225833c526739076022f6b52ba54bff30ea" }, "device-info": { "file": "09-device-info.png", @@ -113,8 +113,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "4db4677b72a4166904a853837eed8014e587d85afc8811c7dd10e0d3365ae54d", - "imageSha256": "094aaea598ea1d8f96bcaa059e66922a94adc27340baa28c3c275cc2efa400c1" + "sourceSha256": "85ce7cdb75b81740bc94a37ad3e35af37c0eb836e5ccd6ad8c010219f3a67137", + "imageSha256": "b49138235d348ca6a2d74da5c9891298f44546fd902efcdea49ef89605654b33" } } } diff --git a/docs/specs/274-wireless-controller-presentation-parity.md b/docs/specs/274-wireless-controller-presentation-parity.md index b6e896cb..ab293d09 100644 --- a/docs/specs/274-wireless-controller-presentation-parity.md +++ b/docs/specs/274-wireless-controller-presentation-parity.md @@ -6,7 +6,7 @@ сложность 5/10 · риск 5/10 - Issue: [#274](https://github.com/Matysh/houseplan-card/issues/274) - Ветка: `issue/274-wireless-controller-parity` -- Статус ТЗ: готово к ревью +- Статус ТЗ: реализовано, готово к code review Канонические документы: `docs/SCOPE.md`, `docs/ARCHITECTURE.md`, `docs/USER-GUIDE.md`, `docs/USER-GUIDE.ru.md`, `docs/TESTING.md` и @@ -314,4 +314,3 @@ provenance принимается только из полного Linux workflo draft после пользовательской правки вправе показывать будущий результат. 4. Точная раскладка новых lifecycle tests техническая и может быть изменена ревьюером при сохранении AC2/AC4 и исполняемых мутантов. - diff --git a/scripts/mutation-gate.mjs b/scripts/mutation-gate.mjs index 73b4619d..436f23a2 100644 --- a/scripts/mutation-gate.mjs +++ b/scripts/mutation-gate.mjs @@ -1306,8 +1306,9 @@ export const MUTANTS = [ + 'the focused matrix keeps own availability and target working as separate facts (#251)', patches: [{ file: 'src/device-presentation.ts', - find: " ? { ...combined, availability: controllerAvailability(hass, d) }", - replace: ' ? combined', + find: " let visual = controllerFace\n" + + " ? { ...combined, availability: controllerAvailability(hass, d) }", + replace: " let visual = controllerFace\n ? combined", }], }, { @@ -1324,6 +1325,36 @@ export const MUTANTS = [ + "&& !eid.startsWith('update.')).some((eid) => {", }], }, + { + id: 'wireless-controller-loses-filtered-target-role', + guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs ' + + '&& node --test --test-name-pattern="issue 274 keeps a wireless controller" ' + + 'test/device-presentation.test.mjs', + because: 'a saved target tombstone may empty the runtime light graph without turning the ' + + 'physical controller into its event-only primary; live diagnostics still prove online (#274)', + patches: [{ + file: 'src/device-presentation.ts', + find: " const controllerFace = sources.sourceKind === 'controls'\n" + + " || (configuredController && sources.sourceKind !== 'light' && sources.sourceKind !== 'cover');", + replace: " const controllerFace = sources.sourceKind === 'controls';", + }], + }, + { + id: 'wireless-controller-preview-drops-sibling-markers', + guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs ' + + '&& node --test --test-name-pattern="issue 274 keeps a wireless controller" ' + + 'test/device-presentation.test.mjs', + because: 'the draft must inherit the same tombstones and ownership roster as the saved plan; ' + + 'isolating it restores the plan/preview contradiction (#274)', + patches: [{ + file: 'src/devices.ts', + find: ' const markers = [\n' + + ' ...siblingMarkers.filter((item) => item.id !== marker.id),\n' + + ' marker,\n' + + ' ];', + replace: ' const markers = [marker];', + }], + }, { id: 'unavailable-toggle-stays-silent', guard: 'node demo/smoke_controls.mjs', diff --git a/src/device-presentation.ts b/src/device-presentation.ts index bcac6945..f6ecbd0f 100644 --- a/src/device-presentation.ts +++ b/src/device-presentation.ts @@ -624,7 +624,18 @@ export function resolveDevicePresentation( // A controller mirrors target work, not target connectivity. Its faded // state describes only the bound controller; Glow/fill/statistics continue // to consume the unchanged target graph. - let visual = sources.sourceKind === 'controls' + // A configured controller remains a controller when every saved target is + // currently filtered out by a plan tombstone. In that case the source graph + // is deliberately empty/device-led, but falling back to the event primary + // would undo #251 and can produce the impossible `unavail` + live LQI face. + // Manual/owned light and cover faces keep their dedicated availability. + const configuredController = !isManualVirtualLightMarker(d.marker) + && persistedExternalControls( + d.marker?.binding, d.marker?.controls ?? d.controls, d.entities, + ).length > 0; + const controllerFace = sources.sourceKind === 'controls' + || (configuredController && sources.sourceKind !== 'light' && sources.sourceKind !== 'cover'); + let visual = controllerFace ? { ...combined, availability: controllerAvailability(hass, d) } : combined; if (effectiveHidden) visual = { availability: 'available', status: 'neutral', activity: 'none' }; diff --git a/src/devices.ts b/src/devices.ts index da7fcda2..65ad28a1 100644 --- a/src/devices.ts +++ b/src/devices.ts @@ -1284,9 +1284,19 @@ export function buildDevices(ctx: BuildCtx): DevItem[] { * projection over buildDevices prevents a second, subtly different preview * implementation from growing beside the runtime one. */ -export function deviceFromMarkerDraft(ctx: Omit & { marker: Marker }): DevItem | null { - const { marker, ...base } = ctx; - return buildDevices({ ...base, markers: [marker] }) +export function deviceFromMarkerDraft( + ctx: Omit & { + marker: Marker; + /** The persisted roster whose tombstones/ownership also constrain the plan. */ + siblingMarkers?: readonly Marker[]; + }, +): DevItem | null { + const { marker, siblingMarkers = [], ...base } = ctx; + const markers = [ + ...siblingMarkers.filter((item) => item.id !== marker.id), + marker, + ]; + return buildDevices({ ...base, markers }) .find((device) => device.id === marker.id) || null; } diff --git a/src/houseplan-card.ts b/src/houseplan-card.ts index bfbd6bed..702bdecc 100755 --- a/src/houseplan-card.ts +++ b/src/houseplan-card.ts @@ -19899,7 +19899,7 @@ class HouseplanCard extends LitElement { private _markerPreviewDevice(d: NonNullable): DevItem | null { const marker = this._markerDraft(d); if (!marker) return null; - const key = `${this._haRegistry.revision}\n${JSON.stringify(marker)}`; + const key = `${this._haRegistry.revision}\n${contentFingerprint(this._markers)}\n${JSON.stringify(marker)}`; if (this._markerPreviewMemo?.key === key) return this._markerPreviewMemo.device; const device = deviceFromMarkerDraft({ hass: this.hass, @@ -19908,6 +19908,7 @@ class HouseplanCard extends LitElement { Object.entries(this._areaToSpace).map(([area, value]) => [area, value.space]), ), marker, + siblingMarkers: this._markers, settings: this._settings, excluded: this._excluded, showAll: this._showAll, diff --git a/test/device-presentation.test.mjs b/test/device-presentation.test.mjs index 1e15405c..56b37f86 100644 --- a/test/device-presentation.test.mjs +++ b/test/device-presentation.test.mjs @@ -16,7 +16,9 @@ import { resolveEntityProvider, } from '../test-build/integration-provider.js'; import { valueBadgeTitle, valueBadgeWriteFields } from '../test-build/device-value-badge.js'; -import { resolvedLightSources } from '../test-build/devices.js'; +import { + buildDevices, deviceFromMarkerDraft, resolvedLightSources, +} from '../test-build/devices.js'; const state = (entity_id, value, attributes = {}) => ({ entity_id, state: value, attributes }); const hass = (states, entities = {}) => ({ @@ -350,6 +352,96 @@ test('issue 251 separates controller availability from controlled target status' assert.ok(alarm.classes.includes('alarm')); }); +test('issue 274 keeps a wireless controller available and gives its draft the full marker roster', () => { + const own = [ + 'event.wall_action', 'sensor.wall_battery', 'sensor.wall_linkquality', 'update.wall', + ]; + const h = hass({ + 'event.wall_action': state('event.wall_action', 'unknown'), + 'sensor.wall_battery': state('sensor.wall_battery', '100'), + 'sensor.wall_linkquality': state('sensor.wall_linkquality', '164'), + 'update.wall': state('update.wall', 'off'), + 'light.wall_group': state('light.wall_group', 'off', { friendly_name: 'Wall lights' }), + }, { + 'event.wall_action': { + entity_id: 'event.wall_action', device_id: 'wall', platform: 'mqtt', + }, + 'sensor.wall_battery': { + entity_id: 'sensor.wall_battery', device_id: 'wall', platform: 'mqtt', + entity_category: 'diagnostic', + }, + 'sensor.wall_linkquality': { + entity_id: 'sensor.wall_linkquality', device_id: 'wall', platform: 'mqtt', + entity_category: 'diagnostic', + }, + 'update.wall': { + entity_id: 'update.wall', device_id: 'wall', platform: 'mqtt', + entity_category: 'config', + }, + 'light.wall_group': { + entity_id: 'light.wall_group', platform: 'group', area_id: 'kitchen', + }, + }); + h.devices.wall = { + id: 'wall', name: 'Wall switch', model: 'Wireless switch', area_id: 'kitchen', + identifiers: [['mqtt', 'wall']], entry_type: null, via_device_id: null, + }; + h.areas = { kitchen: { area_id: 'kitchen', name: 'Kitchen' } }; + const marker = { + id: 'wall-marker', binding: 'device:wall', tap_action: 'toggle', + controls: ['light.wall_group'], + }; + const markers = [ + marker, + { id: 'removed-group', binding: 'entity:light.wall_group', removed: true, hidden: true }, + ]; + const context = { + hass: h, + areaToSpace: { kitchen: 'floor' }, + settings: { filter_seeded: true }, + excluded: new Set(), + showAll: false, + firstSpaceId: 'floor', + loc: (key) => key, + }; + const saved = buildDevices({ ...context, markers }) + .find((item) => item.id === marker.id); + const draft = deviceFromMarkerDraft({ ...context, marker, siblingMarkers: markers }); + assert.ok(saved); + assert.ok(draft); + assert.deepEqual(saved.entities, own); + assert.deepEqual(draft.entities, own); + assert.deepEqual(draft.controls, saved.controls, 'draft honours the same tombstones as the plan'); + + const savedPresentation = resolveDevicePresentation(h, saved, { + ...options, lightDevices: [saved], + }); + const draftPresentation = resolveDevicePresentation(h, draft, { + ...options, designPreview: true, lightDevices: [draft], + }); + for (const result of [savedPresentation, draftPresentation]) { + assert.deepEqual(result.visual, { + availability: 'available', status: 'neutral', activity: 'none', + }); + assert.ok(!result.classes.includes('unavail')); + assert.equal(result.lqiText, '164'); + } + assert.deepEqual( + { + sourceKind: draftPresentation.sourceKind, + visual: draftPresentation.visual, + classes: draftPresentation.classes, + lqiText: draftPresentation.lqiText, + }, + { + sourceKind: savedPresentation.sourceKind, + visual: savedPresentation.visual, + classes: savedPresentation.classes, + lqiText: savedPresentation.lqiText, + }, + ); +}); + test('passive sensor source keeps its normal scalar value and never probes marker ids', () => { const hits = []; const h = hass(new Proxy({