diff --git a/custom_components/houseplan/frontend/houseplan-card.js b/custom_components/houseplan/frontend/houseplan-card.js index afd56894..8b02af02 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__="a26079e078a9ee59646a22d052bb4c421efecc3bdf00ff88f47c6a8e1fa9fabb";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(e,t,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const i=this.t;if(t&&void 0===e){const t=void 0!==i&&1===i.length;t&&(e=s.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&s.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const s=1===e.length?e[0]:t.reduce((t,i,s)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[s+1],e[0]);return new n(s,e,i)},a=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new n("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,m=_?_.emptyScript:"",g=u.reactiveElementPolyfillSupport,f=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?m:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},b=(e,t)=>!r(e,t),y={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:b};Symbol.metadata??=Symbol("metadata"),u.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=y){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(e,i,t);void 0!==s&&l(this.prototype,e,s)}}static getPropertyDescriptor(e,t,i){const{get:s,set:n}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:s,set(t){const o=s?.call(this);n?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??y}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=p(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const e=this.properties,t=[...h(e),...d(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(a(e))}else void 0!==e&&t.push(a(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(t)i.adoptedStyleSheets=s.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of s){const s=document.createElement("style"),n=e.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=t.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),s=this.constructor._$Eu(e,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(e,t){const i=this.constructor,s=i._$Eh.get(e);if(void 0!==s&&this._$Em!==s){const e=i.getPropertyOptions(s),n="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=s;const o=n.fromAttribute(t,e.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(e,t,i,s=!1,n){if(void 0!==e){const o=this.constructor;if(!1===s&&(n=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??b)(n,t)||i.useDefault&&i.reflect&&n===this._$Ej?.get(e)&&!this.hasAttribute(o._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==n||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===s&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,s=this[t];!0!==e||this._$AL.has(t)||void 0===s||this.C(t,void 0,i,s)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,g?.({ReactiveElement:w}),(u.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,P=`<${D}>`,T=document,I=()=>T.createComment(""),R=e=>null===e||"object"!=typeof e&&"function"!=typeof e,A=Array.isArray,z="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,N=/-->/g,E=/>/g,O=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,j=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),q=j(1),W=j(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=T.createTreeWalker(T,129);function Y(e,t){if(!A(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(t):t}const J=(e,t)=>{const i=e.length-1,s=[];let n,o=2===t?"":3===t?"":"",a=F;for(let t=0;t"===l[0]?(a=n??F,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?O:'"'===l[3]?L:H):a===L||a===H?a=O:a===N||a===E?a=F:(a=O,n=void 0);const d=a===O&&e[t+1].startsWith("/>")?" ":"";o+=a===F?i+P:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?t:d)}return[Y(e,o+(e[i]||"")+(2===t?"":3===t?"":"")),s]};class X{constructor({strings:e,_$litType$:t},i){let s;this.parts=[];let n=0,o=0;const a=e.length-1,r=this.parts,[l,c]=J(e,t);if(this.el=X.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==G&&R(this._$AH)?this._$AA.nextSibling.data=e:this.T(T.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,s="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=X.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(t);else{const e=new Q(s,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=V.get(e.strings);return void 0===t&&V.set(e.strings,t=new X(e)),t}k(e){A(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,s=0;for(const n of e)s===t.length?t.push(i=new ee(this.O(I()),this.O(I()),this,this.options)):i=t[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(e,t=this,i,s){const n=this.strings;let o=!1;if(void 0===n)e=Z(this,e,t,0),o=!R(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const s=e;let a,r;for(e=n[0],a=0;a{const s=i?.renderBefore??t;let n=s._$litPart$;if(void 0===n){const e=i?.renderBefore??null;s._$litPart$=n=new ee(t.insertBefore(I(),e),e,void 0,i??{})}return n._$AI(e),n},ce=globalThis;let he=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=le(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};he._$litElement$=!0,he.finalized=!0,ce.litElementHydrateSupport?.({LitElement:he});const de=ce.litElementPolyfillSupport;de?.({LitElement:he}),(ce.litElementVersions??=[]).push("4.2.2");const pe=2,ue=e=>(...t)=>({_$litDirective$:e,values:t});let _e=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this._$Ct=e,this._$AM=t,this._$Ci=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};const me={},ge=ue(class extends _e{constructor(){super(...arguments),this.ot=me}render(e,t){return t()}update(e,[t,i]){if(Array.isArray(t)){if(Array.isArray(this.ot)&&this.ot.length===t.length&&t.every((e,t)=>e===this.ot[t]))return U}else if(this.ot===t)return U;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,i)}}),{I:fe}=ae,ve=e=>e,be=()=>document.createComment(""),ye=(e,t,i)=>{const s=e._$AA.parentNode,n=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=s.insertBefore(be(),n),o=s.insertBefore(be(),n);i=new fe(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,a=o!==e;if(a){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==n||a){let e=i._$AA;for(;e!==t;){const t=ve(e).nextSibling;ve(s).insertBefore(e,n),e=t}}}return i},we=(e,t,i=e)=>(e._$AI(t,i),e),ke={},xe=(e,t=ke)=>e._$AH=t,$e=e=>{e._$AR(),e._$AA.remove()},Se=(e,t,i)=>{const s=new Map;for(let n=t;n<=i;n++)s.set(e[n],n);return s},Me=ue(class extends _e{constructor(e){if(super(e),e.type!==pe)throw Error("repeat() can only be used in text expressions")}dt(e,t,i){let s;void 0===i?i=t:void 0!==t&&(s=t);const n=[],o=[];let a=0;for(const t of e)n[a]=s?s(t,a):a,o[a]=i(t,a),a++;return{values:o,keys:n}}render(e,t,i){return this.dt(e,t,i).values}update(e,[t,i,s]){const n=(e=>e._$AH)(e),{values:o,keys:a}=this.dt(t,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]=we(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=we(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=we(n[d],o[_]),ye(e,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=we(n[p],o[u]),ye(e,n[d],n[p]),p--,u++;else if(void 0===c&&(c=Se(a,u,_),h=Se(r,d,p)),c.has(r[d]))if(c.has(r[p])){const t=h.get(a[u]),i=void 0!==t?n[t]:null;if(null===i){const t=ye(e,n[d]);we(t,o[u]),l[u]=t}else l[u]=we(i,o[u]),ye(e,n[d],i),n[t]=null;u++}else $e(n[p]),p--;else $e(n[d]),d++;for(;u<=_;){const t=ye(e,l[_+1]);we(t,o[u]),l[u++]=t}for(;d<=p;){const e=n[d++];null!==e&&$e(e)}return this.ut=a,xe(e,l),U}}),Ce=new WeakMap;let De=0;class Pe extends he{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-"+ ++De,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");t?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=e=>{if("Escape"===e.key){e.preventDefault(),e.stopImmediatePropagation(),this._pruneOverlays();const t=this._overlays[this._overlays.length-1];return t?void this._closeOverlay(t,"escape"):void this._requestClose()}if("Tab"!==e.key||this._useHaDialog)return;const t=this.renderRoot.querySelector(".close"),i=t?[t,...this._focusableElements()]:this._focusableElements();if(!i.length)return e.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!e.shiftKey||s!==n&&i.includes(s)?e.shiftKey||s!==o||(e.preventDefault(),n.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Ce.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Ce.set(e,t),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const e=[...this._overlays];this._overlays=[];for(const t of e.reverse())t.close("disconnect");const t=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=t?Ce.get(t):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),t&&s&&requestAnimationFrame(()=>{const e=Ce.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Ce.delete(t);const s=i?.closest("hp-dialog");i?.isConnected&&s&&e.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(e){if(super.firstUpdated(e),!this._useHaDialog){const e=this.renderRoot.querySelector("dialog");e&&!e.open&&e.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let e=document.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return e&&e!==document.body?e:null}_focusableElements(){const e=["[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(","),t=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(e)&&t.push(n),n instanceof HTMLSlotElement){for(const e of n.assignedNodes({flatten:!0}))s(e);return}if(n.shadowRoot){for(const e of n.shadowRoot.childNodes)s(e);return}}for(const e of n.childNodes)s(e)}};for(const e of this.childNodes)s(e);const n=this.overlayPortal();return n&&s(n),t.filter(e=>{let t=e;for(;t;){const e=getComputedStyle(t);if(t.hidden||t.inert||"true"===t.getAttribute("aria-hidden")||"none"===e.display||"hidden"===e.visibility)return!1;if(t=t.assignedSlot||t.parentElement||(t.getRootNode()instanceof ShadowRoot?t.getRootNode().host:null),t===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(e=>e.owner.isConnected)}_closeOverlay(e,t){const i=this._overlays.findIndex(t=>t.token===e.token);i>=0&&this._overlays.splice(i,1),e.close(t)}registerOverlay(e){this._pruneOverlays();const t=this._overlays.find(t=>t.owner===e.owner);t&&this._overlays.splice(this._overlays.indexOf(t),1);const i=e.group||"transient";for(const e of[...this._overlays].reverse())e.group===i&&this._closeOverlay(e,"exclusive");const s={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const e=this._overlays.findIndex(e=>e.token===s.token);e>=0&&this._overlays.splice(e,1)}}closeTransientOverlays(e="outside"){this._pruneOverlays();const t=[...this._overlays].filter(e=>"transient"===(e.group||"transient"));for(const i of t.reverse())this._closeOverlay(i,e);return t.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const e=q` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="30d20d6f6822065e2d5226b18abbb05d8d26bc9ddfff42a327dc483b2446800c";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(e,t,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const i=this.t;if(t&&void 0===e){const t=void 0!==i&&1===i.length;t&&(e=s.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&s.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const s=1===e.length?e[0]:t.reduce((t,i,s)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[s+1],e[0]);return new n(s,e,i)},a=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new n("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,m=_?_.emptyScript:"",g=u.reactiveElementPolyfillSupport,f=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?m:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},b=(e,t)=>!r(e,t),y={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:b};Symbol.metadata??=Symbol("metadata"),u.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=y){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(e,i,t);void 0!==s&&l(this.prototype,e,s)}}static getPropertyDescriptor(e,t,i){const{get:s,set:n}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:s,set(t){const o=s?.call(this);n?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??y}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=p(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const e=this.properties,t=[...h(e),...d(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(a(e))}else void 0!==e&&t.push(a(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(t)i.adoptedStyleSheets=s.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of s){const s=document.createElement("style"),n=e.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=t.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),s=this.constructor._$Eu(e,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(e,t){const i=this.constructor,s=i._$Eh.get(e);if(void 0!==s&&this._$Em!==s){const e=i.getPropertyOptions(s),n="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=s;const o=n.fromAttribute(t,e.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(e,t,i,s=!1,n){if(void 0!==e){const o=this.constructor;if(!1===s&&(n=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??b)(n,t)||i.useDefault&&i.reflect&&n===this._$Ej?.get(e)&&!this.hasAttribute(o._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==n||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===s&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,s=this[t];!0!==e||this._$AL.has(t)||void 0===s||this.C(t,void 0,i,s)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,g?.({ReactiveElement:w}),(u.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,P=`<${D}>`,T=document,I=()=>T.createComment(""),R=e=>null===e||"object"!=typeof e&&"function"!=typeof e,A=Array.isArray,z="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,N=/-->/g,E=/>/g,O=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,j=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),q=j(1),W=j(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=T.createTreeWalker(T,129);function Y(e,t){if(!A(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(t):t}const J=(e,t)=>{const i=e.length-1,s=[];let n,o=2===t?"":3===t?"":"",a=F;for(let t=0;t"===l[0]?(a=n??F,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?O:'"'===l[3]?L:H):a===L||a===H?a=O:a===N||a===E?a=F:(a=O,n=void 0);const d=a===O&&e[t+1].startsWith("/>")?" ":"";o+=a===F?i+P:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?t:d)}return[Y(e,o+(e[i]||"")+(2===t?"":3===t?"":"")),s]};class X{constructor({strings:e,_$litType$:t},i){let s;this.parts=[];let n=0,o=0;const a=e.length-1,r=this.parts,[l,c]=J(e,t);if(this.el=X.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==G&&R(this._$AH)?this._$AA.nextSibling.data=e:this.T(T.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,s="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=X.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(t);else{const e=new Q(s,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=V.get(e.strings);return void 0===t&&V.set(e.strings,t=new X(e)),t}k(e){A(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,s=0;for(const n of e)s===t.length?t.push(i=new ee(this.O(I()),this.O(I()),this,this.options)):i=t[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(e,t=this,i,s){const n=this.strings;let o=!1;if(void 0===n)e=Z(this,e,t,0),o=!R(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const s=e;let a,r;for(e=n[0],a=0;a{const s=i?.renderBefore??t;let n=s._$litPart$;if(void 0===n){const e=i?.renderBefore??null;s._$litPart$=n=new ee(t.insertBefore(I(),e),e,void 0,i??{})}return n._$AI(e),n},ce=globalThis;let he=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=le(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};he._$litElement$=!0,he.finalized=!0,ce.litElementHydrateSupport?.({LitElement:he});const de=ce.litElementPolyfillSupport;de?.({LitElement:he}),(ce.litElementVersions??=[]).push("4.2.2");const pe=2,ue=e=>(...t)=>({_$litDirective$:e,values:t});let _e=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this._$Ct=e,this._$AM=t,this._$Ci=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};const me={},ge=ue(class extends _e{constructor(){super(...arguments),this.ot=me}render(e,t){return t()}update(e,[t,i]){if(Array.isArray(t)){if(Array.isArray(this.ot)&&this.ot.length===t.length&&t.every((e,t)=>e===this.ot[t]))return U}else if(this.ot===t)return U;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,i)}}),{I:fe}=ae,ve=e=>e,be=()=>document.createComment(""),ye=(e,t,i)=>{const s=e._$AA.parentNode,n=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=s.insertBefore(be(),n),o=s.insertBefore(be(),n);i=new fe(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,a=o!==e;if(a){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==n||a){let e=i._$AA;for(;e!==t;){const t=ve(e).nextSibling;ve(s).insertBefore(e,n),e=t}}}return i},we=(e,t,i=e)=>(e._$AI(t,i),e),ke={},xe=(e,t=ke)=>e._$AH=t,$e=e=>{e._$AR(),e._$AA.remove()},Se=(e,t,i)=>{const s=new Map;for(let n=t;n<=i;n++)s.set(e[n],n);return s},Me=ue(class extends _e{constructor(e){if(super(e),e.type!==pe)throw Error("repeat() can only be used in text expressions")}dt(e,t,i){let s;void 0===i?i=t:void 0!==t&&(s=t);const n=[],o=[];let a=0;for(const t of e)n[a]=s?s(t,a):a,o[a]=i(t,a),a++;return{values:o,keys:n}}render(e,t,i){return this.dt(e,t,i).values}update(e,[t,i,s]){const n=(e=>e._$AH)(e),{values:o,keys:a}=this.dt(t,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]=we(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=we(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=we(n[d],o[_]),ye(e,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=we(n[p],o[u]),ye(e,n[d],n[p]),p--,u++;else if(void 0===c&&(c=Se(a,u,_),h=Se(r,d,p)),c.has(r[d]))if(c.has(r[p])){const t=h.get(a[u]),i=void 0!==t?n[t]:null;if(null===i){const t=ye(e,n[d]);we(t,o[u]),l[u]=t}else l[u]=we(i,o[u]),ye(e,n[d],i),n[t]=null;u++}else $e(n[p]),p--;else $e(n[d]),d++;for(;u<=_;){const t=ye(e,l[_+1]);we(t,o[u]),l[u++]=t}for(;d<=p;){const e=n[d++];null!==e&&$e(e)}return this.ut=a,xe(e,l),U}}),Ce=new WeakMap;let De=0;class Pe extends he{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-"+ ++De,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");t?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=e=>{if("Escape"===e.key){e.preventDefault(),e.stopImmediatePropagation(),this._pruneOverlays();const t=this._overlays[this._overlays.length-1];return t?void this._closeOverlay(t,"escape"):void this._requestClose()}if("Tab"!==e.key||this._useHaDialog)return;const t=this.renderRoot.querySelector(".close"),i=t?[t,...this._focusableElements()]:this._focusableElements();if(!i.length)return e.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!e.shiftKey||s!==n&&i.includes(s)?e.shiftKey||s!==o||(e.preventDefault(),n.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Ce.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Ce.set(e,t),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const e=[...this._overlays];this._overlays=[];for(const t of e.reverse())t.close("disconnect");const t=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=t?Ce.get(t):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),t&&s&&requestAnimationFrame(()=>{const e=Ce.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Ce.delete(t);const s=i?.closest("hp-dialog");i?.isConnected&&s&&e.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(e){if(super.firstUpdated(e),!this._useHaDialog){const e=this.renderRoot.querySelector("dialog");e&&!e.open&&e.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let e=document.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return e&&e!==document.body?e:null}_focusableElements(){const e=["[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(","),t=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(e)&&t.push(n),n instanceof HTMLSlotElement){for(const e of n.assignedNodes({flatten:!0}))s(e);return}if(n.shadowRoot){for(const e of n.shadowRoot.childNodes)s(e);return}}for(const e of n.childNodes)s(e)}};for(const e of this.childNodes)s(e);const n=this.overlayPortal();return n&&s(n),t.filter(e=>{let t=e;for(;t;){const e=getComputedStyle(t);if(t.hidden||t.inert||"true"===t.getAttribute("aria-hidden")||"none"===e.display||"hidden"===e.visibility)return!1;if(t=t.assignedSlot||t.parentElement||(t.getRootNode()instanceof ShadowRoot?t.getRootNode().host:null),t===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(e=>e.owner.isConnected)}_closeOverlay(e,t){const i=this._overlays.findIndex(t=>t.token===e.token);i>=0&&this._overlays.splice(i,1),e.close(t)}registerOverlay(e){this._pruneOverlays();const t=this._overlays.find(t=>t.owner===e.owner);t&&this._overlays.splice(this._overlays.indexOf(t),1);const i=e.group||"transient";for(const e of[...this._overlays].reverse())e.group===i&&this._closeOverlay(e,"exclusive");const s={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const e=this._overlays.findIndex(e=>e.token===s.token);e>=0&&this._overlays.splice(e,1)}}closeTransientOverlays(e="outside"){this._pruneOverlays();const t=[...this._overlays].filter(e=>"transient"===(e.group||"transient"));for(const i of t.reverse())this._closeOverlay(i,e);return t.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const e=q` ${this.icon?q``:G} ${this.title} `;return this._useHaDialog?q` - `:q``}_openingAt(e){if(!this._openingsR.length)return null;const t=this._openingsR.flatMap(t=>{const i=t.angle*Math.PI/180,s=e[0]-t.rx,n=e[1]-t.ry,o=s*Math.cos(i)+n*Math.sin(i);return Math.abs(o)>t.rlen/2+xh(12,this._cellCm)?[]:[{o:t,localY:-s*Math.sin(i)+n*Math.cos(i)}]});if(!t.length)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s).value;return t.find(({o:e,localY:t})=>{const i="gate"===e.type?!e.flip_v:e.flip_v,s=e.partitionHost||this._spaceWalls.length||"gate"===e.type?this._openingFace(e,n,!!i):{ox:0,oy:0,cm:0,side:-1},o=d_({type:e.type,length:e.rlen,angle:e.angle,amount:this._openingAmt(e),flipH:!!e.flip_h,flipV:!!e.flip_v,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s});return Math.abs(t)<=o.hitHalf})?.o||null}_resolveOpeningPlacement(e){const t=this._openingPreset;if("opening"!==this._tool||!t)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s),o=`${n.key}|partitions:${this._cfgEpoch}`;this._openingPlacementIntervalsCache&&this._openingPlacementIntervalsCache.key===o||(this._openingPlacementIntervalsCache={key:o,value:[...gc(i.rooms,this._spaceWalls,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv),...tu(i.partitions,this._cellCm,this._gridPitch)]}),this._openingDimensionContextCache&&this._openingDimensionContextCache.key===o||(this._openingDimensionContextCache={key:o,value:ev({rooms:i.rooms,walls:this._spaceWalls,openCuts:s,partitions:i.partitions,roomOpenings:this._roomWallOpeningInputs(),partitionCuts:this._partitionOpeningCuts(i),pitch:this._wallKeyPitch,cellCm:this._cellCm,gridPitch:this._gridPitch,coordScale:Pv,epsilon:2e-4*this._gridPitch})});const a=Uf({pointer:[e[0],e[1]],preset:t,geometryRevision:this._cfgEpoch,renderedLength:this._cmToUnits(t.lengthCm),intervals:this._openingPlacementIntervalsCache.value,baseTolerance:1.5*this._gridPitch,bodyPointerPadding:this._cssPxToRender("touch"===this._pointerModality.modality||"pen"===this._pointerModality.modality?10:6),gridStep:this._gridPitch});this._openingJambBlockCm=a.jambBlockedTarget?a.jambBlockedTarget.physicalHalfWidth/this._gridPitch*this._cellCm:null;const r=a.candidate;if(!r)return null;const l="gate"===r.type?!r.flipV:r.flipV;let c;if(r.host){const e=Jp({id:"preview",type:r.type,x:r.x/Pv,y:r.y/Pv,angle:r.angle,length:r.renderedLength/Pv,host:r.host},i.partitions,Pv,this._cellCm,this._gridPitch).resolved;c=e?eu(e,l):{ox:0,oy:0,cm:0,side:-1}}else c=Vc(n.value,{x:r.x,y:r.y,angle:r.angle,length:r.renderedLength,flip_v:l});const h="mi"===this.hass?.config?.unit_system?.length,d=rv(r,this._openingDimensionContextCache.value).map(e=>({x:e.label[0],y:e.label[1],text:li(e.distance/this._gridPitch*this._cellCm,h),dimension:e}));return{...r,face:c,measure:{labels:d,guide:r.measure.guide}}}_activateOpeningPlacement(e){this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingPreset=function(e,t){return{type:e,lengthCm:Bf(e),flipH:!1,flipV:!1,revision:t}}(e,++this._openingPresetRevision),this._openingHoverCandidate=null,this._cursorPt=null)}_clearOpeningPlacement(e){this._openingHoverCandidate=null,this._openingJambBlockCm=null,e&&(this._openingPreset=null,this._openingRebindId=null)}_openingClick(e){const t=this._spaceModel();if(!t)return;const i=this._openingRebindId?null:this._openingAt(e);if(i)return void this._editOpening(i);const s=this._openingPreset;if(!s)return;const n=this._openingHoverCandidate,o=n&&Gf(n,[e[0],e[1]],s.revision,this._cfgEpoch)?n:this._resolveOpeningPlacement(e);if(!o){if(null!=this._openingJambBlockCm)return void this._showToast(this._t("opening.partition_jamb_margin",{distance:li(this._openingJambBlockCm,this._imperial)}));const i=1.5*this._gridPitch,s=ui(e,t.rooms,i);return s&&function(e,t,i,s,n){for(const o of s)if(!(Hs([e,t],o)>n)&&Nl([o[0],o[1]],[o[2],o[3]],i))return!0;return!1}(s.x,s.y,s.angle,this._openCuts(),i)?void this._showToast(this._t("toast.opening_on_zero_wall")):void this._showToast(this._t("toast.opening_no_wall"))}const a=this._openingRebindId?this._curSpaceCfg?.openings?.find(e=>e.id===this._openingRebindId):null;this._openingDialog={...a?{id:a.id,type:a.type,lengthCm:Math.round(a.length*Pv/this._gridPitch*this._cellCm),lengthTouched:!1,contact:a.contact||"",lock:a.lock||"",invert:!!a.invert,flipH:!!a.flip_h,flipV:!!a.flip_v}:{type:o.type,lengthCm:o.lengthCm,contact:"",lock:"",invert:!1,flipH:o.flipH,flipV:o.flipV},...o.host?{host:o.host}:{},x:o.x,y:o.y,angle:o.angle},this._openingRebindId=null,this._openingHoverCandidate=null,this._cursorPt=null}_editOpening(e){this._openingDialog={id:e.id,type:e.type,lengthCm:Math.round(e.rlen/this._gridPitch*this._cellCm),lengthTouched:!1,contact:e.contact||"",lock:e.lock||"",invert:!!e.invert,flipH:!!e.flip_h,flipV:!!e.flip_v,..."partition"===e.host?.kind?{host:{...e.host}}:{},x:e.rx,y:e.ry,angle:e.angle}}_opPointerDown(e,t){if("plan"===this._mode&&this._spaceModel()&&"resize"!==this._tool){e.preventDefault(),e.stopPropagation();try{Ev(e)}catch{}this._opDrag={id:t.id,moved:!1,sx:e.clientX,sy:e.clientY,dirty:!1,before:this._geometrySnapshot()}}}_opPointerMove(e,t){if(!this._opDrag||this._opDrag.id!==t.id)return;if(Math.abs(e.clientX-this._opDrag.sx)+Math.abs(e.clientY-this._opDrag.sy)<=3)return;const i=this._spaceModel();if(!i)return;const s=this._svgPoint(e),n=this._curSpaceCfg,o=n?.openings?.find(e=>e.id===t.id);if(!o)return;if("partition"===o.host?.kind){const e=i.partitions.find(e=>e.id===o.host.id);if(!e)return;const t=e.b[0]-e.a[0],n=e.b[1]-e.a[1],a=Math.hypot(t,n);if(!(a>1e-9))return;const r=t/a,l=n/a;if(Math.abs((s[0]-e.a[0])*l-(s[1]-e.a[1])*r)>4*this._gridPitch)return;const c=o.length*Pv/2+Kp(e,this._cellCm,this._gridPitch);let h=(s[0]-e.a[0])*r+(s[1]-e.a[1])*l;if(h=Math.round(h/this._gridPitch)*this._gridPitch,h=Math.max(c,Math.min(a-c,h)),a<2*c-1e-9)return;const d=h/a,p=(e.a[0]+r*h)/Pv,u=(e.a[1]+l*h)/this._spaceH;let _=180*Math.atan2(n,t)/Math.PI;_>=90?_-=180:_<-90&&(_+=180);const m=o.host.t!==d||o.x!==p||o.y!==u||o.angle!==_;return this._opDrag.moved=!0,m&&(this._opDrag.dirty=!0),o.host={...o.host,t:d},o.x=p,o.y=u,o.angle=_,this._opMeasure=null,m&&this._cfgEpoch++,void this.requestUpdate()}const a=ui(s,i.rooms,4*this._gridPitch);if(!a)return;this._opDrag.moved=!0;const r=this._opRuler(a,o.length*Pv);this._opMeasure=r.measure;const l=r.x/Pv,c=r.y/this._spaceH,h=o.x!==l||o.y!==c||o.angle!==a.angle;if(h&&(this._opDrag.dirty=!0),o.x=l,o.y=c,o.angle=a.angle,Number(this._serverCfg?.model_version||0)>=9){const e=wg(o,n?.wall_segments||[]);e?o.host=e:delete o.host}h&&this._cfgEpoch++,this.requestUpdate()}_opRuler(e,t){const i=this._spaceModel()?.rooms||[],s=this._gridPitch/2;let n=e.x,o=e.y,a=_i([n,o],e.angle,t,i,s);if(a&&a.centered&&(n!==a.wallCenter[0]||o!==a.wallCenter[1]))[n,o]=a.wallCenter,a=_i([n,o],e.angle,t,i,s);else if(a){const[r,l]=a.wallA,[c,h]=a.wallB,d=c-r,p=h-l,u=Math.hypot(d,p);if(u>0){const c=this._gridPitch,h=Math.min(t/2,u/2);let _=Math.round(((n-r)*d+(o-l)*p)/u/c)*c;_=Math.max(h,Math.min(u-h,_)),n=r+_/u*d,o=l+_/u*p,a=_i([n,o],e.angle,t,i,s)||a}}if(!a)return{x:n,y:o,angle:e.angle,measure:null};const r="mi"===this.hass?.config?.unit_system?.length,l=(e,t)=>({x:t[0],y:t[1],text:li(e/this._gridPitch*this._cellCm,r)});return{x:n,y:o,angle:e.angle,measure:{labels:[l(a.sideA,a.midA),l(a.sideB,a.midB)],guide:a.centered?{x:a.wallCenter[0],y:a.wallCenter[1],angle:e.angle}:null}}}_opPointerUp(e,t){if(!this._opDrag||this._opDrag.id!==t.id)return;const i=this._opDrag,s=i.moved;this._opMeasure=null,s&&i.dirty&&this._commitPhysicalGeometry(this._t("history.move_opening"),i.before),s?window.setTimeout(()=>this._opDrag=null,0):this._opDrag=null}_opClick(e,t){"plan"===this._mode&&"resize"===this._tool||(e.stopPropagation(),this._opDrag?.moved||"plan"===this._mode&&this._editOpening(t))}_saveOpening(){const e=this._openingDialog,t=this._curSpaceCfg,i=this._spaceModel();if(!e||!t||!i)return;const s=this._geometrySnapshot(),n=this._spaceH,o=(t.openings||[]).find(t=>t.id===e.id),a={...o||{},id:e.id||"o"+Date.now().toString(36),type:e.type,x:e.x/Pv,y:e.y/n,angle:e.angle,length:o&&!e.lengthTouched?o.length:this._cmToUnits(Math.max(20,e.lengthCm))/Pv,...e.host?{host:{...e.host}}:{}};if("partition"===a.host?.kind){const e=Zp(o,a)?Xp(a,i.partitions,Pv,this._cellCm,this._gridPitch):Jp(a,i.partitions,Pv,this._cellCm,this._gridPitch);if(!e.resolved){const t=i.partitions.find(e=>e.id===a.host.id);if("does-not-fit-jamb"===e.reason&&t){const e=Kp(t,this._cellCm,this._gridPitch);this._showToast(this._t("opening.partition_jamb_margin",{distance:li(e/this._gridPitch*this._cellCm,this._imperial)}))}else this._showToast(this._t("opening.partition_orphan"));return}const s=(t.openings||[]).flatMap(e=>{if(!e.host||e.id===a.id)return[];const t=Jp(e,i.partitions,Pv,this._cellCm,this._gridPitch).resolved;return t?[t]:[]});if(function(e,t,i=1e-9){const s=e.length/(2*e.axis.length),n=e.t-s,o=e.t+s;return t.some(t=>{if(t.host.id!==e.host.id||t.opening.id===e.opening.id)return!1;const s=t.length/(2*t.axis.length);return Math.max(n,t.t-s)=9){const e=wg(a,t.wall_segments||[]);if(!e)return void this._showToast(this._t("toast.opening_no_wall"));a.host=e}else delete a.host;"passage"===e.type?(delete a.contact,delete a.lock,delete a.invert,delete a.flip_h,delete a.flip_v):(a.contact=e.contact||null,a.lock=("door"===e.type||"gate"===e.type)&&e.lock||null,a.invert=e.invert||void 0,a.flip_h="gate"!==e.type&&e.flipH||void 0,a.flip_v=e.flipV||void 0),t.openings=t.openings||[];const r=t.openings.findIndex(e=>e.id===a.id);r>=0?t.openings[r]=a:t.openings.push(a),this._commitPhysicalGeometry(this._t(e.id?"history.edit_opening":"history.add_opening"),s),this._openingDialog=null,this.requestUpdate()}_deleteOpening(){const e=this._openingDialog,t=this._curSpaceCfg;if(!e?.id||!t?.openings)return;const i=this._geometrySnapshot();t.openings=t.openings.filter(t=>t.id!==e.id),this._commitPhysicalGeometry(this._t("history.delete_opening"),i),this._openingDialog=null,this.requestUpdate()}_contactCandidates(){const e=[];for(const t of Object.keys(this.hass.states)){if(!this._openingEntityAvailable(t))continue;const i=t.split(".")[0];if("binary_sensor"!==i&&"cover"!==i)continue;const s=this.hass.states[t],n=["door","window","opening","garage_door","garage"].includes(s?.attributes?.device_class||"");("cover"!==i||n)&&e.push([t,s?.attributes?.friendly_name||t,n?0:1])}return e.sort((e,t)=>e[2]-t[2]||e[1].localeCompare(t[1])).map(([e,t])=>({value:e,label:t}))}_lockCandidates(){return Object.keys(this.hass.states).filter(e=>e.startsWith("lock.")&&this._openingEntityAvailable(e)).map(e=>({value:e,label:this.hass.states[e]?.attributes?.friendly_name||e})).sort((e,t)=>e.label.localeCompare(t.label))}_toggleOpeningEntityPicker(e){const t=this._openingDialog;if(!t)return;const i="contact"===e?!t.contactOpen:!t.lockOpen;this._openingDialog={...t,contactOpen:"contact"===e&&i,lockOpen:"lock"===e&&i}}_filterOpeningEntities(e,t){const i=this._openingDialog;i&&(this._openingDialog="contact"===e?{...i,contactFilter:t}:{...i,lockFilter:t})}_selectOpeningEntity(e,t){const i=this._openingDialog;i&&(this._openingDialog="contact"===e?{...i,contact:t,contactOpen:!1,contactFilter:""}:{...i,lock:t,lockOpen:!1,lockFilter:""})}_mergeClick(e){const t=this._spaceModel();if(!t)return;const i=t.rooms,s=[...i].reverse().find(t=>this._pointInRoom(e,t));if(!s?.id)return;const n=s.id;if(!this._mergeSel||this._mergeSel===n)return void(this._mergeSel=this._mergeSel===n?null:n);const o=i.find(e=>e.id===this._mergeSel),a=o?hi(o):null,r=hi(s),l=a&&r?function(e,t){if(!e||!t||e.length<3||t.length<3)return null;const i=si(Ii(e),Ii(t));if(1!==i.length)return null;if(1!==i[0].length)return null;const s=i[0][0].slice(0,-1).map(e=>[e[0],e[1]]);return s.length>=3?s:null}(a,r):null;if(!l)return this._showToast(this._t("toast.merge_not_adjacent")),void(this._mergeSel=null);this._mergeDialog={aId:this._mergeSel,bId:n,poly:l,pick:"a"},this._mergeSel=null}_commitMerge(){const e=this._mergeDialog,t=this._curSpaceCfg;if(!e||!t||!this._spaceModel())return;const i=this._geometrySnapshot(),s=this._spaceH,n="a"===e.pick?e.aId:e.bId,o="a"===e.pick?e.bId:e.aId,a=t.rooms.find(e=>e.id===n);if(!a)return void(this._mergeDialog=null);a.poly=e.poly.map(e=>[e[0]/Pv,e[1]/s]),delete a.x,delete a.y,delete a.w,delete a.h,t.rooms=t.rooms.filter(e=>e.id!==o);const r=this._commitPhysicalGeometry(this._t("history.merge_rooms"),i);this._mergeDialog=null,this._regSignature="",this._maybeRebuildDevices(),r&&this._showToast(this._t("toast.rooms_merged",{name:a.name||""}))}_splitClick(e){const t=this._spaceModel();if(!t)return;const i=t.rooms;if(!this._splitSel){const t=[...i].reverse().find(t=>this._pointInRoom(e,t));if(!t?.id)return;return void(this._splitSel={roomId:t.id,pts:[]})}const s=i.find(e=>e.id===this._splitSel.roomId),n=s?hi(s):null;if(!s||!n)return void(this._splitSel=null);const o=.02*this._gridPitch,a=6*this._gridPitch,r=function(e,t){if(!t||t.length<2)return null;let i=null,s=1/0;for(let n=0;n=n)continue;n=_;const m=Math.sqrt(p),g=(i>0?Math.max(0,Math.min(m,Math.round(u*m/i)*i)):u*m)/m;s=[a+g*h,r+g*d]}return s}(r,n,this._gridPitch)||r,c=r&&l&&Math.hypot(r[0]-e[0],r[1]-e[1])<=a?l:null,h=!!c&&yi(c,n,o),d=this._splitSel.pts;if(!d.length)return h?void(this._splitSel={...this._splitSel,pts:[c]}):void this._showToast(this._t("toast.split_pick_wall"));if(!h){const t=this._snap(e);return wi(t,n,o)?void(this._splitSel={...this._splitSel,pts:[...d,t]}):void this._showToast(this._t("toast.split_pick_inside"))}const p=zi(n,[...d,c],o);if(!p)return void this._showToast(this._t("toast.split_bad_cut"));this._resetRoomDialogFields();const[u,_]=p,m=Ti(u)>=Ti(_)?u:_,g=m===u?_:u;this._pendingSplit={roomId:s.id,mainPoly:m,newPoly:g},this._cursorPt=null,this._nameSel="",this._areaSel="",this._roomDialog=!0}get _contourClosed(){return this._path.length>=4&&this._samePt(this._path[0],this._path[this._path.length-1])&&(null!=this._closingWallCm||!this._activeDraftId)}_markupMove(e){if(!this._markup)return;if("column"===this._tool)return void(this._cursorPt=this._snap(this._svgPoint(e)));if("opening"===this._tool||"wallthick"===this._tool)return void(this._cursorPt=this._svgPoint(e));const t="draw"===this._tool&&!this._contourClosed,i="split"===this._tool&&!!this._splitSel?.pts?.length;if(!t&&!i)return;const s=this._svgPoint(e);if(t){const t=this._resolvePlanDrawPoint(s,e.shiftKey);return this._planSnapHover={contextKey:t.contextKey,candidate:t.candidate,conflicts:t.conflicts},this._syncPlanSnapConflictMarkers(t.conflicts),this._path.length?void(this._cursorPt=t.point):void this._syncPlanSnapActiveMarker(t.candidate)}this._cursorPt=this._snap(s)}get _openingPreview(){const e=this._openingPreset;if("opening"!==this._tool||!e||!this._cursorPt)return null;const t=this._cursorPt,i=this._openingHoverCandidate;if(i&&Gf(i,[t[0],t[1]],e.revision,this._cfgEpoch))return i;if(this._openingAt(t))return this._openingHoverCandidate=null,null;const s=this._resolveOpeningPlacement(t);return this._openingHoverCandidate=s,s}get _opMeasureView(){return this._opMeasure||this._openingPreview?.measure||null}_saveRoom(){(this._areaSel||this._nameSel.trim())&&(this._wallFaceBatch?this._decideWallFace(!0):this._commitRoom())}_decideWallFace(e){const t=this._wallFaceBatch;if(!t)return;const i=t.candidates[t.index];if(!i)return;if(!e&&(i.existing||i.repair)&&1===t.candidates.length)return this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",void this.requestUpdate();const s=e?{candidate:i,create:!0,name:this._nameSel.trim(),area:this._areaSel||null,settings:this._roomSettingsFromDialog()?JSON.parse(JSON.stringify(this._roomSettingsFromDialog())):null}:{candidate:i,create:!1},n=[...t.decisions,s],o=t.index+1;if(o"number"==typeof e&&Number.isFinite(e)&&e>=0?e:null,n=.02*this._gridPitch,o=this._spaceModel();if(!o)return ul;for(const t of this._planSnapGeometrySnapshot().value.segments){if("room"===t.sourceKind||Hs(e,[t.a[0],t.a[1],t.b[0],t.b[1]])>n)continue;if("partition"===t.sourceKind)return s(o.partitions.find(e=>e.id===t.sourceId)?.cm)??ul;const i=t.sourceId.lastIndexOf(":"),a=i>=0?t.sourceId.slice(0,i):t.sourceId,r=i>=0?Number(t.sourceId.slice(i+1)):-1;return s(o.room_drafts.find(e=>e.id===a)?.segments[r]?.cm)??ul}const a=ku(Math.max(0,t.length-1),i,this._drawWallCm,ul);for(let i=0;i+1[...e]);if(!t?.sourceKey.startsWith("active:"))return i;const s=/:(\d+)$/.exec(t.sourceKey),n=s?Number(s[1])+("b"===t.endpoint?1:0):-1;return n>=0&&nt.key===e.sourceKey),o=s.find(t=>t.key===e.targetSourceKey);if(!n||!o)return!1;const a="a"===e.endpoint?n.a:n.b;return!(Math.hypot(a[0]-e.from[0],a[1]-e.from[1])>i)&&(!(Hs(e.to,[o.a[0],o.a[1],o.b[0],o.b[1]])>i)&&!function(e,t){if(!e.sourceKey.startsWith("static:partition|"))return!1;const i=e.sourceKey.slice(17).split("|")[0];return!!i&&t.some(e=>"partition"===e.host?.kind&&e.host.id===i)}(e,this._curSpaceCfg?.openings||[]))}_applyWallRepair(e,t){const i=this._curSpaceCfg;if(!i||!this._validateWallRepair(e,t.activePath))return!1;const s=t=>{t[0]=e.to[0]/Pv,t[1]=e.to[1]/Pv};if(e.sourceKey.startsWith("active:")){const n=/:(\d+)$/.exec(e.sourceKey),o=n?Number(n[1])+("b"===e.endpoint?1:0):-1;if(o<0||o>=t.activePath.length)return!1;t.activePath[o]=[...e.to];const a=(i.room_drafts||[]).find(e=>e.id===t.activeDraftId);return a?.points?.[o]&&s(a.points[o]),!0}if(!e.sourceKey.startsWith("static:"))return!1;const[n,o]=e.sourceKey.slice(7).split("|");if("partition"===n){const t=(i.partitions||[]).find(e=>e.id===o);if(!t)return!1;const n=[t.a[0]*Pv,t.a[1]*Pv],a=[t.b[0]*Pv,t.b[1]*Pv],r=Math.hypot(n[0]-e.from[0],n[1]-e.from[1])<=2e-4*this._gridPitch?t.a:Math.hypot(a[0]-e.from[0],a[1]-e.from[1])<=2e-4*this._gridPitch?t.b:null;return!!r&&(s(r),!0)}if("draft"===n){const t=o.lastIndexOf(":"),n=t>=0?o.slice(0,t):"",a=t>=0?Number(o.slice(t+1)):-1,r=(i.room_drafts||[]).find(e=>e.id===n);if(!r?.points?.[a]||!r?.points?.[a+1])return!1;const l=[a,a+1].find(t=>Math.hypot(r.points[t][0]*Pv-e.from[0],r.points[t][1]*Pv-e.from[1])<=2e-4*this._gridPitch);return null!=l&&(s(r.points[l]),!0)}return!1}_applyWallFaceBatch(){const e=this._wallFaceBatch,t=this._curSpaceCfg,i=this._spaceModel();if(!e||!t||!i)return;const s=(e,t)=>{this._showToast(this._t(e,t)),this._roomDialogCancel()},n=e.decisions.filter(e=>e.create),o=n.map(e=>e.candidate.ring),a=i.rooms;for(let e=0;ei.id!==t&&!!hi(i)&&Di(o[e],hi(i)));if(i)return void s("toast.room_overlap",{name:i.name||""})}if((t.rooms||[]).length+n.length>400)return void s("toast.physical_limit");if(n.some(e=>e.candidate.split&&!t.rooms.some(t=>t.id===e.candidate.split.roomId)))return void s("toast.contour_cannot_close");const r=n.map(e=>e.candidate.repair).filter(e=>!!e);if(r.length>1||r[0]&&!this._validateWallRepair(r[0],e.activePath))return void s("toast.wall_repair_changed");const l=this._activePathWithRepair(e.activePath,r[0]),c=2e-4*this._gridPitch,h=new Map;for(let t=0;te.candidate.atomKeys)),t=n.some(e=>e.candidate.consumeAllActive);for(const i of Wu(this._wallGraphSources(l),c)){const s=i.sourceKeys.find(e=>h.has(e));!s||t||e.has(i.key)||d.push({a:i.a,b:i.b,cm:h.get(s)})}}else d.push(...xu(l,ku(l.length-1,e.activeCms,this._drawWallCm,ul)));if((t.partitions||[]).length+d.length>Av)return void s("toast.physical_limit");const p=n.map(e=>e.candidate.ring.map(()=>"")),u=e.activeDraftId?(t.room_drafts||[]).find(t=>t.id===e.activeDraftId):null,_=this._draftSegmentsForPath(e.activePath,u,e.activeCms),m=(e,t)=>{const i=`${e[0].toFixed(9)},${e[1].toFixed(9)}`,s=`${t[0].toFixed(9)},${t[1].toFixed(9)}`;return i<=s?`${i}|${s}`:`${s}|${i}`};for(let t=0;t<_.length;t++){const i=_[t]?.id;if(!i)continue;const s=e.activePath[t],o=e.activePath[t+1],a=[s[0],s[1],o[0],o[1]],r=[];n.forEach((e,t)=>e.candidate.ring.forEach((i,s)=>{const n=e.candidate.ring[(s+1)%e.candidate.ring.length];Hs(i,a)<=c&&Hs(n,a)<=c&&r.push({kind:"room",owner:t,edge:s,a:i,b:n})})),d.forEach((e,t)=>{Hs(e.a,a)<=c&&Hs(e.b,a)<=c&&r.push({kind:"partition",owner:t,edge:0,a:e.a,b:e.b})});const l=[(s[0]+o[0])/2,(s[1]+o[1])/2];r.sort((e,t)=>{const i=[e.a[0],e.a[1],e.b[0],e.b[1]],n=[t.a[0],t.a[1],t.b[0],t.b[1]];return(Hs(l,i)<=c?0:1)-(Hs(l,n)<=c?0:1)||(Hs(s,i)<=c?0:1)-(Hs(s,n)<=c?0:1)||m(e.a,e.b).localeCompare(m(t.a,t.b))});const h=r[0];if(!h)continue;const u=m(h.a,h.b);for(const e of r)m(e.a,e.b)===u&&("room"===e.kind?p[e.owner][e.edge]=i:d[e.owner].id=i)}const g=this._geometrySnapshot();if(r[0]&&!this._applyWallRepair(r[0],e))return void s("toast.wall_repair_changed");const f=n.some(e=>!!e.candidate.split),v=f?fc(i.rooms,t.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Pv):null,b=f&&Array.isArray(t.walls)?t.walls:null;for(const e of n){const i=e.candidate.split;if(!i)continue;const n=t.rooms.find(e=>e.id===i.roomId);if(!n)return void s("toast.contour_cannot_close");n.poly=i.mainPoly.map(e=>[e[0]/Pv,e[1]/this._spaceH]),delete n.x,delete n.y,delete n.w,delete n.h}const y=Date.now().toString(36),w=[];if(n.forEach((e,i)=>{const s=e.area?this.hass.areas[e.area]?.name:"",n={id:`r${y}-${i}`,name:e.name||s||this._t("room.default_name"),area:e.area||null,poly:e.candidate.ring.map(e=>[e[0]/Pv,e[1]/this._spaceH]),...p[i].some(Boolean)?{wall_ids:p[i]}:{},...e.settings?{settings:JSON.parse(JSON.stringify(e.settings))}:{}};t.rooms.push(n),w.push({room:n,decision:e})}),e.activeDraftId&&Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t.id!==e.activeDraftId),t.room_drafts.length||delete t.room_drafts),d.length&&(t.partitions||=[],d.forEach((e,i)=>t.partitions.push({id:e.id||`partition-${y}-${i}`,a:[e.a[0]/Pv,e.a[1]/Pv],b:[e.b[0]/Pv,e.b[1]/Pv],cm:e.cm}))),f){const e=this._normalizeWalls(v,this._openCuts());e.length?t.walls=e:b?.length?t.walls=b:delete t.walls}if(w.length){this._cfgEpoch++;const i=this._openCuts(),s=this._spaceModel();if(!s)return;let n=t.walls;for(const{room:t,decision:o}of w){const a=o.candidate.ring,r=this._wallSourceCmAt(a[0],e.activePath,e.activeCms);n=jl(n,s.rooms,t.id,r,this._wallKeyPitch,i,Pv);for(const o of gc(s.rooms,n,i,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv)){if(o.roomId!==t.id||"outer"!==o.kind)continue;const i=[(o.a[0]+o.b[0])/2,(o.a[1]+o.b[1])/2];n=Ll(n,o.a,o.b,this._wallSourceCmAt(i,e.activePath,e.activeCms),this._wallKeyPitch,Pv)}}const o=this._normalizeWalls(n,i);o.length?t.walls=o:delete t.walls}if(!this._commitPhysicalGeometry(this._t("history.wall_face_batch"),g))return;delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices();const k=new Set(n.map(e=>e.area).filter(e=>!!e));if(k.size){const e={...this._layout};for(const t of this._devices){if(!k.has(t.area||"")||t.space!==this._space)continue;if(this._layout[t.id])continue;const i=this._defPos[t.id];i&&(e[t.id]={s:this._space,x:i.x/Pv,y:i.y/Pv},this._dirtyPos.add(t.id))}this._layout=e,this._persistLayout()}this._showToast(this._t(n.length?"toast.wall_rooms_saved":"toast.wall_chain_saved",{n:n.length}))}_commitRoom(){const e=this._curSpaceCfg,t=this._spaceModel();if(!e||!t)return;const i=this._geometrySnapshot(),s=this._spaceH,n=!!this._pendingSplit,o=n?fc(t.rooms,e.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Pv):null,a=n&&Array.isArray(e.walls)?e.walls:null;let r;if(this._pendingSplit){const t=e.rooms.find(e=>e.id===this._pendingSplit.roomId);if(!t)return this._pendingSplit=null,this._splitSel=null,void(this._roomDialog=!1);t.poly=this._pendingSplit.mainPoly.map(e=>[e[0]/Pv,e[1]/s]),delete t.x,delete t.y,delete t.w,delete t.h,r=this._pendingSplit.newPoly}else{if(!this._contourClosed)return;r=this._path.slice(0,-1)}const l=this._areaSel?this.hass.areas[this._areaSel]?.name:"",c={id:"r"+Date.now().toString(36),name:this._nameSel||l||this._t("room.default_name"),area:this._areaSel||null,poly:r.map(e=>[e[0]/Pv,e[1]/s]),...this._roomSettingsFromDialog()?{settings:this._roomSettingsFromDialog()}:{}};if(!n&&this._activeDraftId){const t=Array.isArray(e.room_drafts)?e.room_drafts.find(e=>e.id===this._activeDraftId):null,i=ku(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,ul),s=this._draftSegmentsForPath(this._path,t,i);s.length===r.length&&s.every(e=>!!e.id)&&(c.wall_ids=s.map(e=>e.id))}if(e.rooms.push(c),!n&&this._activeDraftId&&Array.isArray(e.room_drafts)&&(e.room_drafts=e.room_drafts.filter(e=>e.id!==this._activeDraftId),e.room_drafts.length||delete e.room_drafts),n){const t=this._normalizeWalls(o,this._openCuts());t.length?e.walls=t:a?.length?e.walls=a:delete e.walls}if(!n){const t=ku(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,ul),i=t[0];if(null!=i){this._cfgEpoch++;const s=this._openCuts(),n=this._spaceModel();if(!n)return;let o=jl(e.walls,n.rooms,c.id,i,this._wallKeyPitch,s,Pv);for(const e of gc(n.rooms,o,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv)){if(e.roomId!==c.id||"outer"!==e.kind)continue;const i=[(e.a[0]+e.b[0])/2,(e.a[1]+e.b[1])/2],s=r.findIndex((e,t)=>{const s=r[(t+1)%r.length];return Hs(i,[e[0],e[1],s[0],s[1]])<=.02*this._gridPitch});s>=0&&(o=Ll(o,e.a,e.b,t[s],this._wallKeyPitch,Pv))}o=this._normalizeWalls(o,s),o.length?e.walls=o:delete e.walls}}const h=this._commitPhysicalGeometry(this._t(n?"history.split_room":"history.add_room"),i);this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._pendingSplit=null,this._splitSel=null;const d=this._areaSel;if(this._areaSel="",this._nameSel="",this._roomDialog=!1,this._regSignature="",this._maybeRebuildDevices(),!h)return;let p=0;if(d){const e=Pv,t={...this._layout};for(const i of this._devices){if(i.area!==d||i.space!==this._space)continue;if(p++,this._layout[i.id])continue;const s=this._defPos[i.id];s&&(t[i.id]={s:this._space,x:s.x/Pv,y:s.y/e},this._dirtyPos.add(i.id))}this._layout=t,this._persistLayout()}const u=this._model.find(e=>e.id===this._space)?.rooms.length||0;this._showToast(d?this._t("toast.room_saved",{n:u,added:p}):this._t("toast.room_saved_no_area",{n:u}))}_cancelPath(){this._wallRepairDiagnostic=null,this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),this._roomDialog=!1,this._pendingSplit=null,this._wallFaceBatch=null,this._splitSel=null,this._mergeSel=null,this._mergeDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._clearOpeningPlacement(!0)}_resumeLastDraft(){const e=this._resumeDraftBySpace[this._space];if(!e)return;const t=this._spaceModel()?.room_drafts.find(t=>t.id===e);t?(this._activeDraftId=e,this._path=t.points.map(e=>[...e]),this._draftSegmentCms=this._adoptDraftCms(this._path,t.segments.map(e=>e.cm),t.id),this._clearPlanSnapHover()):delete this._resumeDraftBySpace[this._space]}_roomDialogCancel(){if(this._roomDialog=!1,this._roomEditId)return this._roomEditId=null,this._nameSel="",void(this._areaSel="");if(this._wallFaceBatch){const e=this._wallFaceBatch;return this._wallFaceBatch=null,this._path=e.activePath.map(e=>[...e]),this._draftSegmentCms=[...e.activeCms],this._activeDraftId=e.activeDraftId,this._nameSel="",this._areaSel="",void this.requestUpdate()}if(this._pendingSplit)return this._pendingSplit=null,void(this._splitSel=null);this._undoPoint()}get _freeAreas(){const e=new Set;for(const t of this._serverCfg?.spaces||[])for(const i of t.rooms||[])i.area&&e.add(i.area);for(const t of this._wallFaceBatch?.decisions||[])t.create&&t.area&&e.add(t.area);return Object.values(this.hass?.areas||{}).filter(t=>!e.has(t.area_id)).sort((e,t)=>(e.name||"").localeCompare(t.name||""))}_openDeviceInbox(){this._deviceInboxReturn=null,this._deviceInbox=this._deviceInbox||{tab:"on_plan",search:"",showEntities:!1,onlyNew:!1,limit:100}}_closeMarkerDialog(){if(this._markerDialog=null,this._deviceInboxReturn){const e={...this._deviceInboxReturn};this._deviceInbox=e,this._deviceInboxReturn=null,e.anchor&&this.updateComplete.then(()=>requestAnimationFrame(()=>{const t=`.device-inbox-row[data-binding="${CSS.escape(e.anchor)}"]`;this.renderRoot.querySelector(t)?.scrollIntoView({block:"nearest"})}))}}_deviceInboxCandidates(e){return gp({hass:this._planHass,devices:this._devices,markers:this._markers,showEntities:e,labels:{device:this._t("marker.sub_device"),z2mGroup:this._t("marker.sub_z2m_group"),group:this._t("marker.sub_group"),helper:this._t("marker.sub_helper"),entity:this._t("marker.sub_entity")}})}_deviceInboxRows(){const e=this._deviceInbox||this._deviceInboxReturn,t=!!e?.showEntities,i=[this._haRegistry.revision,this._cfgRev,this._cfgEpoch,this._regSignature,this._newSyncKey,t?1:0,this._showAll?1:0,ra(this.hass,this._config?.language)].join("|");if(this._deviceInboxMemo?.key===i)return this._deviceInboxMemo.rows;const s=this._deviceInboxCandidates(t),n=new Set(s.map(e=>e.value));for(const e of this._markers)e.binding&&"virtual"!==e.binding&&n.add(e.binding);for(const e of this._devices)e.bindingKind&&"virtual"!==e.bindingKind&&e.bindingRef&&n.add(`${e.bindingKind}:${e.bindingRef}`);const o=new Map;for(const e of n)o.set(e,this._bindingStatus(e));const a={};for(const[e,t]of Object.entries(this.hass?.areas||{}))a[e]=t?.name||e;const r=Object.fromEntries(this._model.map(e=>[e.id,e.title])),l=Object.fromEntries(Object.entries(this._areaToSpace).map(([e,t])=>[e,t.space])),c={},h=new Map;for(const[e,t]of Object.entries(this._fullRegistryHass.entities||{})){const i=String(t?.platform||"").trim();if(i&&(c[`entity:${e}`]=i),i&&t?.device_id){const e=h.get(t.device_id)||new Set;e.add(i),h.set(t.device_id,e)}}for(const[e,t]of h)c[`device:${e}`]=[...t].sort().join(", ");const d={};for(const[e,t]of Object.entries(this._fullRegistryHass.devices||{})){const i=`device:${e}`,s=h.get(e)||new Set,n=Array.isArray(t?.identifiers?.[0])?String(t.identifiers[0][0]||""):"",o=[n,...s].some(e=>this._excluded.has(e));"service"===t?.entry_type?d[i]="service_entry":o?d[i]="excluded_integration":"Group"===t?.model?d[i]="grouped_light":/scene/i.test(t?.model||"")?d[i]="excluded_domain":(/bridge/i.test(`${t?.model||""}${t?.name||""}`)||"myheat"===n&&t?.via_device_id)&&(d[i]="represented_by_parent")}const p=function(e){const{devices:t,markers:i,candidates:s,statuses:n,newDeviceIds:o,showHiddenOnPlan:a,areaNames:r={},spaceNames:l={},spaceByArea:c={},integrationByBinding:h={},reasonByBinding:d={}}=e,p=new Map;for(const e of t)!e.virtual&&e.bindingKind&&"virtual"!==e.bindingKind&&e.bindingRef&&p.set(`${e.bindingKind}:${e.bindingRef}`,e);const u=new Map,_=new Map;for(const e of i)e?.binding&&"virtual"!==e.binding&&(e.removed?_.set(e.binding,e):u.set(e.binding,e));const m=new Map(s.map(e=>[e.value,e])),g=new Set([...p.keys(),...u.keys(),...m.keys(),...[..._.keys()].filter(e=>m.has(e))]),f=[];for(const e of g){const t=p.get(e),i=u.get(e),s=i?void 0:_.get(e),g=m.get(e);let v;if(s&&g)v="readd";else if(!0===i?.hidden)v="hidden";else if(t||i)v="on_plan";else{if(!g)continue;v="available"}const b=t?.bindingStatus||n.get(e)||fp,y=i||s,w=vp(e),k=t?.area||g?.areaId||y?.area||"",x=t?.space||y?.space||c[k]||"",$=t?.name||y?.name||g?.label||e,S=t?.model||y?.model||g?.model||"",M=!!g?.parentDeviceId&&p.has(`device:${g.parentDeviceId}`),C="readd"===v?"removed":"hidden"===v?i&&bp(i)?d[e]||"automatic_hidden":"manual_hidden":"on_plan"===v?i?"visible_explicit":"visible_auto":d[e]||(M?"represented_by_parent":k&&x?"available":"no_bound_room"),D=!!t&&(!t.hidden||a),P="active"===b.kind,T=D&&(P||"ha_disabled"===b.kind&&a),I="device"===w||"entity"===w,R=[$,S,h[e],r[k],l[x],e,g?.sub].filter(Boolean).join(" ").toLocaleLowerCase();f.push({key:e,binding:e,category:v,status:b,reason:C,deviceId:t?.id,markerId:y?.id,name:$,icon:t?.icon||y?.icon||("entity"===w?"mdi:code-braces":"mdi:devices"),model:S,integration:h[e]||"",areaId:k,areaName:r[k]||"",spaceId:x,spaceName:l[x]||"",kind:w,isNew:!!t&&o.has(t.id),searchText:R,canFind:T,canEdit:!!t||!!i,canHide:"on_plan"===v&&P,canShow:"hidden"===v&&P,canAdd:("available"===v||"readd"===v)&&P,canOpenHa:I})}const v=e=>"active"===e.status.kind?1:0;return f.sort((e,t)=>e.category.localeCompare(t.category)||Number(t.isNew)-Number(e.isNew)||v(e)-v(t)||e.name.localeCompare(t.name)||e.binding.localeCompare(t.binding))}({devices:this._devices,markers:this._markers,candidates:s,statuses:o,newDeviceIds:this._newIds,showHiddenOnPlan:this._showAll,areaNames:a,spaceNames:r,spaceByArea:l,integrationByBinding:c,reasonByBinding:d});return this._deviceInboxMemo={key:i,rows:p},p}_deviceForInboxRow(e){const t=e.deviceId?this._devices.find(t=>t.id===e.deviceId):null;if(t)return t;const i=e.markerId?this._markers.find(t=>t.id===e.markerId):null;return!i||i.removed?null:{id:i.id,name:e.name,model:e.model,area:e.areaId,space:e.spaceId||this._space,hidden:!0===i.hidden||"ha_disabled"===e.status.kind,userHidden:!0===i.hidden,bindingStatus:e.status,icon:e.icon,entities:"active"===e.status.kind?e.status.enabledEntityIds:[],allEntities:e.status.allEntityIds,primary:"active"===e.status.kind?e.status.enabledEntityIds[0]:void 0,marker:i,bindingKind:e.kind,bindingRef:e.binding.slice(e.binding.indexOf(":")+1),pdfs:i.pdfs||[]}}_openInboxMarker(e,t=!1){const i=this._deviceInbox;if(i){if(this._deviceInboxReturn={...i,anchor:e.key},this._deviceInbox=null,!t){const t=this._deviceForInboxRow(e);return void(t?this._openMarkerDialog(t):this._closeMarkerDialog())}this._openMarkerDialog(),this._markerDialog?this._markerDialog={...this._markerDialog,bindingMode:"ha",binding:e.binding,bindingOpen:!1,showEntities:"entity"===e.kind,name:""}:this._closeMarkerDialog()}}async _setInboxHidden(e,t){const i=this._deviceInbox,s=this._serverCfg;if(!i||!s||i.busy||"active"!==e.status.kind)return;const n=s.markers||[],o=n.find(t=>!t.removed&&t.binding===e.binding);if(!t&&!o)return;const a=o?.id||Fi(e.binding,e.markerId,()=>`m_${Date.now().toString(36)}`),r=o?{...o,hidden:t}:{id:a,binding:e.binding,hidden:!0};s.markers=[...n.filter(t=>t.id!==a&&(t.binding!==e.binding||!0===t.removed)),r],this._deviceInbox={...i,busy:e.key,anchor:e.key};try{await this._saveConfigNow(),this._regSignature="",this._deviceInboxMemo=null,this._maybeRebuildDevices(),this._deviceInbox&&(this._deviceInbox={...this._deviceInbox,busy:void 0}),this._showToast(this._t("device_inbox.saved"))}catch(e){this._serverCfg===s&&(s.markers=n),this._deviceInbox&&(this._deviceInbox={...this._deviceInbox,busy:void 0}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}_findInboxDevice(e){if(!e.canFind)return;const t=this._deviceForInboxRow(e);if(!t)return;if(this._deviceInbox=null,t.space&&t.space!==this._space){if(!this._commitSpace(t.space))return;this._restoreZoom()}const i=()=>{const e=this._devices.find(e=>e.id===t.id)||t,i=this._pos(e);this._applyView(this._zoom,i.x,i.y),this._selId=e.id,this.requestUpdate(),window.setTimeout(()=>{this._selId===e.id&&(this._selId=null,this.requestUpdate())},1500)};requestAnimationFrame(()=>requestAnimationFrame(i))}_deviceInboxTabKey(e){if("ArrowLeft"!==e.key&&"ArrowRight"!==e.key)return;const t=this._deviceInbox;if(!t)return;const i=["on_plan","available","hidden","readd"],s="ArrowRight"===e.key?1:-1,n=(i.indexOf(t.tab)+s+i.length)%i.length;this._deviceInbox={...t,tab:i[n],limit:100,onlyNew:!1},e.preventDefault()}_openMarkerDialog(e){if(this._vacAllCamerasFor=null,this._vacAllCameraCache=null,e&&this._ackNewDevice(e.id),this._norm)if(e){const t=e.marker,i=Object.prototype.hasOwnProperty.call(t||{},"is_light"),s=Object.prototype.hasOwnProperty.call(t||{},"light_entity"),n=Object.prototype.hasOwnProperty.call(t||{},"glow_color"),o=Object.prototype.hasOwnProperty.call(t||{},"value_badge"),a=Object.prototype.hasOwnProperty.call(t||{},"tap_action"),r=Object.prototype.hasOwnProperty.call(t||{},"toggle_entity"),l=ks(t?.glow_color),c=this._devicePresentation(e,!0).valueBadge,h=qo(this._planHass,e,this._devices),d=Wo(this._planHass,e,h);this._markerDialog={devId:e.id,name:e.name,binding:"virtual"===e.bindingKind?"virtual":e.bindingKind+":"+e.bindingRef,bindingMode:"virtual"===e.bindingKind?"virtual":"ha",bindingOpen:!1,showEntities:"entity"===e.bindingKind&&!!this._fullRegistryHass.entities[e.bindingRef||""]?.device_id,bindingFilter:"",icon:e.marker?.icon||"",autoIcon:e.icon||"",display:Bi(e.marker?.display),rippleColor:Ie(e.marker?.ripple_color,""),rippleSize:Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,size:Number(e.marker?.size)>0?Number(e.marker.size):1,angle:Number(e.marker?.angle)||0,tapAction:Op(e.marker?.tap_action,e.primary?.split(".")[0]),tapActionTouched:!1,originalHasTapAction:a,originalTapAction:e.marker?.tap_action,tapHintAnnouncement:"",toggleEntity:t?.toggle_entity||"",toggleEntityTouched:!1,originalHasToggleEntity:r,originalToggleEntity:t?.toggle_entity,tapTarget:e.marker?.tap_target||"",tapConfirm:!0===e.marker?.tap_confirm,runFilter:"",controls:Zn(e.marker?.binding,e.marker?.controls,e.entities),controlsFilter:"",lightRole:!0===t?.is_light?"always":!1===t?.is_light?"never":"auto",lightRoleTouched:!1,originalHasIsLight:i,originalIsLight:t?.is_light,lightEntity:t?.light_entity||"",lightEntityTouched:!1,originalHasLightEntity:s,originalLightEntity:t?.light_entity,glowMode:null!=l?.bri?"fixed":l?"color":"auto",glowColor:l?.c||this._fillColors.glow_light.c,glowBrightness:Math.max(1,Math.round(100*(l?.bri??1))),glowColorDrafted:!!l,glowBrightnessDrafted:null!=l?.bri,glowTouched:!1,originalHasGlowColor:n&&(!!l||null===t?.glow_color),originalGlowColor:l||(null===t?.glow_color?null:void 0),valueBadgeEnabled:o?!0===t?.value_badge?.enabled:!!c,valueBadgeSource:t?.value_badge?.source||c?.source||d,valueBadgePosition:t?.value_badge?.position||c?.position||"right",valueBadgeTouched:!1,originalHasValueBadge:o,originalValueBadge:t?.value_badge,useClimateTemp:!0===e.marker?.use_climate_temp,glowRadius:Number(e.marker?.glow_radius_cm)>0?String(this._imperial?Math.round(Number(e.marker.glow_radius_cm)/30.48*10)/10:Math.round(Number(e.marker.glow_radius_cm))/100):"",model:e.model||"",link:e.link||"",description:e.description||"",pdfs:[...e.pdfs||[]],room:e.marker?.room_id?e.space+"#@"+e.marker.room_id:e.space&&e.area?e.space+"#"+e.area:"",hideFromPlan:!0===e.marker?.hidden,busy:!1}}else this._markerDialog={name:"",binding:"virtual",bindingMode:"virtual",bindingOpen:!1,showEntities:!1,bindingFilter:"",icon:"",autoIcon:"",display:"badge",rippleColor:"",rippleSize:1.5,size:1,angle:0,tapAction:"info",tapActionTouched:!1,originalHasTapAction:!1,originalTapAction:void 0,tapHintAnnouncement:"",toggleEntity:"",toggleEntityTouched:!1,originalHasToggleEntity:!1,originalToggleEntity:void 0,tapTarget:"",tapConfirm:!1,runFilter:"",controls:[],controlsFilter:"",lightRole:"auto",lightRoleTouched:!1,originalHasIsLight:!1,originalIsLight:void 0,lightEntity:"",lightEntityTouched:!1,originalHasLightEntity:!1,originalLightEntity:void 0,glowMode:"auto",glowColor:this._fillColors.glow_light.c,glowBrightness:100,glowColorDrafted:!1,glowBrightnessDrafted:!1,glowTouched:!1,originalHasGlowColor:!1,originalGlowColor:void 0,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgePosition:"right",valueBadgeTouched:!1,originalHasValueBadge:!1,originalValueBadge:void 0,useClimateTemp:!1,glowRadius:"",model:"",link:"",description:"",pdfs:[],room:"",hideFromPlan:!1,busy:!1,uploadId:"up_"+Date.now().toString(36)+Math.random().toString(36).slice(2,6)};else this._showToast(this._t("toast.marker_needs_server"))}_runCandidates(){const e=[];for(const t of Gi)for(const[i,s]of Object.entries(this.hass.states))i.startsWith(t+".")&&this._planEntityAvailable(i)&&e.push({value:i,label:s?.attributes?.friendly_name||i,sub:this._t("run."+t)});return e.sort((e,t)=>e.sub.localeCompare(t.sub)||e.label.localeCompare(t.label))}_bindingCandidates(){const e=gp({hass:this._planHass,devices:this._devices,markers:this._markers,showEntities:!!this._markerDialog?.showEntities,currentBinding:this._markerDialog?.binding,currentDeviceId:this._markerDialog?.devId,labels:{device:this._t("marker.sub_device"),z2mGroup:this._t("marker.sub_z2m_group"),group:this._t("marker.sub_group"),helper:this._t("marker.sub_helper"),entity:this._t("marker.sub_entity")}}),t=(this._markerDialog?.bindingFilter||"").toLowerCase().trim(),i=t?e.filter(e=>(e.label+" "+e.sub+" "+e.value).toLowerCase().includes(t)):e;return i.sort((e,t)=>e.label.localeCompare(t.label)),i.slice(0,200)}_physicalBodiesR(e=this._spaceModel()){if(!e)return[];const t=`${e.id}|${this._cfgEpoch}|${this._cellCm}|${this._gridPitch}`;if(this._physicalBodiesCache?.key===t)return this._physicalBodiesCache.all;const i=ch(e,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(e));return this._physicalBodiesCache={key:t,...i},i.all}_rawPhysicalBodiesR(e=this._spaceModel()){if(!e)return[];this._physicalBodiesR(e);const t=this._physicalBodiesCache;return t?[...t.drafts,...t.partitions,...t.columns]:[]}_cleanFloor(e,t,i=this._spaceModel()){if(!i)return{floor:t,geom:null,path:"",area:mh([[[...t,t[0]]]])};const s=e.id||`#${i.rooms.indexOf(e)}`,n=`${i.id}|${this._cfgEpoch}|${s}`;if(!this._resize.preview){const e=gv(this._cleanFloorCache,n);if(e.hit)return e.value}const o=t.map(e=>e[0]),a=t.map(e=>e[1]),r=[Math.min(...o),Math.min(...a),Math.max(...o),Math.max(...a)],l=this._physicalBodiesR(i).filter(e=>{const t=e.map(e=>e[0]),i=e.map(e=>e[1]);return Math.max(...t)>=r[0]&&Math.min(...t)<=r[2]&&Math.max(...i)>=r[1]&&Math.min(...i)<=r[3]}),c=l.length?_h(t,l):null,h={floor:t,geom:c,path:c?nh(c):"",area:mh(c||[[[...t,t[0]]]])};return this._resize.preview||fv(this._cleanFloorCache,n,h,600),h}_autoIconForBinding(e){if("virtual"===e)return"mdi:map-marker";const[t,i]=e.split(":");if(!i)return"";const s=this._fullRegistryHass,n=this._bindingStatus(e),o="active"===n.kind?n.enabledEntityIds:n.allEntityIds;if("device"===t){const e=s.devices?.[i];if(!e)return"mdi:help-circle";const t=o;return t.some(e=>e.startsWith("lock."))?"mdi:lock":yo(s,e.name_by_user||e.name||"",e.model,t,this._iconRules)}if("entity"===t){const e=s.entities?.[i],t=this.hass.states?.[i],n=e?.name||t?.attributes?.friendly_name||i;return i.startsWith("lock.")?"mdi:lock":yo(s,n,"",[i],this._iconRules)}return""}_allRoomsFlat(){const e=[];for(const t of this._serverCfg?.spaces||[])for(const i of t.rooms||[])i.area?e.push({value:t.id+"#"+i.area,label:(t.title||t.id)+" · "+i.name}):i.id&&e.push({value:t.id+"#@"+i.id,label:(t.title||t.id)+" · "+i.name+" · "+this._t("marker.subarea")});return e}_errText(e){if(!e)return this._t("err.unknown");if("string"==typeof e)return e;if("invalid_passage_fields"===e.code){const t=String(e.message||e.error||"").match(/space=([^;]*);\s*opening=([^;]*);\s*fields=([^;]*)/);if(t){const e=this._serverCfg?.spaces?.find(e=>String(e.id)===t[1]),i={contact:"opening.contact_label",lock:"opening.lock_label",invert:"opening.invert",flip_h:"opening.flip_h",flip_v:"opening.flip_v"},s=t[3].split(",").filter(Boolean).map(e=>i[e]?this._t(i[e]):e).join(", ");return this._t("opening.invalid_passage_fields",{room:e?.title||t[1],fields:s})}}if("invalid_partition_opening_jamb_margin"===e.code){const t=String(e.message||e.error||"").match(/margin_cm=([^;]*)/),i=t?Number(t[1]):NaN;if(Number.isFinite(i))return this._t("opening.partition_jamb_margin",{distance:li(i,this._imperial)})}if(e.message)return e.message;if(e.error)return e.error;if(null!=e.code)return this._t("err.code",{code:e.code});try{return JSON.stringify(e)}catch{return String(e)}}_backupErrorText(e){const t=e?.code??e?.error;if("string"==typeof t){const e=`backup.error.${t}`,i=this._t(e);if(i!==e)return i}return this._errText(e)}async _pickMarkerFiles(e){const t=e.target,i=t.files?[...t.files]:[];if(t.value="",!i.length||!this._markerDialog)return;const s=this._markerDialog.uploadId||this._markerDialog.devId||"new",n=[];for(const e of i)try{const t=new FormData;t.append("marker_id",s),t.append("file",e,e.name);const i=this.hass?.fetchWithAuth?await this.hass.fetchWithAuth("/api/houseplan/upload",{method:"POST",body:t}):await fetch("/api/houseplan/upload",{method:"POST",body:t,headers:this.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.hass.auth.data.access_token}`}:{}}),o=await i.json().catch(()=>({}));if(!i.ok||o.error){const e={too_large:this._t("err.too_large",{mb:o.max_mb||50}),bad_ext:this._t("err.bad_ext"),unauthorized:this._t("err.unauthorized")};throw new Error(e[o.error]||o.error||"HTTP "+i.status)}n.push({name:o.name||e.name,url:o.url})}catch(t){this._showToast(this._t("toast.file_failed",{name:e.name,err:this._errText(t)}))}n.length&&this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:[...this._markerDialog.pdfs,...n]},this._showToast(this._t("toast.files_attached",{n:n.length})))}_removeMarkerPdf(e){this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:this._markerDialog.pdfs.filter(t=>t.url!==e)})}_markerLightFields(e){const t={};if(e.lightRoleTouched?"always"===e.lightRole?t.is_light=!0:"never"===e.lightRole&&(t.is_light=!1):e.originalHasIsLight&&(t.is_light=e.originalIsLight??null),e.lightEntityTouched?e.lightEntity&&(t.light_entity=e.lightEntity):e.originalHasLightEntity&&(t.light_entity=e.originalLightEntity??null),e.glowTouched){if("auto"!==e.glowMode){const i={c:Ie(e.glowColor,this._fillColors.glow_light.c)};"fixed"===e.glowMode&&(i.bri=Math.max(.01,Math.min(1,Math.round(e.glowBrightness)/100))),t.glow_color=i}}else e.originalHasGlowColor&&(t.glow_color=e.originalGlowColor??null);return t}_markerTapActionFields(e){return e.tapActionTouched?{tap_action:e.tapAction||null}:e.originalHasTapAction?{tap_action:e.originalTapAction??null}:{}}_markerToggleEntityFields(e){return(t={touched:e.toggleEntityTouched,originalHas:e.originalHasToggleEntity,original:e.originalToggleEntity,value:e.toggleEntity}).touched?t.value?{toggle_entity:t.value}:{}:t.originalHas?{toggle_entity:t.original??null}:{};var t}async _saveMarker(){const e=this._markerDialog;if(!e||e.busy)return;const t=this._effectiveMarkerTapAction(e);if("ha"===e.bindingMode&&(!e.binding||"virtual"===e.binding))return;if("virtual"===e.binding&&!e.name.trim())return void this._showToast(this._t("toast.virtual_name_required"));if("run"===t&&!e.tapTarget)return void this._showToast(this._t("toast.run_target_required"));if(e.valueBadgeTouched&&e.valueBadgeEnabled&&!e.valueBadgeSource)return void this._showToast(this._t("toast.value_badge_source_required"));if("ha"===e.bindingMode){const t=this._bindingStatus(e.binding),i=e.devId?this._markers.find(t=>t.id===e.devId):null,s=!i||i.binding!==e.binding;if("active"!==t.kind&&s)return void this._showToast(this._t("ha_disabled"===t.kind?"toast.ha_disabled_add":"toast.ha_binding_unverified"));if("ha_disabled"===t.kind&&!0===i?.hidden&&!e.hideFromPlan)return this._markerDialog={...e,hideFromPlan:!0},void this._showToast(this._t("entity"===t.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device"))}const i=this._serverCfg;if(!i)return;const s=i.markers||[],n=js(e.room);let o=n?.space||null;const a=n?.area||null,r=n?.roomId||null,l=Fi(e.binding,e.devId,()=>"v_"+Date.now().toString(36)),c=e.devId,h=c?this._devices.find(e=>e.id===c):null,d=n?.space||h?.space||null,p=d?this._spaceModelById(d):this._spaceModel();if(!p)return;const u=p.id;"virtual"!==e.binding||o||(o=u),this._markerDialog={...e,busy:!0};try{const n="virtual"===e.binding?[]:s.filter(t=>t.removed&&t.binding===e.binding).map(e=>e.id),d=n.length>0,_=Zn(e.binding,e.controls,this._bindingEntities(e.binding)),m=s.find(e=>e.id===l||e.id===c)?.vacuum||null,g={id:l,vacuum:m,binding:e.binding,name:e.name.trim()||null,icon:e.icon||null,display:"badge"!==e.display?e.display:null,ripple_color:"icon_ripple"===e.display&&e.rippleColor?e.rippleColor:null,ripple_size:"icon_ripple"===e.display&&1.5!==e.rippleSize?e.rippleSize:null,size:1!==e.size?e.size:null,angle:e.angle?e.angle:null,...this._markerTapActionFields(e),...this._markerToggleEntityFields(e),tap_target:"run"===t&&e.tapTarget||null,tap_confirm:!!e.tapConfirm||null,controls:_.length?_:null,...this._markerLightFields(e),...this._markerValueBadgeFields(e),use_climate_temp:!!e.useClimateTemp||null,glow_radius_cm:(()=>{const t=mv(e.glowRadius);return null==t||t<=0?null:Math.round(this._imperial?30.48*t:100*t)})(),model:e.model.trim()||null,link:e.link.trim()||null,description:e.description.trim()||null,pdfs:e.pdfs,hidden:!!e.hideFromPlan};("virtual"===e.binding||e.room)&&(g.space=o,g.area=a,g.room_id=r);const f=h?.marker?.room_id??null,v=!!e.room&&null!=h&&(h.space!==o||h.area!==a||f!==r);let b=!1;const y=e.uploadId||c;if(y&&y!==l&&g.pdfs?.length)try{const e=await this.hass.callWS({type:"houseplan/files/migrate",from_id:y,to_id:l}),t=e?.mapping||{};g.pdfs=function(e,t,i,s){if(!t||!i||t===i)return e;const n="/files/"+t+"/",o="/files/"+i+"/";return e.map(e=>{if(!e.url.includes(n))return e;const t=e.url.split(n)[1]||"",[i,a]=[t.split("?")[0],t.includes("?")?"?"+t.split("?")[1]:""];if(s){const t=s[decodeURIComponent(i)]??s[i];return t?{...e,url:e.url.split(n+i)[0]+o+encodeURIComponent(t)+a}:e}return{...e,url:e.url.split(n).join(o)}})}(g.pdfs,y,l,t),b=Object.keys(t).length>0}catch(e){this._showToast(this._t("toast.files_migrate_failed",{err:this._errText(e)}))}i.markers=s,c&&c!==l&&(i.markers=function(e,t,i){if(!t||!i||t===i)return[...e];const s=`marker:${t}`,n=`marker:${i}`;return e.map(e=>{const t=Array.isArray(e.controls)?e.controls.map(e=>e===s?n:e):e.controls,i="derived_marker_state"===e.value_badge?.source?.kind&&e.value_badge.source.ref===s?{...e.value_badge,source:{...e.value_badge.source,ref:n}}:e.value_badge;return t===e.controls&&i===e.value_badge?e:{...e,controls:t,value_badge:i}})}(i.markers,c,l)),c&&c!==l&&"derived_marker_state"===g.value_badge?.source?.kind&&g.value_badge.source.ref===`marker:${c}`&&(g.value_badge.source={kind:"derived_marker_state",ref:`marker:${l}`}),i.markers=i.markers.filter(e=>e.id!==l&&e.id!==c&&("virtual"===g.binding||e.binding!==g.binding)),i.markers.push(g);let w=null;const k=c?this._layout[c]:null,x=k?{s:k.s||h?.space||this._space,x:k.x,y:k.y}:c&&h&&this._defPos[c]?this._normPos(h.space,this._defPos[c].x,this._defPos[c].y):null;if(!d&&x&&x.s===u)l===c&&this._layout[l]&&!v||(w={s:x.s,x:x.x,y:x.y},this._layout={...this._layout,[l]:w});else if(d||!this._layout[l]||v){let e=p.vb[0]+p.vb[2]/2,t=p.vb[1]+p.vb[3]/2;const i=r?p.rooms.find(e=>e.id===r):a?p.rooms.find(e=>e.area===a):void 0;i&&([e,t]=this._roomCenter(i)),w=this._normPos(u,e,t),this._layout={...this._layout,[l]:w}}if(await this._saveConfigNow(),w){const e=hl(w);this._layout={...this._layout,[l]:e},this._noteLayoutRev(await this.hass.callWS({type:"houseplan/layout/update",device_id:l,pos:e}))}const $=new Set(n);c&&c!==l&&$.add(c),$.delete(l);for(const e of $)delete this._layout[e],await this.hass.callWS({type:"houseplan/layout/delete",device_id:e}).then(e=>this._noteLayoutRev(e)).catch(()=>{});b&&y&&await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:y}).catch(()=>{}),this._closeMarkerDialog(),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_saved"))}catch(e){this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}async _deleteMarker(){const e=this._markerDialog;if(!e||e.busy||!e.devId)return;const t=e.devId?this._devices.find(t=>t.id===e.devId):null,i=this._markers.find(t=>t.id===e.devId);if(!t&&!i)return;const s=e.name||this._t("device.fallback");if(!confirm(this._t("confirm.remove_marker",{name:s})))return;const n=this._serverCfg;n.markers=n.markers||[];const o=n.markers,a=t?.id||i.id,r=t?"virtual"===t.bindingKind?"virtual":t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:"":i.binding;if(!r)return;const l=function(e,t,i,s){const n=new Set([t]),o=e.filter(e=>{const o=e.id===t||!s&&e.binding===i;return o&&n.add(e.id),!o});return{markers:s?o:[...o,{id:t,binding:i,removed:!0,hidden:!0}],cleanupIds:n}}(n.markers,a,r,"virtual"===r);var c,h;n.markers=(c=l.markers,h=l.cleanupIds,c.map(e=>{if(!Array.isArray(e.controls))return e;const t=e.controls.filter(e=>!("string"==typeof e&&e.startsWith("marker:")&&h.has(e.slice(7))));return t.length===e.controls.length?e:{...e,controls:t.length?t:null}}));const d=l.cleanupIds;this._markerDialog={...e,busy:!0};try{await this._saveConfigNow();for(const e of d){delete this._layout[e],delete this._defPos[e],this._dirtyPos.delete(e),this._sentPos.delete(e);const t=this._activityRt.get(e);t&&clearTimeout(t.timer),this._activityRt.delete(e),this._vacRt.delete(e),delete this._vacSrvTrails[e],await this.hass.callWS({type:"houseplan/layout/delete",device_id:e}).then(e=>this._noteLayoutRev(e)).catch(()=>{}),await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:e}).catch(()=>{}),await this.hass.callWS({type:"houseplan/trail/delete",marker_id:e}).catch(()=>{})}this._deviceInboxReturn&&(this._deviceInboxReturn={...this._deviceInboxReturn,tab:"readd",anchor:r}),this._closeMarkerDialog(),this._infoCard?.id===a&&this._closeInfoCard(),this._selId===a&&(this._selId=null),this._drag?.id===a&&(this._drag=null),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_removed"))}catch(e){this._serverCfg===n&&(n.markers=o),this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}_normPos(e,t,i){return{s:e,x:t/Pv,y:i/Pv}}_openSpaceDialog(e,t){if(this._serverStorage&&this._serverCfg)if("edit"===e){const i=this._serverCfg.spaces.find(e=>e.id===t);if(!i)return;const s=cs(i),n=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?rs(i.settings.custom_fill):null,o="none"===s.fill?{...n||as,a:0}:n;this._spaceDialog={mode:e,spaceId:t,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:s.showBorders,showNames:s.showNames,zeroWallStyle:O_(i),displayTouched:!0,hideDecor:s.hideDecor,hideOpenings:s.hideOpenings,roomColor:s.color,roomOpacity:s.opacity,fillMode:"none"===s.fill?"custom":s.fill,customFill:o,glowEnabled:s.glow,bgColor:s.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:Pr({},i.settings),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:s.tempMin,tempMax:s.tempMax,showLqi:s.showLqi??this._config?.show_signal??!0,cardFontScale:s.cardFontScale,labelTemp:s.labelTemp,labelHum:s.labelHum,labelLqi:s.labelLqi,labelLight:s.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:Sh(Number(i.cell_cm)>0?Number(i.cell_cm):5,this._imperial),cellCmTouched:!1,busy:!1}}else this._spaceDialog={mode:e,title:"",planUrl:null,planFile:null,...Gd(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:ns,roomOpacity:os,fillMode:"custom",customFill:{...as,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:20,tempMax:25,showLqi:this._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:$h(this._imperial),cellCmInput:Sh($h(this._imperial),this._imperial),cellCmTouched:!1,busy:!1};else this._showToast(this._t("toast.integration_missing"))}async _pickPlanFile(e){const t=e.target,i=t.files?.[0];if(!i||!this._spaceDialog)return;const s={"image/svg+xml":"svg","image/png":"png","image/jpeg":"jpg","image/webp":"webp"}[i.type]||(i.name.toLowerCase().endsWith(".svg")?"svg":"");if(!s)return void this._showToast(this._t("toast.plan_formats"));const n=new Uint8Array(await i.arrayBuffer());let o="";for(let e=0;e{const t=new Image;t.onload=()=>e(t.naturalWidth&&t.naturalHeight?t.naturalWidth/t.naturalHeight:1.414),t.onerror=()=>e(1.414),t.src=r});URL.revokeObjectURL(r),this._spaceDialog={...this._spaceDialog,planFile:{ext:s,b64:a,aspect:l,name:i.name}}}_useServerPlan(e){const t=this._spaceDialog;t&&(this._spaceDialog={...t,planUrl:e,planFile:null,pickSaved:!1,savedAspect:void 0},this._aspectJob=this._readPlanAspect(e))}async _readPlanAspect(e){for(let t=0;t<40;t++){const t=this._display(e);if(t){const i=await new Promise(e=>{const i=new Image;i.onload=()=>e(i.naturalWidth&&i.naturalHeight?i.naturalWidth/i.naturalHeight:0),i.onerror=()=>e(0),i.src=t}),s=this._spaceDialog;return s&&s.planUrl===e&&Number.isFinite(i)&&i>0?(this._spaceDialog={...s,savedAspect:i},i):0}if(await new Promise(e=>setTimeout(e,150)),this._spaceDialog?.planUrl!==e)return 0}return 0}async _deleteServerPlan(e){if(confirm(this._t("confirm.delete_plan",{name:e})))try{await this.hass.callWS({type:"houseplan/plans/delete",name:e});const t=this._spaceDialog;t?.saved&&(this._spaceDialog={...t,saved:t.saved.filter(t=>t.name!==e)})}catch(e){this._showToast(this._t("toast.plan_delete_failed",{err:this._errText(e)}))}}_renderServerPlans(e){if(e.savedBusy)return q`
${this._t("space.loading")}
`;const t=e.saved||[];if(!t.length)return q`
${this._t("space.no_saved")}
`;return q`
+
`:q``}_openingAt(e){if(!this._openingsR.length)return null;const t=this._openingsR.flatMap(t=>{const i=t.angle*Math.PI/180,s=e[0]-t.rx,n=e[1]-t.ry,o=s*Math.cos(i)+n*Math.sin(i);return Math.abs(o)>t.rlen/2+xh(12,this._cellCm)?[]:[{o:t,localY:-s*Math.sin(i)+n*Math.cos(i)}]});if(!t.length)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s).value;return t.find(({o:e,localY:t})=>{const i="gate"===e.type?!e.flip_v:e.flip_v,s=e.partitionHost||this._spaceWalls.length||"gate"===e.type?this._openingFace(e,n,!!i):{ox:0,oy:0,cm:0,side:-1},o=d_({type:e.type,length:e.rlen,angle:e.angle,amount:this._openingAmt(e),flipH:!!e.flip_h,flipV:!!e.flip_v,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s});return Math.abs(t)<=o.hitHalf})?.o||null}_resolveOpeningPlacement(e){const t=this._openingPreset;if("opening"!==this._tool||!t)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s),o=`${n.key}|partitions:${this._cfgEpoch}`;this._openingPlacementIntervalsCache&&this._openingPlacementIntervalsCache.key===o||(this._openingPlacementIntervalsCache={key:o,value:[...gc(i.rooms,this._spaceWalls,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv),...tu(i.partitions,this._cellCm,this._gridPitch)]}),this._openingDimensionContextCache&&this._openingDimensionContextCache.key===o||(this._openingDimensionContextCache={key:o,value:ev({rooms:i.rooms,walls:this._spaceWalls,openCuts:s,partitions:i.partitions,roomOpenings:this._roomWallOpeningInputs(),partitionCuts:this._partitionOpeningCuts(i),pitch:this._wallKeyPitch,cellCm:this._cellCm,gridPitch:this._gridPitch,coordScale:Pv,epsilon:2e-4*this._gridPitch})});const a=Uf({pointer:[e[0],e[1]],preset:t,geometryRevision:this._cfgEpoch,renderedLength:this._cmToUnits(t.lengthCm),intervals:this._openingPlacementIntervalsCache.value,baseTolerance:1.5*this._gridPitch,bodyPointerPadding:this._cssPxToRender("touch"===this._pointerModality.modality||"pen"===this._pointerModality.modality?10:6),gridStep:this._gridPitch});this._openingJambBlockCm=a.jambBlockedTarget?a.jambBlockedTarget.physicalHalfWidth/this._gridPitch*this._cellCm:null;const r=a.candidate;if(!r)return null;const l="gate"===r.type?!r.flipV:r.flipV;let c;if(r.host){const e=Jp({id:"preview",type:r.type,x:r.x/Pv,y:r.y/Pv,angle:r.angle,length:r.renderedLength/Pv,host:r.host},i.partitions,Pv,this._cellCm,this._gridPitch).resolved;c=e?eu(e,l):{ox:0,oy:0,cm:0,side:-1}}else c=Vc(n.value,{x:r.x,y:r.y,angle:r.angle,length:r.renderedLength,flip_v:l});const h="mi"===this.hass?.config?.unit_system?.length,d=rv(r,this._openingDimensionContextCache.value).map(e=>({x:e.label[0],y:e.label[1],text:li(e.distance/this._gridPitch*this._cellCm,h),dimension:e}));return{...r,face:c,measure:{labels:d,guide:r.measure.guide}}}_activateOpeningPlacement(e){this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingPreset=function(e,t){return{type:e,lengthCm:Bf(e),flipH:!1,flipV:!1,revision:t}}(e,++this._openingPresetRevision),this._openingHoverCandidate=null,this._cursorPt=null)}_clearOpeningPlacement(e){this._openingHoverCandidate=null,this._openingJambBlockCm=null,e&&(this._openingPreset=null,this._openingRebindId=null)}_openingClick(e){const t=this._spaceModel();if(!t)return;const i=this._openingRebindId?null:this._openingAt(e);if(i)return void this._editOpening(i);const s=this._openingPreset;if(!s)return;const n=this._openingHoverCandidate,o=n&&Gf(n,[e[0],e[1]],s.revision,this._cfgEpoch)?n:this._resolveOpeningPlacement(e);if(!o){if(null!=this._openingJambBlockCm)return void this._showToast(this._t("opening.partition_jamb_margin",{distance:li(this._openingJambBlockCm,this._imperial)}));const i=1.5*this._gridPitch,s=ui(e,t.rooms,i);return s&&function(e,t,i,s,n){for(const o of s)if(!(Hs([e,t],o)>n)&&Nl([o[0],o[1]],[o[2],o[3]],i))return!0;return!1}(s.x,s.y,s.angle,this._openCuts(),i)?void this._showToast(this._t("toast.opening_on_zero_wall")):void this._showToast(this._t("toast.opening_no_wall"))}const a=this._openingRebindId?this._curSpaceCfg?.openings?.find(e=>e.id===this._openingRebindId):null;this._openingDialog={...a?{id:a.id,type:a.type,lengthCm:Math.round(a.length*Pv/this._gridPitch*this._cellCm),lengthTouched:!1,contact:a.contact||"",lock:a.lock||"",invert:!!a.invert,flipH:!!a.flip_h,flipV:!!a.flip_v}:{type:o.type,lengthCm:o.lengthCm,contact:"",lock:"",invert:!1,flipH:o.flipH,flipV:o.flipV},...o.host?{host:o.host}:{},x:o.x,y:o.y,angle:o.angle},this._openingRebindId=null,this._openingHoverCandidate=null,this._cursorPt=null}_editOpening(e){this._openingDialog={id:e.id,type:e.type,lengthCm:Math.round(e.rlen/this._gridPitch*this._cellCm),lengthTouched:!1,contact:e.contact||"",lock:e.lock||"",invert:!!e.invert,flipH:!!e.flip_h,flipV:!!e.flip_v,..."partition"===e.host?.kind?{host:{...e.host}}:{},x:e.rx,y:e.ry,angle:e.angle}}_opPointerDown(e,t){if("plan"===this._mode&&this._spaceModel()&&"resize"!==this._tool){e.preventDefault(),e.stopPropagation();try{Ev(e)}catch{}this._opDrag={id:t.id,moved:!1,sx:e.clientX,sy:e.clientY,dirty:!1,before:this._geometrySnapshot()}}}_opPointerMove(e,t){if(!this._opDrag||this._opDrag.id!==t.id)return;if(Math.abs(e.clientX-this._opDrag.sx)+Math.abs(e.clientY-this._opDrag.sy)<=3)return;const i=this._spaceModel();if(!i)return;const s=this._svgPoint(e),n=this._curSpaceCfg,o=n?.openings?.find(e=>e.id===t.id);if(!o)return;if("partition"===o.host?.kind){const e=i.partitions.find(e=>e.id===o.host.id);if(!e)return;const t=e.b[0]-e.a[0],n=e.b[1]-e.a[1],a=Math.hypot(t,n);if(!(a>1e-9))return;const r=t/a,l=n/a;if(Math.abs((s[0]-e.a[0])*l-(s[1]-e.a[1])*r)>4*this._gridPitch)return;const c=o.length*Pv/2+Kp(e,this._cellCm,this._gridPitch);let h=(s[0]-e.a[0])*r+(s[1]-e.a[1])*l;if(h=Math.round(h/this._gridPitch)*this._gridPitch,h=Math.max(c,Math.min(a-c,h)),a<2*c-1e-9)return;const d=h/a,p=(e.a[0]+r*h)/Pv,u=(e.a[1]+l*h)/this._spaceH;let _=180*Math.atan2(n,t)/Math.PI;_>=90?_-=180:_<-90&&(_+=180);const m=o.host.t!==d||o.x!==p||o.y!==u||o.angle!==_;return this._opDrag.moved=!0,m&&(this._opDrag.dirty=!0),o.host={...o.host,t:d},o.x=p,o.y=u,o.angle=_,this._opMeasure=null,m&&this._cfgEpoch++,void this.requestUpdate()}const a=ui(s,i.rooms,4*this._gridPitch);if(!a)return;this._opDrag.moved=!0;const r=this._opRuler(a,o.length*Pv);this._opMeasure=r.measure;const l=r.x/Pv,c=r.y/this._spaceH,h=o.x!==l||o.y!==c||o.angle!==a.angle;if(h&&(this._opDrag.dirty=!0),o.x=l,o.y=c,o.angle=a.angle,Number(this._serverCfg?.model_version||0)>=9){const e=wg(o,n?.wall_segments||[]);e?o.host=e:delete o.host}h&&this._cfgEpoch++,this.requestUpdate()}_opRuler(e,t){const i=this._spaceModel()?.rooms||[],s=this._gridPitch/2;let n=e.x,o=e.y,a=_i([n,o],e.angle,t,i,s);if(a&&a.centered&&(n!==a.wallCenter[0]||o!==a.wallCenter[1]))[n,o]=a.wallCenter,a=_i([n,o],e.angle,t,i,s);else if(a){const[r,l]=a.wallA,[c,h]=a.wallB,d=c-r,p=h-l,u=Math.hypot(d,p);if(u>0){const c=this._gridPitch,h=Math.min(t/2,u/2);let _=Math.round(((n-r)*d+(o-l)*p)/u/c)*c;_=Math.max(h,Math.min(u-h,_)),n=r+_/u*d,o=l+_/u*p,a=_i([n,o],e.angle,t,i,s)||a}}if(!a)return{x:n,y:o,angle:e.angle,measure:null};const r="mi"===this.hass?.config?.unit_system?.length,l=(e,t)=>({x:t[0],y:t[1],text:li(e/this._gridPitch*this._cellCm,r)});return{x:n,y:o,angle:e.angle,measure:{labels:[l(a.sideA,a.midA),l(a.sideB,a.midB)],guide:a.centered?{x:a.wallCenter[0],y:a.wallCenter[1],angle:e.angle}:null}}}_opPointerUp(e,t){if(!this._opDrag||this._opDrag.id!==t.id)return;const i=this._opDrag,s=i.moved;this._opMeasure=null,s&&i.dirty&&this._commitPhysicalGeometry(this._t("history.move_opening"),i.before),s?window.setTimeout(()=>this._opDrag=null,0):this._opDrag=null}_opClick(e,t){"plan"===this._mode&&"resize"===this._tool||(e.stopPropagation(),this._opDrag?.moved||"plan"===this._mode&&this._editOpening(t))}_saveOpening(){const e=this._openingDialog,t=this._curSpaceCfg,i=this._spaceModel();if(!e||!t||!i)return;const s=this._geometrySnapshot(),n=this._spaceH,o=(t.openings||[]).find(t=>t.id===e.id),a={...o||{},id:e.id||"o"+Date.now().toString(36),type:e.type,x:e.x/Pv,y:e.y/n,angle:e.angle,length:o&&!e.lengthTouched?o.length:this._cmToUnits(Math.max(20,e.lengthCm))/Pv,...e.host?{host:{...e.host}}:{}};if("partition"===a.host?.kind){const e=Zp(o,a)?Xp(a,i.partitions,Pv,this._cellCm,this._gridPitch):Jp(a,i.partitions,Pv,this._cellCm,this._gridPitch);if(!e.resolved){const t=i.partitions.find(e=>e.id===a.host.id);if("does-not-fit-jamb"===e.reason&&t){const e=Kp(t,this._cellCm,this._gridPitch);this._showToast(this._t("opening.partition_jamb_margin",{distance:li(e/this._gridPitch*this._cellCm,this._imperial)}))}else this._showToast(this._t("opening.partition_orphan"));return}const s=(t.openings||[]).flatMap(e=>{if(!e.host||e.id===a.id)return[];const t=Jp(e,i.partitions,Pv,this._cellCm,this._gridPitch).resolved;return t?[t]:[]});if(function(e,t,i=1e-9){const s=e.length/(2*e.axis.length),n=e.t-s,o=e.t+s;return t.some(t=>{if(t.host.id!==e.host.id||t.opening.id===e.opening.id)return!1;const s=t.length/(2*t.axis.length);return Math.max(n,t.t-s)=9){const e=wg(a,t.wall_segments||[]);if(!e)return void this._showToast(this._t("toast.opening_no_wall"));a.host=e}else delete a.host;"passage"===e.type?(delete a.contact,delete a.lock,delete a.invert,delete a.flip_h,delete a.flip_v):(a.contact=e.contact||null,a.lock=("door"===e.type||"gate"===e.type)&&e.lock||null,a.invert=e.invert||void 0,a.flip_h="gate"!==e.type&&e.flipH||void 0,a.flip_v=e.flipV||void 0),t.openings=t.openings||[];const r=t.openings.findIndex(e=>e.id===a.id);r>=0?t.openings[r]=a:t.openings.push(a),this._commitPhysicalGeometry(this._t(e.id?"history.edit_opening":"history.add_opening"),s),this._openingDialog=null,this.requestUpdate()}_deleteOpening(){const e=this._openingDialog,t=this._curSpaceCfg;if(!e?.id||!t?.openings)return;const i=this._geometrySnapshot();t.openings=t.openings.filter(t=>t.id!==e.id),this._commitPhysicalGeometry(this._t("history.delete_opening"),i),this._openingDialog=null,this.requestUpdate()}_contactCandidates(){const e=[];for(const t of Object.keys(this.hass.states)){if(!this._openingEntityAvailable(t))continue;const i=t.split(".")[0];if("binary_sensor"!==i&&"cover"!==i)continue;const s=this.hass.states[t],n=["door","window","opening","garage_door","garage"].includes(s?.attributes?.device_class||"");("cover"!==i||n)&&e.push([t,s?.attributes?.friendly_name||t,n?0:1])}return e.sort((e,t)=>e[2]-t[2]||e[1].localeCompare(t[1])).map(([e,t])=>({value:e,label:t}))}_lockCandidates(){return Object.keys(this.hass.states).filter(e=>e.startsWith("lock.")&&this._openingEntityAvailable(e)).map(e=>({value:e,label:this.hass.states[e]?.attributes?.friendly_name||e})).sort((e,t)=>e.label.localeCompare(t.label))}_toggleOpeningEntityPicker(e){const t=this._openingDialog;if(!t)return;const i="contact"===e?!t.contactOpen:!t.lockOpen;this._openingDialog={...t,contactOpen:"contact"===e&&i,lockOpen:"lock"===e&&i}}_filterOpeningEntities(e,t){const i=this._openingDialog;i&&(this._openingDialog="contact"===e?{...i,contactFilter:t}:{...i,lockFilter:t})}_selectOpeningEntity(e,t){const i=this._openingDialog;i&&(this._openingDialog="contact"===e?{...i,contact:t,contactOpen:!1,contactFilter:""}:{...i,lock:t,lockOpen:!1,lockFilter:""})}_mergeClick(e){const t=this._spaceModel();if(!t)return;const i=t.rooms,s=[...i].reverse().find(t=>this._pointInRoom(e,t));if(!s?.id)return;const n=s.id;if(!this._mergeSel||this._mergeSel===n)return void(this._mergeSel=this._mergeSel===n?null:n);const o=i.find(e=>e.id===this._mergeSel),a=o?hi(o):null,r=hi(s),l=a&&r?function(e,t){if(!e||!t||e.length<3||t.length<3)return null;const i=si(Ii(e),Ii(t));if(1!==i.length)return null;if(1!==i[0].length)return null;const s=i[0][0].slice(0,-1).map(e=>[e[0],e[1]]);return s.length>=3?s:null}(a,r):null;if(!l)return this._showToast(this._t("toast.merge_not_adjacent")),void(this._mergeSel=null);this._mergeDialog={aId:this._mergeSel,bId:n,poly:l,pick:"a"},this._mergeSel=null}_commitMerge(){const e=this._mergeDialog,t=this._curSpaceCfg;if(!e||!t||!this._spaceModel())return;const i=this._geometrySnapshot(),s=this._spaceH,n="a"===e.pick?e.aId:e.bId,o="a"===e.pick?e.bId:e.aId,a=t.rooms.find(e=>e.id===n);if(!a)return void(this._mergeDialog=null);a.poly=e.poly.map(e=>[e[0]/Pv,e[1]/s]),delete a.x,delete a.y,delete a.w,delete a.h,t.rooms=t.rooms.filter(e=>e.id!==o);const r=this._commitPhysicalGeometry(this._t("history.merge_rooms"),i);this._mergeDialog=null,this._regSignature="",this._maybeRebuildDevices(),r&&this._showToast(this._t("toast.rooms_merged",{name:a.name||""}))}_splitClick(e){const t=this._spaceModel();if(!t)return;const i=t.rooms;if(!this._splitSel){const t=[...i].reverse().find(t=>this._pointInRoom(e,t));if(!t?.id)return;return void(this._splitSel={roomId:t.id,pts:[]})}const s=i.find(e=>e.id===this._splitSel.roomId),n=s?hi(s):null;if(!s||!n)return void(this._splitSel=null);const o=.02*this._gridPitch,a=6*this._gridPitch,r=function(e,t){if(!t||t.length<2)return null;let i=null,s=1/0;for(let n=0;n=n)continue;n=_;const m=Math.sqrt(p),g=(i>0?Math.max(0,Math.min(m,Math.round(u*m/i)*i)):u*m)/m;s=[a+g*h,r+g*d]}return s}(r,n,this._gridPitch)||r,c=r&&l&&Math.hypot(r[0]-e[0],r[1]-e[1])<=a?l:null,h=!!c&&yi(c,n,o),d=this._splitSel.pts;if(!d.length)return h?void(this._splitSel={...this._splitSel,pts:[c]}):void this._showToast(this._t("toast.split_pick_wall"));if(!h){const t=this._snap(e);return wi(t,n,o)?void(this._splitSel={...this._splitSel,pts:[...d,t]}):void this._showToast(this._t("toast.split_pick_inside"))}const p=zi(n,[...d,c],o);if(!p)return void this._showToast(this._t("toast.split_bad_cut"));this._resetRoomDialogFields();const[u,_]=p,m=Ti(u)>=Ti(_)?u:_,g=m===u?_:u;this._pendingSplit={roomId:s.id,mainPoly:m,newPoly:g},this._cursorPt=null,this._nameSel="",this._areaSel="",this._roomDialog=!0}get _contourClosed(){return this._path.length>=4&&this._samePt(this._path[0],this._path[this._path.length-1])&&(null!=this._closingWallCm||!this._activeDraftId)}_markupMove(e){if(!this._markup)return;if("column"===this._tool)return void(this._cursorPt=this._snap(this._svgPoint(e)));if("opening"===this._tool||"wallthick"===this._tool)return void(this._cursorPt=this._svgPoint(e));const t="draw"===this._tool&&!this._contourClosed,i="split"===this._tool&&!!this._splitSel?.pts?.length;if(!t&&!i)return;const s=this._svgPoint(e);if(t){const t=this._resolvePlanDrawPoint(s,e.shiftKey);return this._planSnapHover={contextKey:t.contextKey,candidate:t.candidate,conflicts:t.conflicts},this._syncPlanSnapConflictMarkers(t.conflicts),this._path.length?void(this._cursorPt=t.point):void this._syncPlanSnapActiveMarker(t.candidate)}this._cursorPt=this._snap(s)}get _openingPreview(){const e=this._openingPreset;if("opening"!==this._tool||!e||!this._cursorPt)return null;const t=this._cursorPt,i=this._openingHoverCandidate;if(i&&Gf(i,[t[0],t[1]],e.revision,this._cfgEpoch))return i;if(this._openingAt(t))return this._openingHoverCandidate=null,null;const s=this._resolveOpeningPlacement(t);return this._openingHoverCandidate=s,s}get _opMeasureView(){return this._opMeasure||this._openingPreview?.measure||null}_saveRoom(){(this._areaSel||this._nameSel.trim())&&(this._wallFaceBatch?this._decideWallFace(!0):this._commitRoom())}_decideWallFace(e){const t=this._wallFaceBatch;if(!t)return;const i=t.candidates[t.index];if(!i)return;if(!e&&(i.existing||i.repair)&&1===t.candidates.length)return this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",void this.requestUpdate();const s=e?{candidate:i,create:!0,name:this._nameSel.trim(),area:this._areaSel||null,settings:this._roomSettingsFromDialog()?JSON.parse(JSON.stringify(this._roomSettingsFromDialog())):null}:{candidate:i,create:!1},n=[...t.decisions,s],o=t.index+1;if(o"number"==typeof e&&Number.isFinite(e)&&e>=0?e:null,n=.02*this._gridPitch,o=this._spaceModel();if(!o)return ul;for(const t of this._planSnapGeometrySnapshot().value.segments){if("room"===t.sourceKind||Hs(e,[t.a[0],t.a[1],t.b[0],t.b[1]])>n)continue;if("partition"===t.sourceKind)return s(o.partitions.find(e=>e.id===t.sourceId)?.cm)??ul;const i=t.sourceId.lastIndexOf(":"),a=i>=0?t.sourceId.slice(0,i):t.sourceId,r=i>=0?Number(t.sourceId.slice(i+1)):-1;return s(o.room_drafts.find(e=>e.id===a)?.segments[r]?.cm)??ul}const a=ku(Math.max(0,t.length-1),i,this._drawWallCm,ul);for(let i=0;i+1[...e]);if(!t?.sourceKey.startsWith("active:"))return i;const s=/:(\d+)$/.exec(t.sourceKey),n=s?Number(s[1])+("b"===t.endpoint?1:0):-1;return n>=0&&nt.key===e.sourceKey),o=s.find(t=>t.key===e.targetSourceKey);if(!n||!o)return!1;const a="a"===e.endpoint?n.a:n.b;return!(Math.hypot(a[0]-e.from[0],a[1]-e.from[1])>i)&&(!(Hs(e.to,[o.a[0],o.a[1],o.b[0],o.b[1]])>i)&&!function(e,t){if(!e.sourceKey.startsWith("static:partition|"))return!1;const i=e.sourceKey.slice(17).split("|")[0];return!!i&&t.some(e=>"partition"===e.host?.kind&&e.host.id===i)}(e,this._curSpaceCfg?.openings||[]))}_applyWallRepair(e,t){const i=this._curSpaceCfg;if(!i||!this._validateWallRepair(e,t.activePath))return!1;const s=t=>{t[0]=e.to[0]/Pv,t[1]=e.to[1]/Pv};if(e.sourceKey.startsWith("active:")){const n=/:(\d+)$/.exec(e.sourceKey),o=n?Number(n[1])+("b"===e.endpoint?1:0):-1;if(o<0||o>=t.activePath.length)return!1;t.activePath[o]=[...e.to];const a=(i.room_drafts||[]).find(e=>e.id===t.activeDraftId);return a?.points?.[o]&&s(a.points[o]),!0}if(!e.sourceKey.startsWith("static:"))return!1;const[n,o]=e.sourceKey.slice(7).split("|");if("partition"===n){const t=(i.partitions||[]).find(e=>e.id===o);if(!t)return!1;const n=[t.a[0]*Pv,t.a[1]*Pv],a=[t.b[0]*Pv,t.b[1]*Pv],r=Math.hypot(n[0]-e.from[0],n[1]-e.from[1])<=2e-4*this._gridPitch?t.a:Math.hypot(a[0]-e.from[0],a[1]-e.from[1])<=2e-4*this._gridPitch?t.b:null;return!!r&&(s(r),!0)}if("draft"===n){const t=o.lastIndexOf(":"),n=t>=0?o.slice(0,t):"",a=t>=0?Number(o.slice(t+1)):-1,r=(i.room_drafts||[]).find(e=>e.id===n);if(!r?.points?.[a]||!r?.points?.[a+1])return!1;const l=[a,a+1].find(t=>Math.hypot(r.points[t][0]*Pv-e.from[0],r.points[t][1]*Pv-e.from[1])<=2e-4*this._gridPitch);return null!=l&&(s(r.points[l]),!0)}return!1}_applyWallFaceBatch(){const e=this._wallFaceBatch,t=this._curSpaceCfg,i=this._spaceModel();if(!e||!t||!i)return;const s=(e,t)=>{this._showToast(this._t(e,t)),this._roomDialogCancel()},n=e.decisions.filter(e=>e.create),o=n.map(e=>e.candidate.ring),a=i.rooms;for(let e=0;ei.id!==t&&!!hi(i)&&Di(o[e],hi(i)));if(i)return void s("toast.room_overlap",{name:i.name||""})}if((t.rooms||[]).length+n.length>400)return void s("toast.physical_limit");if(n.some(e=>e.candidate.split&&!t.rooms.some(t=>t.id===e.candidate.split.roomId)))return void s("toast.contour_cannot_close");const r=n.map(e=>e.candidate.repair).filter(e=>!!e);if(r.length>1||r[0]&&!this._validateWallRepair(r[0],e.activePath))return void s("toast.wall_repair_changed");const l=this._activePathWithRepair(e.activePath,r[0]),c=2e-4*this._gridPitch,h=new Map;for(let t=0;te.candidate.atomKeys)),t=n.some(e=>e.candidate.consumeAllActive);for(const i of Wu(this._wallGraphSources(l),c)){const s=i.sourceKeys.find(e=>h.has(e));!s||t||e.has(i.key)||d.push({a:i.a,b:i.b,cm:h.get(s)})}}else d.push(...xu(l,ku(l.length-1,e.activeCms,this._drawWallCm,ul)));if((t.partitions||[]).length+d.length>Av)return void s("toast.physical_limit");const p=n.map(e=>e.candidate.ring.map(()=>"")),u=e.activeDraftId?(t.room_drafts||[]).find(t=>t.id===e.activeDraftId):null,_=this._draftSegmentsForPath(e.activePath,u,e.activeCms),m=(e,t)=>{const i=`${e[0].toFixed(9)},${e[1].toFixed(9)}`,s=`${t[0].toFixed(9)},${t[1].toFixed(9)}`;return i<=s?`${i}|${s}`:`${s}|${i}`};for(let t=0;t<_.length;t++){const i=_[t]?.id;if(!i)continue;const s=e.activePath[t],o=e.activePath[t+1],a=[s[0],s[1],o[0],o[1]],r=[];n.forEach((e,t)=>e.candidate.ring.forEach((i,s)=>{const n=e.candidate.ring[(s+1)%e.candidate.ring.length];Hs(i,a)<=c&&Hs(n,a)<=c&&r.push({kind:"room",owner:t,edge:s,a:i,b:n})})),d.forEach((e,t)=>{Hs(e.a,a)<=c&&Hs(e.b,a)<=c&&r.push({kind:"partition",owner:t,edge:0,a:e.a,b:e.b})});const l=[(s[0]+o[0])/2,(s[1]+o[1])/2];r.sort((e,t)=>{const i=[e.a[0],e.a[1],e.b[0],e.b[1]],n=[t.a[0],t.a[1],t.b[0],t.b[1]];return(Hs(l,i)<=c?0:1)-(Hs(l,n)<=c?0:1)||(Hs(s,i)<=c?0:1)-(Hs(s,n)<=c?0:1)||m(e.a,e.b).localeCompare(m(t.a,t.b))});const h=r[0];if(!h)continue;const u=m(h.a,h.b);for(const e of r)m(e.a,e.b)===u&&("room"===e.kind?p[e.owner][e.edge]=i:d[e.owner].id=i)}const g=this._geometrySnapshot();if(r[0]&&!this._applyWallRepair(r[0],e))return void s("toast.wall_repair_changed");const f=n.some(e=>!!e.candidate.split),v=f?fc(i.rooms,t.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Pv):null,b=f&&Array.isArray(t.walls)?t.walls:null;for(const e of n){const i=e.candidate.split;if(!i)continue;const n=t.rooms.find(e=>e.id===i.roomId);if(!n)return void s("toast.contour_cannot_close");n.poly=i.mainPoly.map(e=>[e[0]/Pv,e[1]/this._spaceH]),delete n.x,delete n.y,delete n.w,delete n.h}const y=Date.now().toString(36),w=[];if(n.forEach((e,i)=>{const s=e.area?this.hass.areas[e.area]?.name:"",n={id:`r${y}-${i}`,name:e.name||s||this._t("room.default_name"),area:e.area||null,poly:e.candidate.ring.map(e=>[e[0]/Pv,e[1]/this._spaceH]),...p[i].some(Boolean)?{wall_ids:p[i]}:{},...e.settings?{settings:JSON.parse(JSON.stringify(e.settings))}:{}};t.rooms.push(n),w.push({room:n,decision:e})}),e.activeDraftId&&Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t.id!==e.activeDraftId),t.room_drafts.length||delete t.room_drafts),d.length&&(t.partitions||=[],d.forEach((e,i)=>t.partitions.push({id:e.id||`partition-${y}-${i}`,a:[e.a[0]/Pv,e.a[1]/Pv],b:[e.b[0]/Pv,e.b[1]/Pv],cm:e.cm}))),f){const e=this._normalizeWalls(v,this._openCuts());e.length?t.walls=e:b?.length?t.walls=b:delete t.walls}if(w.length){this._cfgEpoch++;const i=this._openCuts(),s=this._spaceModel();if(!s)return;let n=t.walls;for(const{room:t,decision:o}of w){const a=o.candidate.ring,r=this._wallSourceCmAt(a[0],e.activePath,e.activeCms);n=jl(n,s.rooms,t.id,r,this._wallKeyPitch,i,Pv);for(const o of gc(s.rooms,n,i,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv)){if(o.roomId!==t.id||"outer"!==o.kind)continue;const i=[(o.a[0]+o.b[0])/2,(o.a[1]+o.b[1])/2];n=Ll(n,o.a,o.b,this._wallSourceCmAt(i,e.activePath,e.activeCms),this._wallKeyPitch,Pv)}}const o=this._normalizeWalls(n,i);o.length?t.walls=o:delete t.walls}if(!this._commitPhysicalGeometry(this._t("history.wall_face_batch"),g))return;delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices();const k=new Set(n.map(e=>e.area).filter(e=>!!e));if(k.size){const e={...this._layout};for(const t of this._devices){if(!k.has(t.area||"")||t.space!==this._space)continue;if(this._layout[t.id])continue;const i=this._defPos[t.id];i&&(e[t.id]={s:this._space,x:i.x/Pv,y:i.y/Pv},this._dirtyPos.add(t.id))}this._layout=e,this._persistLayout()}this._showToast(this._t(n.length?"toast.wall_rooms_saved":"toast.wall_chain_saved",{n:n.length}))}_commitRoom(){const e=this._curSpaceCfg,t=this._spaceModel();if(!e||!t)return;const i=this._geometrySnapshot(),s=this._spaceH,n=!!this._pendingSplit,o=n?fc(t.rooms,e.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Pv):null,a=n&&Array.isArray(e.walls)?e.walls:null;let r;if(this._pendingSplit){const t=e.rooms.find(e=>e.id===this._pendingSplit.roomId);if(!t)return this._pendingSplit=null,this._splitSel=null,void(this._roomDialog=!1);t.poly=this._pendingSplit.mainPoly.map(e=>[e[0]/Pv,e[1]/s]),delete t.x,delete t.y,delete t.w,delete t.h,r=this._pendingSplit.newPoly}else{if(!this._contourClosed)return;r=this._path.slice(0,-1)}const l=this._areaSel?this.hass.areas[this._areaSel]?.name:"",c={id:"r"+Date.now().toString(36),name:this._nameSel||l||this._t("room.default_name"),area:this._areaSel||null,poly:r.map(e=>[e[0]/Pv,e[1]/s]),...this._roomSettingsFromDialog()?{settings:this._roomSettingsFromDialog()}:{}};if(!n&&this._activeDraftId){const t=Array.isArray(e.room_drafts)?e.room_drafts.find(e=>e.id===this._activeDraftId):null,i=ku(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,ul),s=this._draftSegmentsForPath(this._path,t,i);s.length===r.length&&s.every(e=>!!e.id)&&(c.wall_ids=s.map(e=>e.id))}if(e.rooms.push(c),!n&&this._activeDraftId&&Array.isArray(e.room_drafts)&&(e.room_drafts=e.room_drafts.filter(e=>e.id!==this._activeDraftId),e.room_drafts.length||delete e.room_drafts),n){const t=this._normalizeWalls(o,this._openCuts());t.length?e.walls=t:a?.length?e.walls=a:delete e.walls}if(!n){const t=ku(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,ul),i=t[0];if(null!=i){this._cfgEpoch++;const s=this._openCuts(),n=this._spaceModel();if(!n)return;let o=jl(e.walls,n.rooms,c.id,i,this._wallKeyPitch,s,Pv);for(const e of gc(n.rooms,o,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv)){if(e.roomId!==c.id||"outer"!==e.kind)continue;const i=[(e.a[0]+e.b[0])/2,(e.a[1]+e.b[1])/2],s=r.findIndex((e,t)=>{const s=r[(t+1)%r.length];return Hs(i,[e[0],e[1],s[0],s[1]])<=.02*this._gridPitch});s>=0&&(o=Ll(o,e.a,e.b,t[s],this._wallKeyPitch,Pv))}o=this._normalizeWalls(o,s),o.length?e.walls=o:delete e.walls}}const h=this._commitPhysicalGeometry(this._t(n?"history.split_room":"history.add_room"),i);this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._pendingSplit=null,this._splitSel=null;const d=this._areaSel;if(this._areaSel="",this._nameSel="",this._roomDialog=!1,this._regSignature="",this._maybeRebuildDevices(),!h)return;let p=0;if(d){const e=Pv,t={...this._layout};for(const i of this._devices){if(i.area!==d||i.space!==this._space)continue;if(p++,this._layout[i.id])continue;const s=this._defPos[i.id];s&&(t[i.id]={s:this._space,x:s.x/Pv,y:s.y/e},this._dirtyPos.add(i.id))}this._layout=t,this._persistLayout()}const u=this._model.find(e=>e.id===this._space)?.rooms.length||0;this._showToast(d?this._t("toast.room_saved",{n:u,added:p}):this._t("toast.room_saved_no_area",{n:u}))}_cancelPath(){this._wallRepairDiagnostic=null,this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),this._roomDialog=!1,this._pendingSplit=null,this._wallFaceBatch=null,this._splitSel=null,this._mergeSel=null,this._mergeDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._clearOpeningPlacement(!0)}_resumeLastDraft(){const e=this._resumeDraftBySpace[this._space];if(!e)return;const t=this._spaceModel()?.room_drafts.find(t=>t.id===e);t?(this._activeDraftId=e,this._path=t.points.map(e=>[...e]),this._draftSegmentCms=this._adoptDraftCms(this._path,t.segments.map(e=>e.cm),t.id),this._clearPlanSnapHover()):delete this._resumeDraftBySpace[this._space]}_roomDialogCancel(){if(this._roomDialog=!1,this._roomEditId)return this._roomEditId=null,this._nameSel="",void(this._areaSel="");if(this._wallFaceBatch){const e=this._wallFaceBatch;return this._wallFaceBatch=null,this._path=e.activePath.map(e=>[...e]),this._draftSegmentCms=[...e.activeCms],this._activeDraftId=e.activeDraftId,this._nameSel="",this._areaSel="",void this.requestUpdate()}if(this._pendingSplit)return this._pendingSplit=null,void(this._splitSel=null);this._undoPoint()}get _freeAreas(){const e=new Set;for(const t of this._serverCfg?.spaces||[])for(const i of t.rooms||[])i.area&&e.add(i.area);for(const t of this._wallFaceBatch?.decisions||[])t.create&&t.area&&e.add(t.area);return Object.values(this.hass?.areas||{}).filter(t=>!e.has(t.area_id)).sort((e,t)=>(e.name||"").localeCompare(t.name||""))}_openDeviceInbox(){this._deviceInboxReturn=null,this._deviceInbox=this._deviceInbox||{tab:"on_plan",search:"",showEntities:!1,onlyNew:!1,limit:100}}_closeMarkerDialog(){if(this._markerDialog=null,this._deviceInboxReturn){const e={...this._deviceInboxReturn};this._deviceInbox=e,this._deviceInboxReturn=null,e.anchor&&this.updateComplete.then(()=>requestAnimationFrame(()=>{const t=`.device-inbox-row[data-binding="${CSS.escape(e.anchor)}"]`;this.renderRoot.querySelector(t)?.scrollIntoView({block:"nearest"})}))}}_deviceInboxCandidates(e){return gp({hass:this._planHass,devices:this._devices,markers:this._markers,showEntities:e,labels:{device:this._t("marker.sub_device"),z2mGroup:this._t("marker.sub_z2m_group"),group:this._t("marker.sub_group"),helper:this._t("marker.sub_helper"),entity:this._t("marker.sub_entity")}})}_deviceInboxRows(){const e=this._deviceInbox||this._deviceInboxReturn,t=!!e?.showEntities,i=[this._haRegistry.revision,this._cfgRev,this._cfgEpoch,this._regSignature,this._newSyncKey,t?1:0,this._showAll?1:0,ra(this.hass,this._config?.language)].join("|");if(this._deviceInboxMemo?.key===i)return this._deviceInboxMemo.rows;const s=this._deviceInboxCandidates(t),n=new Set(s.map(e=>e.value));for(const e of this._markers)e.binding&&"virtual"!==e.binding&&n.add(e.binding);for(const e of this._devices)e.bindingKind&&"virtual"!==e.bindingKind&&e.bindingRef&&n.add(`${e.bindingKind}:${e.bindingRef}`);const o=new Map;for(const e of n)o.set(e,this._bindingStatus(e));const a=this._areaToSpace,r={};for(const[e,t]of Object.entries(this.hass?.areas||{}))r[e]=a[e]?.room?.name||t?.name||e;for(const[e,t]of Object.entries(a))r[e]=t.room.name||r[e]||e;const l=Object.fromEntries(this._model.map(e=>[e.id,e.title])),c=Object.fromEntries(Object.entries(a).map(([e,t])=>[e,t.space])),h={},d=new Map;for(const[e,t]of Object.entries(this._fullRegistryHass.entities||{})){const i=String(t?.platform||"").trim();if(i&&(h[`entity:${e}`]=i),i&&t?.device_id){const e=d.get(t.device_id)||new Set;e.add(i),d.set(t.device_id,e)}}for(const[e,t]of d)h[`device:${e}`]=[...t].sort().join(", ");const p={};for(const[e,t]of Object.entries(this._fullRegistryHass.devices||{})){const i=`device:${e}`,s=d.get(e)||new Set,n=Array.isArray(t?.identifiers?.[0])?String(t.identifiers[0][0]||""):"",o=[n,...s].some(e=>this._excluded.has(e));"service"===t?.entry_type?p[i]="service_entry":o?p[i]="excluded_integration":"Group"===t?.model?p[i]="grouped_light":/scene/i.test(t?.model||"")?p[i]="excluded_domain":(/bridge/i.test(`${t?.model||""}${t?.name||""}`)||"myheat"===n&&t?.via_device_id)&&(p[i]="represented_by_parent")}const u=function(e){const{devices:t,markers:i,candidates:s,statuses:n,newDeviceIds:o,showHiddenOnPlan:a,areaNames:r={},spaceNames:l={},spaceByArea:c={},integrationByBinding:h={},reasonByBinding:d={}}=e,p=new Map;for(const e of t)!e.virtual&&e.bindingKind&&"virtual"!==e.bindingKind&&e.bindingRef&&p.set(`${e.bindingKind}:${e.bindingRef}`,e);const u=new Map,_=new Map;for(const e of i)e?.binding&&"virtual"!==e.binding&&(e.removed?_.set(e.binding,e):u.set(e.binding,e));const m=new Map(s.map(e=>[e.value,e])),g=new Set([...p.keys(),...u.keys(),...m.keys(),...[..._.keys()].filter(e=>m.has(e))]),f=[];for(const e of g){const t=p.get(e),i=u.get(e),s=i?void 0:_.get(e),g=m.get(e);let v;if(s&&g)v="readd";else if(!0===i?.hidden)v="hidden";else if(t||i)v="on_plan";else{if(!g)continue;v="available"}const b=t?.bindingStatus||n.get(e)||fp,y=i||s,w=vp(e),k=t?.area||g?.areaId||y?.area||"",x=t?.space||y?.space||c[k]||"",$=t?.name||y?.name||g?.label||e,S=t?.model||y?.model||g?.model||"",M=!!g?.parentDeviceId&&p.has(`device:${g.parentDeviceId}`),C="readd"===v?"removed":"hidden"===v?i&&bp(i)?d[e]||"automatic_hidden":"manual_hidden":"on_plan"===v?i?"visible_explicit":"visible_auto":d[e]||(M?"represented_by_parent":k&&x?"available":"no_bound_room"),D=!!t&&(!t.hidden||a),P="active"===b.kind,T=D&&(P||"ha_disabled"===b.kind&&a),I=[$,S,h[e],r[k],l[x],e,g?.sub].filter(Boolean).join(" ").toLocaleLowerCase();f.push({key:e,binding:e,category:v,status:b,reason:C,deviceId:t?.id,markerId:y?.id,name:$,icon:t?.icon||y?.icon||("entity"===w?"mdi:code-braces":"mdi:devices"),model:S,integration:h[e]||"",areaId:k,areaName:r[k]||"",spaceId:x,spaceName:l[x]||"",kind:w,isNew:!!t&&o.has(t.id),searchText:I,canFind:T,canEdit:!!t||!!i,canHide:"on_plan"===v&&P,canShow:"hidden"===v&&P,canAdd:("available"===v||"readd"===v)&&P})}const v=e=>"active"===e.status.kind?1:0;return f.sort((e,t)=>e.category.localeCompare(t.category)||Number(t.isNew)-Number(e.isNew)||v(e)-v(t)||e.name.localeCompare(t.name)||e.binding.localeCompare(t.binding))}({devices:this._devices,markers:this._markers,candidates:s,statuses:o,newDeviceIds:this._newIds,showHiddenOnPlan:this._showAll,areaNames:r,spaceNames:l,spaceByArea:c,integrationByBinding:h,reasonByBinding:p});return this._deviceInboxMemo={key:i,rows:u},u}_deviceForInboxRow(e){const t=e.deviceId?this._devices.find(t=>t.id===e.deviceId):null;if(t)return t;const i=e.markerId?this._markers.find(t=>t.id===e.markerId):null;return!i||i.removed?null:{id:i.id,name:e.name,model:e.model,area:e.areaId,space:e.spaceId||this._space,hidden:!0===i.hidden||"ha_disabled"===e.status.kind,userHidden:!0===i.hidden,bindingStatus:e.status,icon:e.icon,entities:"active"===e.status.kind?e.status.enabledEntityIds:[],allEntities:e.status.allEntityIds,primary:"active"===e.status.kind?e.status.enabledEntityIds[0]:void 0,marker:i,bindingKind:e.kind,bindingRef:e.binding.slice(e.binding.indexOf(":")+1),pdfs:i.pdfs||[]}}_openInboxMarker(e,t=!1){const i=this._deviceInbox;if(i){if(this._deviceInboxReturn={...i,anchor:e.key},this._deviceInbox=null,!t){const t=this._deviceForInboxRow(e);return void(t?this._openMarkerDialog(t):this._closeMarkerDialog())}this._openMarkerDialog(),this._markerDialog?this._markerDialog={...this._markerDialog,bindingMode:"ha",binding:e.binding,bindingOpen:!1,showEntities:"entity"===e.kind,name:""}:this._closeMarkerDialog()}}async _setInboxHidden(e,t){const i=this._deviceInbox,s=this._serverCfg;if(!i||!s||i.busy||"active"!==e.status.kind)return;const n=s.markers||[],o=n.find(t=>!t.removed&&t.binding===e.binding);if(!t&&!o)return;const a=o?.id||Fi(e.binding,e.markerId,()=>`m_${Date.now().toString(36)}`),r=o?{...o,hidden:t}:{id:a,binding:e.binding,hidden:!0};s.markers=[...n.filter(t=>t.id!==a&&(t.binding!==e.binding||!0===t.removed)),r],this._deviceInbox={...i,busy:e.key,anchor:e.key};try{await this._saveConfigNow(),this._regSignature="",this._deviceInboxMemo=null,this._maybeRebuildDevices(),this._deviceInbox&&(this._deviceInbox={...this._deviceInbox,busy:void 0}),this._showToast(this._t("device_inbox.saved"))}catch(e){this._serverCfg===s&&(s.markers=n),this._deviceInbox&&(this._deviceInbox={...this._deviceInbox,busy:void 0}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}_findInboxDevice(e){if(!e.canFind)return;const t=this._deviceForInboxRow(e);if(!t)return;if(this._deviceInbox=null,t.space&&t.space!==this._space){if(!this._commitSpace(t.space))return;this._restoreZoom()}const i=()=>{const e=this._devices.find(e=>e.id===t.id)||t,i=this._pos(e);this._applyView(this._zoom,i.x,i.y),this._selId=e.id,this.requestUpdate(),window.setTimeout(()=>{this._selId===e.id&&(this._selId=null,this.requestUpdate())},1500)};requestAnimationFrame(()=>requestAnimationFrame(i))}_deviceInboxTabKey(e){if("ArrowLeft"!==e.key&&"ArrowRight"!==e.key)return;const t=this._deviceInbox;if(!t)return;const i=["on_plan","available","hidden","readd"],s="ArrowRight"===e.key?1:-1,n=(i.indexOf(t.tab)+s+i.length)%i.length;this._deviceInbox={...t,tab:i[n],limit:100,onlyNew:!1},e.preventDefault()}_openMarkerDialog(e){if(this._vacAllCamerasFor=null,this._vacAllCameraCache=null,e&&this._ackNewDevice(e.id),this._norm)if(e){const t=e.marker,i=Object.prototype.hasOwnProperty.call(t||{},"is_light"),s=Object.prototype.hasOwnProperty.call(t||{},"light_entity"),n=Object.prototype.hasOwnProperty.call(t||{},"glow_color"),o=Object.prototype.hasOwnProperty.call(t||{},"value_badge"),a=Object.prototype.hasOwnProperty.call(t||{},"tap_action"),r=Object.prototype.hasOwnProperty.call(t||{},"toggle_entity"),l=ks(t?.glow_color),c=this._devicePresentation(e,!0).valueBadge,h=qo(this._planHass,e,this._devices),d=Wo(this._planHass,e,h);this._markerDialog={devId:e.id,name:e.name,binding:"virtual"===e.bindingKind?"virtual":e.bindingKind+":"+e.bindingRef,bindingMode:"virtual"===e.bindingKind?"virtual":"ha",bindingOpen:!1,showEntities:"entity"===e.bindingKind&&!!this._fullRegistryHass.entities[e.bindingRef||""]?.device_id,bindingFilter:"",icon:e.marker?.icon||"",autoIcon:e.icon||"",display:Bi(e.marker?.display),rippleColor:Ie(e.marker?.ripple_color,""),rippleSize:Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,size:Number(e.marker?.size)>0?Number(e.marker.size):1,angle:Number(e.marker?.angle)||0,tapAction:Op(e.marker?.tap_action,e.primary?.split(".")[0]),tapActionTouched:!1,originalHasTapAction:a,originalTapAction:e.marker?.tap_action,tapHintAnnouncement:"",toggleEntity:t?.toggle_entity||"",toggleEntityTouched:!1,originalHasToggleEntity:r,originalToggleEntity:t?.toggle_entity,tapTarget:e.marker?.tap_target||"",tapConfirm:!0===e.marker?.tap_confirm,runFilter:"",controls:Zn(e.marker?.binding,e.marker?.controls,e.entities),controlsFilter:"",lightRole:!0===t?.is_light?"always":!1===t?.is_light?"never":"auto",lightRoleTouched:!1,originalHasIsLight:i,originalIsLight:t?.is_light,lightEntity:t?.light_entity||"",lightEntityTouched:!1,originalHasLightEntity:s,originalLightEntity:t?.light_entity,glowMode:null!=l?.bri?"fixed":l?"color":"auto",glowColor:l?.c||this._fillColors.glow_light.c,glowBrightness:Math.max(1,Math.round(100*(l?.bri??1))),glowColorDrafted:!!l,glowBrightnessDrafted:null!=l?.bri,glowTouched:!1,originalHasGlowColor:n&&(!!l||null===t?.glow_color),originalGlowColor:l||(null===t?.glow_color?null:void 0),valueBadgeEnabled:o?!0===t?.value_badge?.enabled:!!c,valueBadgeSource:t?.value_badge?.source||c?.source||d,valueBadgePosition:t?.value_badge?.position||c?.position||"right",valueBadgeTouched:!1,originalHasValueBadge:o,originalValueBadge:t?.value_badge,useClimateTemp:!0===e.marker?.use_climate_temp,glowRadius:Number(e.marker?.glow_radius_cm)>0?String(this._imperial?Math.round(Number(e.marker.glow_radius_cm)/30.48*10)/10:Math.round(Number(e.marker.glow_radius_cm))/100):"",model:e.model||"",link:e.link||"",description:e.description||"",pdfs:[...e.pdfs||[]],room:e.marker?.room_id?e.space+"#@"+e.marker.room_id:e.space&&e.area?e.space+"#"+e.area:"",hideFromPlan:!0===e.marker?.hidden,busy:!1}}else this._markerDialog={name:"",binding:"virtual",bindingMode:"virtual",bindingOpen:!1,showEntities:!1,bindingFilter:"",icon:"",autoIcon:"",display:"badge",rippleColor:"",rippleSize:1.5,size:1,angle:0,tapAction:"info",tapActionTouched:!1,originalHasTapAction:!1,originalTapAction:void 0,tapHintAnnouncement:"",toggleEntity:"",toggleEntityTouched:!1,originalHasToggleEntity:!1,originalToggleEntity:void 0,tapTarget:"",tapConfirm:!1,runFilter:"",controls:[],controlsFilter:"",lightRole:"auto",lightRoleTouched:!1,originalHasIsLight:!1,originalIsLight:void 0,lightEntity:"",lightEntityTouched:!1,originalHasLightEntity:!1,originalLightEntity:void 0,glowMode:"auto",glowColor:this._fillColors.glow_light.c,glowBrightness:100,glowColorDrafted:!1,glowBrightnessDrafted:!1,glowTouched:!1,originalHasGlowColor:!1,originalGlowColor:void 0,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgePosition:"right",valueBadgeTouched:!1,originalHasValueBadge:!1,originalValueBadge:void 0,useClimateTemp:!1,glowRadius:"",model:"",link:"",description:"",pdfs:[],room:"",hideFromPlan:!1,busy:!1,uploadId:"up_"+Date.now().toString(36)+Math.random().toString(36).slice(2,6)};else this._showToast(this._t("toast.marker_needs_server"))}_runCandidates(){const e=[];for(const t of Gi)for(const[i,s]of Object.entries(this.hass.states))i.startsWith(t+".")&&this._planEntityAvailable(i)&&e.push({value:i,label:s?.attributes?.friendly_name||i,sub:this._t("run."+t)});return e.sort((e,t)=>e.sub.localeCompare(t.sub)||e.label.localeCompare(t.label))}_bindingCandidates(){const e=gp({hass:this._planHass,devices:this._devices,markers:this._markers,showEntities:!!this._markerDialog?.showEntities,currentBinding:this._markerDialog?.binding,currentDeviceId:this._markerDialog?.devId,labels:{device:this._t("marker.sub_device"),z2mGroup:this._t("marker.sub_z2m_group"),group:this._t("marker.sub_group"),helper:this._t("marker.sub_helper"),entity:this._t("marker.sub_entity")}}),t=(this._markerDialog?.bindingFilter||"").toLowerCase().trim(),i=t?e.filter(e=>(e.label+" "+e.sub+" "+e.value).toLowerCase().includes(t)):e;return i.sort((e,t)=>e.label.localeCompare(t.label)),i.slice(0,200)}_physicalBodiesR(e=this._spaceModel()){if(!e)return[];const t=`${e.id}|${this._cfgEpoch}|${this._cellCm}|${this._gridPitch}`;if(this._physicalBodiesCache?.key===t)return this._physicalBodiesCache.all;const i=ch(e,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(e));return this._physicalBodiesCache={key:t,...i},i.all}_rawPhysicalBodiesR(e=this._spaceModel()){if(!e)return[];this._physicalBodiesR(e);const t=this._physicalBodiesCache;return t?[...t.drafts,...t.partitions,...t.columns]:[]}_cleanFloor(e,t,i=this._spaceModel()){if(!i)return{floor:t,geom:null,path:"",area:mh([[[...t,t[0]]]])};const s=e.id||`#${i.rooms.indexOf(e)}`,n=`${i.id}|${this._cfgEpoch}|${s}`;if(!this._resize.preview){const e=gv(this._cleanFloorCache,n);if(e.hit)return e.value}const o=t.map(e=>e[0]),a=t.map(e=>e[1]),r=[Math.min(...o),Math.min(...a),Math.max(...o),Math.max(...a)],l=this._physicalBodiesR(i).filter(e=>{const t=e.map(e=>e[0]),i=e.map(e=>e[1]);return Math.max(...t)>=r[0]&&Math.min(...t)<=r[2]&&Math.max(...i)>=r[1]&&Math.min(...i)<=r[3]}),c=l.length?_h(t,l):null,h={floor:t,geom:c,path:c?nh(c):"",area:mh(c||[[[...t,t[0]]]])};return this._resize.preview||fv(this._cleanFloorCache,n,h,600),h}_autoIconForBinding(e){if("virtual"===e)return"mdi:map-marker";const[t,i]=e.split(":");if(!i)return"";const s=this._fullRegistryHass,n=this._bindingStatus(e),o="active"===n.kind?n.enabledEntityIds:n.allEntityIds;if("device"===t){const e=s.devices?.[i];if(!e)return"mdi:help-circle";const t=o;return t.some(e=>e.startsWith("lock."))?"mdi:lock":yo(s,e.name_by_user||e.name||"",e.model,t,this._iconRules)}if("entity"===t){const e=s.entities?.[i],t=this.hass.states?.[i],n=e?.name||t?.attributes?.friendly_name||i;return i.startsWith("lock.")?"mdi:lock":yo(s,n,"",[i],this._iconRules)}return""}_allRoomsFlat(){const e=[];for(const t of this._serverCfg?.spaces||[])for(const i of t.rooms||[])i.area?e.push({value:t.id+"#"+i.area,label:(t.title||t.id)+" · "+i.name}):i.id&&e.push({value:t.id+"#@"+i.id,label:(t.title||t.id)+" · "+i.name+" · "+this._t("marker.subarea")});return e}_errText(e){if(!e)return this._t("err.unknown");if("string"==typeof e)return e;if("invalid_passage_fields"===e.code){const t=String(e.message||e.error||"").match(/space=([^;]*);\s*opening=([^;]*);\s*fields=([^;]*)/);if(t){const e=this._serverCfg?.spaces?.find(e=>String(e.id)===t[1]),i={contact:"opening.contact_label",lock:"opening.lock_label",invert:"opening.invert",flip_h:"opening.flip_h",flip_v:"opening.flip_v"},s=t[3].split(",").filter(Boolean).map(e=>i[e]?this._t(i[e]):e).join(", ");return this._t("opening.invalid_passage_fields",{room:e?.title||t[1],fields:s})}}if("invalid_partition_opening_jamb_margin"===e.code){const t=String(e.message||e.error||"").match(/margin_cm=([^;]*)/),i=t?Number(t[1]):NaN;if(Number.isFinite(i))return this._t("opening.partition_jamb_margin",{distance:li(i,this._imperial)})}if(e.message)return e.message;if(e.error)return e.error;if(null!=e.code)return this._t("err.code",{code:e.code});try{return JSON.stringify(e)}catch{return String(e)}}_backupErrorText(e){const t=e?.code??e?.error;if("string"==typeof t){const e=`backup.error.${t}`,i=this._t(e);if(i!==e)return i}return this._errText(e)}async _pickMarkerFiles(e){const t=e.target,i=t.files?[...t.files]:[];if(t.value="",!i.length||!this._markerDialog)return;const s=this._markerDialog.uploadId||this._markerDialog.devId||"new",n=[];for(const e of i)try{const t=new FormData;t.append("marker_id",s),t.append("file",e,e.name);const i=this.hass?.fetchWithAuth?await this.hass.fetchWithAuth("/api/houseplan/upload",{method:"POST",body:t}):await fetch("/api/houseplan/upload",{method:"POST",body:t,headers:this.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.hass.auth.data.access_token}`}:{}}),o=await i.json().catch(()=>({}));if(!i.ok||o.error){const e={too_large:this._t("err.too_large",{mb:o.max_mb||50}),bad_ext:this._t("err.bad_ext"),unauthorized:this._t("err.unauthorized")};throw new Error(e[o.error]||o.error||"HTTP "+i.status)}n.push({name:o.name||e.name,url:o.url})}catch(t){this._showToast(this._t("toast.file_failed",{name:e.name,err:this._errText(t)}))}n.length&&this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:[...this._markerDialog.pdfs,...n]},this._showToast(this._t("toast.files_attached",{n:n.length})))}_removeMarkerPdf(e){this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:this._markerDialog.pdfs.filter(t=>t.url!==e)})}_markerLightFields(e){const t={};if(e.lightRoleTouched?"always"===e.lightRole?t.is_light=!0:"never"===e.lightRole&&(t.is_light=!1):e.originalHasIsLight&&(t.is_light=e.originalIsLight??null),e.lightEntityTouched?e.lightEntity&&(t.light_entity=e.lightEntity):e.originalHasLightEntity&&(t.light_entity=e.originalLightEntity??null),e.glowTouched){if("auto"!==e.glowMode){const i={c:Ie(e.glowColor,this._fillColors.glow_light.c)};"fixed"===e.glowMode&&(i.bri=Math.max(.01,Math.min(1,Math.round(e.glowBrightness)/100))),t.glow_color=i}}else e.originalHasGlowColor&&(t.glow_color=e.originalGlowColor??null);return t}_markerTapActionFields(e){return e.tapActionTouched?{tap_action:e.tapAction||null}:e.originalHasTapAction?{tap_action:e.originalTapAction??null}:{}}_markerToggleEntityFields(e){return(t={touched:e.toggleEntityTouched,originalHas:e.originalHasToggleEntity,original:e.originalToggleEntity,value:e.toggleEntity}).touched?t.value?{toggle_entity:t.value}:{}:t.originalHas?{toggle_entity:t.original??null}:{};var t}async _saveMarker(){const e=this._markerDialog;if(!e||e.busy)return;const t=this._effectiveMarkerTapAction(e);if("ha"===e.bindingMode&&(!e.binding||"virtual"===e.binding))return;if("virtual"===e.binding&&!e.name.trim())return void this._showToast(this._t("toast.virtual_name_required"));if("run"===t&&!e.tapTarget)return void this._showToast(this._t("toast.run_target_required"));if(e.valueBadgeTouched&&e.valueBadgeEnabled&&!e.valueBadgeSource)return void this._showToast(this._t("toast.value_badge_source_required"));if("ha"===e.bindingMode){const t=this._bindingStatus(e.binding),i=e.devId?this._markers.find(t=>t.id===e.devId):null,s=!i||i.binding!==e.binding;if("active"!==t.kind&&s)return void this._showToast(this._t("ha_disabled"===t.kind?"toast.ha_disabled_add":"toast.ha_binding_unverified"));if("ha_disabled"===t.kind&&!0===i?.hidden&&!e.hideFromPlan)return this._markerDialog={...e,hideFromPlan:!0},void this._showToast(this._t("entity"===t.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device"))}const i=this._serverCfg;if(!i)return;const s=i.markers||[],n=js(e.room);let o=n?.space||null;const a=n?.area||null,r=n?.roomId||null,l=Fi(e.binding,e.devId,()=>"v_"+Date.now().toString(36)),c=e.devId,h=c?this._devices.find(e=>e.id===c):null,d=n?.space||h?.space||null,p=d?this._spaceModelById(d):this._spaceModel();if(!p)return;const u=p.id;"virtual"!==e.binding||o||(o=u),this._markerDialog={...e,busy:!0};try{const n="virtual"===e.binding?[]:s.filter(t=>t.removed&&t.binding===e.binding).map(e=>e.id),d=n.length>0,_=Zn(e.binding,e.controls,this._bindingEntities(e.binding)),m=s.find(e=>e.id===l||e.id===c)?.vacuum||null,g={id:l,vacuum:m,binding:e.binding,name:e.name.trim()||null,icon:e.icon||null,display:"badge"!==e.display?e.display:null,ripple_color:"icon_ripple"===e.display&&e.rippleColor?e.rippleColor:null,ripple_size:"icon_ripple"===e.display&&1.5!==e.rippleSize?e.rippleSize:null,size:1!==e.size?e.size:null,angle:e.angle?e.angle:null,...this._markerTapActionFields(e),...this._markerToggleEntityFields(e),tap_target:"run"===t&&e.tapTarget||null,tap_confirm:!!e.tapConfirm||null,controls:_.length?_:null,...this._markerLightFields(e),...this._markerValueBadgeFields(e),use_climate_temp:!!e.useClimateTemp||null,glow_radius_cm:(()=>{const t=mv(e.glowRadius);return null==t||t<=0?null:Math.round(this._imperial?30.48*t:100*t)})(),model:e.model.trim()||null,link:e.link.trim()||null,description:e.description.trim()||null,pdfs:e.pdfs,hidden:!!e.hideFromPlan};("virtual"===e.binding||e.room)&&(g.space=o,g.area=a,g.room_id=r);const f=h?.marker?.room_id??null,v=!!e.room&&null!=h&&(h.space!==o||h.area!==a||f!==r);let b=!1;const y=e.uploadId||c;if(y&&y!==l&&g.pdfs?.length)try{const e=await this.hass.callWS({type:"houseplan/files/migrate",from_id:y,to_id:l}),t=e?.mapping||{};g.pdfs=function(e,t,i,s){if(!t||!i||t===i)return e;const n="/files/"+t+"/",o="/files/"+i+"/";return e.map(e=>{if(!e.url.includes(n))return e;const t=e.url.split(n)[1]||"",[i,a]=[t.split("?")[0],t.includes("?")?"?"+t.split("?")[1]:""];if(s){const t=s[decodeURIComponent(i)]??s[i];return t?{...e,url:e.url.split(n+i)[0]+o+encodeURIComponent(t)+a}:e}return{...e,url:e.url.split(n).join(o)}})}(g.pdfs,y,l,t),b=Object.keys(t).length>0}catch(e){this._showToast(this._t("toast.files_migrate_failed",{err:this._errText(e)}))}i.markers=s,c&&c!==l&&(i.markers=function(e,t,i){if(!t||!i||t===i)return[...e];const s=`marker:${t}`,n=`marker:${i}`;return e.map(e=>{const t=Array.isArray(e.controls)?e.controls.map(e=>e===s?n:e):e.controls,i="derived_marker_state"===e.value_badge?.source?.kind&&e.value_badge.source.ref===s?{...e.value_badge,source:{...e.value_badge.source,ref:n}}:e.value_badge;return t===e.controls&&i===e.value_badge?e:{...e,controls:t,value_badge:i}})}(i.markers,c,l)),c&&c!==l&&"derived_marker_state"===g.value_badge?.source?.kind&&g.value_badge.source.ref===`marker:${c}`&&(g.value_badge.source={kind:"derived_marker_state",ref:`marker:${l}`}),i.markers=i.markers.filter(e=>e.id!==l&&e.id!==c&&("virtual"===g.binding||e.binding!==g.binding)),i.markers.push(g);let w=null;const k=c?this._layout[c]:null,x=k?{s:k.s||h?.space||this._space,x:k.x,y:k.y}:c&&h&&this._defPos[c]?this._normPos(h.space,this._defPos[c].x,this._defPos[c].y):null;if(!d&&x&&x.s===u)l===c&&this._layout[l]&&!v||(w={s:x.s,x:x.x,y:x.y},this._layout={...this._layout,[l]:w});else if(d||!this._layout[l]||v){let e=p.vb[0]+p.vb[2]/2,t=p.vb[1]+p.vb[3]/2;const i=r?p.rooms.find(e=>e.id===r):a?p.rooms.find(e=>e.area===a):void 0;i&&([e,t]=this._roomCenter(i)),w=this._normPos(u,e,t),this._layout={...this._layout,[l]:w}}if(await this._saveConfigNow(),w){const e=hl(w);this._layout={...this._layout,[l]:e},this._noteLayoutRev(await this.hass.callWS({type:"houseplan/layout/update",device_id:l,pos:e}))}const $=new Set(n);c&&c!==l&&$.add(c),$.delete(l);for(const e of $)delete this._layout[e],await this.hass.callWS({type:"houseplan/layout/delete",device_id:e}).then(e=>this._noteLayoutRev(e)).catch(()=>{});b&&y&&await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:y}).catch(()=>{}),this._closeMarkerDialog(),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_saved"))}catch(e){this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}async _deleteMarker(){const e=this._markerDialog;if(!e||e.busy||!e.devId)return;const t=e.devId?this._devices.find(t=>t.id===e.devId):null,i=this._markers.find(t=>t.id===e.devId);if(!t&&!i)return;const s=e.name||this._t("device.fallback");if(!confirm(this._t("confirm.remove_marker",{name:s})))return;const n=this._serverCfg;n.markers=n.markers||[];const o=n.markers,a=t?.id||i.id,r=t?"virtual"===t.bindingKind?"virtual":t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:"":i.binding;if(!r)return;const l=function(e,t,i,s){const n=new Set([t]),o=e.filter(e=>{const o=e.id===t||!s&&e.binding===i;return o&&n.add(e.id),!o});return{markers:s?o:[...o,{id:t,binding:i,removed:!0,hidden:!0}],cleanupIds:n}}(n.markers,a,r,"virtual"===r);var c,h;n.markers=(c=l.markers,h=l.cleanupIds,c.map(e=>{if(!Array.isArray(e.controls))return e;const t=e.controls.filter(e=>!("string"==typeof e&&e.startsWith("marker:")&&h.has(e.slice(7))));return t.length===e.controls.length?e:{...e,controls:t.length?t:null}}));const d=l.cleanupIds;this._markerDialog={...e,busy:!0};try{await this._saveConfigNow();for(const e of d){delete this._layout[e],delete this._defPos[e],this._dirtyPos.delete(e),this._sentPos.delete(e);const t=this._activityRt.get(e);t&&clearTimeout(t.timer),this._activityRt.delete(e),this._vacRt.delete(e),delete this._vacSrvTrails[e],await this.hass.callWS({type:"houseplan/layout/delete",device_id:e}).then(e=>this._noteLayoutRev(e)).catch(()=>{}),await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:e}).catch(()=>{}),await this.hass.callWS({type:"houseplan/trail/delete",marker_id:e}).catch(()=>{})}this._deviceInboxReturn&&(this._deviceInboxReturn={...this._deviceInboxReturn,tab:"readd",anchor:r}),this._closeMarkerDialog(),this._infoCard?.id===a&&this._closeInfoCard(),this._selId===a&&(this._selId=null),this._drag?.id===a&&(this._drag=null),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_removed"))}catch(e){this._serverCfg===n&&(n.markers=o),this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}_normPos(e,t,i){return{s:e,x:t/Pv,y:i/Pv}}_openSpaceDialog(e,t){if(this._serverStorage&&this._serverCfg)if("edit"===e){const i=this._serverCfg.spaces.find(e=>e.id===t);if(!i)return;const s=cs(i),n=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?rs(i.settings.custom_fill):null,o="none"===s.fill?{...n||as,a:0}:n;this._spaceDialog={mode:e,spaceId:t,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:s.showBorders,showNames:s.showNames,zeroWallStyle:O_(i),displayTouched:!0,hideDecor:s.hideDecor,hideOpenings:s.hideOpenings,roomColor:s.color,roomOpacity:s.opacity,fillMode:"none"===s.fill?"custom":s.fill,customFill:o,glowEnabled:s.glow,bgColor:s.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:Pr({},i.settings),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:s.tempMin,tempMax:s.tempMax,showLqi:s.showLqi??this._config?.show_signal??!0,cardFontScale:s.cardFontScale,labelTemp:s.labelTemp,labelHum:s.labelHum,labelLqi:s.labelLqi,labelLight:s.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:Sh(Number(i.cell_cm)>0?Number(i.cell_cm):5,this._imperial),cellCmTouched:!1,busy:!1}}else this._spaceDialog={mode:e,title:"",planUrl:null,planFile:null,...Gd(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:ns,roomOpacity:os,fillMode:"custom",customFill:{...as,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:20,tempMax:25,showLqi:this._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:$h(this._imperial),cellCmInput:Sh($h(this._imperial),this._imperial),cellCmTouched:!1,busy:!1};else this._showToast(this._t("toast.integration_missing"))}async _pickPlanFile(e){const t=e.target,i=t.files?.[0];if(!i||!this._spaceDialog)return;const s={"image/svg+xml":"svg","image/png":"png","image/jpeg":"jpg","image/webp":"webp"}[i.type]||(i.name.toLowerCase().endsWith(".svg")?"svg":"");if(!s)return void this._showToast(this._t("toast.plan_formats"));const n=new Uint8Array(await i.arrayBuffer());let o="";for(let e=0;e{const t=new Image;t.onload=()=>e(t.naturalWidth&&t.naturalHeight?t.naturalWidth/t.naturalHeight:1.414),t.onerror=()=>e(1.414),t.src=r});URL.revokeObjectURL(r),this._spaceDialog={...this._spaceDialog,planFile:{ext:s,b64:a,aspect:l,name:i.name}}}_useServerPlan(e){const t=this._spaceDialog;t&&(this._spaceDialog={...t,planUrl:e,planFile:null,pickSaved:!1,savedAspect:void 0},this._aspectJob=this._readPlanAspect(e))}async _readPlanAspect(e){for(let t=0;t<40;t++){const t=this._display(e);if(t){const i=await new Promise(e=>{const i=new Image;i.onload=()=>e(i.naturalWidth&&i.naturalHeight?i.naturalWidth/i.naturalHeight:0),i.onerror=()=>e(0),i.src=t}),s=this._spaceDialog;return s&&s.planUrl===e&&Number.isFinite(i)&&i>0?(this._spaceDialog={...s,savedAspect:i},i):0}if(await new Promise(e=>setTimeout(e,150)),this._spaceDialog?.planUrl!==e)return 0}return 0}async _deleteServerPlan(e){if(confirm(this._t("confirm.delete_plan",{name:e})))try{await this.hass.callWS({type:"houseplan/plans/delete",name:e});const t=this._spaceDialog;t?.saved&&(this._spaceDialog={...t,saved:t.saved.filter(t=>t.name!==e)})}catch(e){this._showToast(this._t("toast.plan_delete_failed",{err:this._errText(e)}))}}_renderServerPlans(e){if(e.savedBusy)return q`
${this._t("space.loading")}
`;const t=e.saved||[];if(!t.length)return q`
${this._t("space.no_saved")}
`;return q`
${t.map(t=>q`
diff --git a/demo/smoke_device_inbox.mjs b/demo/smoke_device_inbox.mjs index 45280fa8..e9c4a6a2 100644 --- a/demo/smoke_device_inbox.mjs +++ b/demo/smoke_device_inbox.mjs @@ -39,6 +39,31 @@ const out = await page.evaluate(async () => { result.onPlanHasRows = root().querySelectorAll('.device-inbox-row[data-category="on_plan"]').length > 0; result.noHorizontalOverflow = !!dialog && dialog.scrollWidth <= dialog.clientWidth + 1; + // The catalog speaks in the plan's room names, not a stale HA Area name. + const initialRoomRow = c._deviceInboxRows() + .find((item) => item.areaId && c._areaToSpace[item.areaId]); + const roomTarget = initialRoomRow ? c._areaToSpace[initialRoomRow.areaId] : null; + const sourceRoom = roomTarget ? c._serverCfg.spaces.find((space) => space.id === roomTarget.space) + ?.rooms?.find((room) => room.id === roomTarget.room.id) : null; + result.hasCatalogRowInPlanRoom = !!roomTarget && !!initialRoomRow && !!sourceRoom; + if (roomTarget && initialRoomRow && sourceRoom) { + const originalRoomName = sourceRoom?.name; + const planRoomName = 'Renamed room on plan'; + sourceRoom.name = planRoomName; + c._cfgEpoch++; + c._deviceInboxMemo = null; + await c.updateComplete; + const roomRow = c._deviceInboxRows().find((item) => item.binding === initialRoomRow.binding); + result.planRoomNameWins = roomRow?.areaName === planRoomName; + result.planRoomNameIsSearchable = !!roomRow?.searchText.includes(planRoomName.toLowerCase()); + sourceRoom.name = originalRoomName; + c._cfgEpoch++; + c._deviceInboxMemo = null; + } else { + result.planRoomNameWins = false; + result.planRoomNameIsSearchable = false; + } + const search = root().querySelector('.device-inbox-search'); search.value = 'Ceiling light'; search.dispatchEvent(new Event('input', { bubbles: true, composed: true })); diff --git a/demo/smoke_editor_tabs.mjs b/demo/smoke_editor_tabs.mjs index 77456d2e..165559a6 100644 --- a/demo/smoke_editor_tabs.mjs +++ b/demo/smoke_editor_tabs.mjs @@ -156,7 +156,7 @@ const res = await page.evaluate(async () => { tabs()[1].click(); await c.updateComplete; out.directSwitch = c._mode === 'devices'; out.devBar = !!sr().querySelector('.editbar.devbar'); - out.devBarBtns = sr().querySelectorAll('.editbar.devbar .btn:not(.barclose)').length === 3; // add/show-all/rules (v1.33.2: Reset removed) + out.devBarBtns = sr().querySelectorAll('.editbar.devbar .btn:not(.barclose)').length === 2; // devices catalog + icon rules (#29) const swapChrome = sr().querySelector('.editorchrome'); const swapInner = swapChrome.querySelector('.editorchrome-inner'); out.editorSwapAnimatesHeight = c._modeTransitionBusy diff --git a/dist/houseplan-card.js b/dist/houseplan-card.js index afd56894..8b02af02 100755 --- a/dist/houseplan-card.js +++ b/dist/houseplan-card.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="a26079e078a9ee59646a22d052bb4c421efecc3bdf00ff88f47c6a8e1fa9fabb";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(e,t,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const i=this.t;if(t&&void 0===e){const t=void 0!==i&&1===i.length;t&&(e=s.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&s.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const s=1===e.length?e[0]:t.reduce((t,i,s)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[s+1],e[0]);return new n(s,e,i)},a=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new n("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,m=_?_.emptyScript:"",g=u.reactiveElementPolyfillSupport,f=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?m:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},b=(e,t)=>!r(e,t),y={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:b};Symbol.metadata??=Symbol("metadata"),u.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=y){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(e,i,t);void 0!==s&&l(this.prototype,e,s)}}static getPropertyDescriptor(e,t,i){const{get:s,set:n}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:s,set(t){const o=s?.call(this);n?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??y}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=p(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const e=this.properties,t=[...h(e),...d(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(a(e))}else void 0!==e&&t.push(a(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(t)i.adoptedStyleSheets=s.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of s){const s=document.createElement("style"),n=e.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=t.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),s=this.constructor._$Eu(e,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(e,t){const i=this.constructor,s=i._$Eh.get(e);if(void 0!==s&&this._$Em!==s){const e=i.getPropertyOptions(s),n="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=s;const o=n.fromAttribute(t,e.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(e,t,i,s=!1,n){if(void 0!==e){const o=this.constructor;if(!1===s&&(n=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??b)(n,t)||i.useDefault&&i.reflect&&n===this._$Ej?.get(e)&&!this.hasAttribute(o._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==n||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===s&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,s=this[t];!0!==e||this._$AL.has(t)||void 0===s||this.C(t,void 0,i,s)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,g?.({ReactiveElement:w}),(u.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,P=`<${D}>`,T=document,I=()=>T.createComment(""),R=e=>null===e||"object"!=typeof e&&"function"!=typeof e,A=Array.isArray,z="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,N=/-->/g,E=/>/g,O=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,j=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),q=j(1),W=j(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=T.createTreeWalker(T,129);function Y(e,t){if(!A(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(t):t}const J=(e,t)=>{const i=e.length-1,s=[];let n,o=2===t?"":3===t?"":"",a=F;for(let t=0;t"===l[0]?(a=n??F,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?O:'"'===l[3]?L:H):a===L||a===H?a=O:a===N||a===E?a=F:(a=O,n=void 0);const d=a===O&&e[t+1].startsWith("/>")?" ":"";o+=a===F?i+P:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?t:d)}return[Y(e,o+(e[i]||"")+(2===t?"":3===t?"":"")),s]};class X{constructor({strings:e,_$litType$:t},i){let s;this.parts=[];let n=0,o=0;const a=e.length-1,r=this.parts,[l,c]=J(e,t);if(this.el=X.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==G&&R(this._$AH)?this._$AA.nextSibling.data=e:this.T(T.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,s="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=X.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(t);else{const e=new Q(s,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=V.get(e.strings);return void 0===t&&V.set(e.strings,t=new X(e)),t}k(e){A(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,s=0;for(const n of e)s===t.length?t.push(i=new ee(this.O(I()),this.O(I()),this,this.options)):i=t[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(e,t=this,i,s){const n=this.strings;let o=!1;if(void 0===n)e=Z(this,e,t,0),o=!R(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const s=e;let a,r;for(e=n[0],a=0;a{const s=i?.renderBefore??t;let n=s._$litPart$;if(void 0===n){const e=i?.renderBefore??null;s._$litPart$=n=new ee(t.insertBefore(I(),e),e,void 0,i??{})}return n._$AI(e),n},ce=globalThis;let he=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=le(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};he._$litElement$=!0,he.finalized=!0,ce.litElementHydrateSupport?.({LitElement:he});const de=ce.litElementPolyfillSupport;de?.({LitElement:he}),(ce.litElementVersions??=[]).push("4.2.2");const pe=2,ue=e=>(...t)=>({_$litDirective$:e,values:t});let _e=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this._$Ct=e,this._$AM=t,this._$Ci=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};const me={},ge=ue(class extends _e{constructor(){super(...arguments),this.ot=me}render(e,t){return t()}update(e,[t,i]){if(Array.isArray(t)){if(Array.isArray(this.ot)&&this.ot.length===t.length&&t.every((e,t)=>e===this.ot[t]))return U}else if(this.ot===t)return U;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,i)}}),{I:fe}=ae,ve=e=>e,be=()=>document.createComment(""),ye=(e,t,i)=>{const s=e._$AA.parentNode,n=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=s.insertBefore(be(),n),o=s.insertBefore(be(),n);i=new fe(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,a=o!==e;if(a){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==n||a){let e=i._$AA;for(;e!==t;){const t=ve(e).nextSibling;ve(s).insertBefore(e,n),e=t}}}return i},we=(e,t,i=e)=>(e._$AI(t,i),e),ke={},xe=(e,t=ke)=>e._$AH=t,$e=e=>{e._$AR(),e._$AA.remove()},Se=(e,t,i)=>{const s=new Map;for(let n=t;n<=i;n++)s.set(e[n],n);return s},Me=ue(class extends _e{constructor(e){if(super(e),e.type!==pe)throw Error("repeat() can only be used in text expressions")}dt(e,t,i){let s;void 0===i?i=t:void 0!==t&&(s=t);const n=[],o=[];let a=0;for(const t of e)n[a]=s?s(t,a):a,o[a]=i(t,a),a++;return{values:o,keys:n}}render(e,t,i){return this.dt(e,t,i).values}update(e,[t,i,s]){const n=(e=>e._$AH)(e),{values:o,keys:a}=this.dt(t,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]=we(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=we(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=we(n[d],o[_]),ye(e,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=we(n[p],o[u]),ye(e,n[d],n[p]),p--,u++;else if(void 0===c&&(c=Se(a,u,_),h=Se(r,d,p)),c.has(r[d]))if(c.has(r[p])){const t=h.get(a[u]),i=void 0!==t?n[t]:null;if(null===i){const t=ye(e,n[d]);we(t,o[u]),l[u]=t}else l[u]=we(i,o[u]),ye(e,n[d],i),n[t]=null;u++}else $e(n[p]),p--;else $e(n[d]),d++;for(;u<=_;){const t=ye(e,l[_+1]);we(t,o[u]),l[u++]=t}for(;d<=p;){const e=n[d++];null!==e&&$e(e)}return this.ut=a,xe(e,l),U}}),Ce=new WeakMap;let De=0;class Pe extends he{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-"+ ++De,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");t?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=e=>{if("Escape"===e.key){e.preventDefault(),e.stopImmediatePropagation(),this._pruneOverlays();const t=this._overlays[this._overlays.length-1];return t?void this._closeOverlay(t,"escape"):void this._requestClose()}if("Tab"!==e.key||this._useHaDialog)return;const t=this.renderRoot.querySelector(".close"),i=t?[t,...this._focusableElements()]:this._focusableElements();if(!i.length)return e.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!e.shiftKey||s!==n&&i.includes(s)?e.shiftKey||s!==o||(e.preventDefault(),n.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Ce.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Ce.set(e,t),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const e=[...this._overlays];this._overlays=[];for(const t of e.reverse())t.close("disconnect");const t=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=t?Ce.get(t):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),t&&s&&requestAnimationFrame(()=>{const e=Ce.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Ce.delete(t);const s=i?.closest("hp-dialog");i?.isConnected&&s&&e.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(e){if(super.firstUpdated(e),!this._useHaDialog){const e=this.renderRoot.querySelector("dialog");e&&!e.open&&e.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let e=document.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return e&&e!==document.body?e:null}_focusableElements(){const e=["[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(","),t=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(e)&&t.push(n),n instanceof HTMLSlotElement){for(const e of n.assignedNodes({flatten:!0}))s(e);return}if(n.shadowRoot){for(const e of n.shadowRoot.childNodes)s(e);return}}for(const e of n.childNodes)s(e)}};for(const e of this.childNodes)s(e);const n=this.overlayPortal();return n&&s(n),t.filter(e=>{let t=e;for(;t;){const e=getComputedStyle(t);if(t.hidden||t.inert||"true"===t.getAttribute("aria-hidden")||"none"===e.display||"hidden"===e.visibility)return!1;if(t=t.assignedSlot||t.parentElement||(t.getRootNode()instanceof ShadowRoot?t.getRootNode().host:null),t===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(e=>e.owner.isConnected)}_closeOverlay(e,t){const i=this._overlays.findIndex(t=>t.token===e.token);i>=0&&this._overlays.splice(i,1),e.close(t)}registerOverlay(e){this._pruneOverlays();const t=this._overlays.find(t=>t.owner===e.owner);t&&this._overlays.splice(this._overlays.indexOf(t),1);const i=e.group||"transient";for(const e of[...this._overlays].reverse())e.group===i&&this._closeOverlay(e,"exclusive");const s={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const e=this._overlays.findIndex(e=>e.token===s.token);e>=0&&this._overlays.splice(e,1)}}closeTransientOverlays(e="outside"){this._pruneOverlays();const t=[...this._overlays].filter(e=>"transient"===(e.group||"transient"));for(const i of t.reverse())this._closeOverlay(i,e);return t.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const e=q` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="30d20d6f6822065e2d5226b18abbb05d8d26bc9ddfff42a327dc483b2446800c";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(e,t,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const i=this.t;if(t&&void 0===e){const t=void 0!==i&&1===i.length;t&&(e=s.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&s.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const s=1===e.length?e[0]:t.reduce((t,i,s)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[s+1],e[0]);return new n(s,e,i)},a=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new n("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,m=_?_.emptyScript:"",g=u.reactiveElementPolyfillSupport,f=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?m:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},b=(e,t)=>!r(e,t),y={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:b};Symbol.metadata??=Symbol("metadata"),u.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=y){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(e,i,t);void 0!==s&&l(this.prototype,e,s)}}static getPropertyDescriptor(e,t,i){const{get:s,set:n}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:s,set(t){const o=s?.call(this);n?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??y}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=p(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const e=this.properties,t=[...h(e),...d(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(a(e))}else void 0!==e&&t.push(a(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(t)i.adoptedStyleSheets=s.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of s){const s=document.createElement("style"),n=e.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=t.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),s=this.constructor._$Eu(e,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(e,t){const i=this.constructor,s=i._$Eh.get(e);if(void 0!==s&&this._$Em!==s){const e=i.getPropertyOptions(s),n="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=s;const o=n.fromAttribute(t,e.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(e,t,i,s=!1,n){if(void 0!==e){const o=this.constructor;if(!1===s&&(n=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??b)(n,t)||i.useDefault&&i.reflect&&n===this._$Ej?.get(e)&&!this.hasAttribute(o._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==n||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===s&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,s=this[t];!0!==e||this._$AL.has(t)||void 0===s||this.C(t,void 0,i,s)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,g?.({ReactiveElement:w}),(u.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,P=`<${D}>`,T=document,I=()=>T.createComment(""),R=e=>null===e||"object"!=typeof e&&"function"!=typeof e,A=Array.isArray,z="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,N=/-->/g,E=/>/g,O=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,j=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),q=j(1),W=j(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=T.createTreeWalker(T,129);function Y(e,t){if(!A(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(t):t}const J=(e,t)=>{const i=e.length-1,s=[];let n,o=2===t?"":3===t?"":"",a=F;for(let t=0;t"===l[0]?(a=n??F,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?O:'"'===l[3]?L:H):a===L||a===H?a=O:a===N||a===E?a=F:(a=O,n=void 0);const d=a===O&&e[t+1].startsWith("/>")?" ":"";o+=a===F?i+P:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?t:d)}return[Y(e,o+(e[i]||"")+(2===t?"":3===t?"":"")),s]};class X{constructor({strings:e,_$litType$:t},i){let s;this.parts=[];let n=0,o=0;const a=e.length-1,r=this.parts,[l,c]=J(e,t);if(this.el=X.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==G&&R(this._$AH)?this._$AA.nextSibling.data=e:this.T(T.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,s="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=X.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(t);else{const e=new Q(s,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=V.get(e.strings);return void 0===t&&V.set(e.strings,t=new X(e)),t}k(e){A(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,s=0;for(const n of e)s===t.length?t.push(i=new ee(this.O(I()),this.O(I()),this,this.options)):i=t[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(e,t=this,i,s){const n=this.strings;let o=!1;if(void 0===n)e=Z(this,e,t,0),o=!R(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const s=e;let a,r;for(e=n[0],a=0;a{const s=i?.renderBefore??t;let n=s._$litPart$;if(void 0===n){const e=i?.renderBefore??null;s._$litPart$=n=new ee(t.insertBefore(I(),e),e,void 0,i??{})}return n._$AI(e),n},ce=globalThis;let he=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=le(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};he._$litElement$=!0,he.finalized=!0,ce.litElementHydrateSupport?.({LitElement:he});const de=ce.litElementPolyfillSupport;de?.({LitElement:he}),(ce.litElementVersions??=[]).push("4.2.2");const pe=2,ue=e=>(...t)=>({_$litDirective$:e,values:t});let _e=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this._$Ct=e,this._$AM=t,this._$Ci=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};const me={},ge=ue(class extends _e{constructor(){super(...arguments),this.ot=me}render(e,t){return t()}update(e,[t,i]){if(Array.isArray(t)){if(Array.isArray(this.ot)&&this.ot.length===t.length&&t.every((e,t)=>e===this.ot[t]))return U}else if(this.ot===t)return U;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,i)}}),{I:fe}=ae,ve=e=>e,be=()=>document.createComment(""),ye=(e,t,i)=>{const s=e._$AA.parentNode,n=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=s.insertBefore(be(),n),o=s.insertBefore(be(),n);i=new fe(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,a=o!==e;if(a){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==n||a){let e=i._$AA;for(;e!==t;){const t=ve(e).nextSibling;ve(s).insertBefore(e,n),e=t}}}return i},we=(e,t,i=e)=>(e._$AI(t,i),e),ke={},xe=(e,t=ke)=>e._$AH=t,$e=e=>{e._$AR(),e._$AA.remove()},Se=(e,t,i)=>{const s=new Map;for(let n=t;n<=i;n++)s.set(e[n],n);return s},Me=ue(class extends _e{constructor(e){if(super(e),e.type!==pe)throw Error("repeat() can only be used in text expressions")}dt(e,t,i){let s;void 0===i?i=t:void 0!==t&&(s=t);const n=[],o=[];let a=0;for(const t of e)n[a]=s?s(t,a):a,o[a]=i(t,a),a++;return{values:o,keys:n}}render(e,t,i){return this.dt(e,t,i).values}update(e,[t,i,s]){const n=(e=>e._$AH)(e),{values:o,keys:a}=this.dt(t,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]=we(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=we(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=we(n[d],o[_]),ye(e,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=we(n[p],o[u]),ye(e,n[d],n[p]),p--,u++;else if(void 0===c&&(c=Se(a,u,_),h=Se(r,d,p)),c.has(r[d]))if(c.has(r[p])){const t=h.get(a[u]),i=void 0!==t?n[t]:null;if(null===i){const t=ye(e,n[d]);we(t,o[u]),l[u]=t}else l[u]=we(i,o[u]),ye(e,n[d],i),n[t]=null;u++}else $e(n[p]),p--;else $e(n[d]),d++;for(;u<=_;){const t=ye(e,l[_+1]);we(t,o[u]),l[u++]=t}for(;d<=p;){const e=n[d++];null!==e&&$e(e)}return this.ut=a,xe(e,l),U}}),Ce=new WeakMap;let De=0;class Pe extends he{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-"+ ++De,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");t?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=e=>{if("Escape"===e.key){e.preventDefault(),e.stopImmediatePropagation(),this._pruneOverlays();const t=this._overlays[this._overlays.length-1];return t?void this._closeOverlay(t,"escape"):void this._requestClose()}if("Tab"!==e.key||this._useHaDialog)return;const t=this.renderRoot.querySelector(".close"),i=t?[t,...this._focusableElements()]:this._focusableElements();if(!i.length)return e.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!e.shiftKey||s!==n&&i.includes(s)?e.shiftKey||s!==o||(e.preventDefault(),n.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Ce.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Ce.set(e,t),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const e=[...this._overlays];this._overlays=[];for(const t of e.reverse())t.close("disconnect");const t=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=t?Ce.get(t):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),t&&s&&requestAnimationFrame(()=>{const e=Ce.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Ce.delete(t);const s=i?.closest("hp-dialog");i?.isConnected&&s&&e.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(e){if(super.firstUpdated(e),!this._useHaDialog){const e=this.renderRoot.querySelector("dialog");e&&!e.open&&e.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let e=document.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return e&&e!==document.body?e:null}_focusableElements(){const e=["[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(","),t=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(e)&&t.push(n),n instanceof HTMLSlotElement){for(const e of n.assignedNodes({flatten:!0}))s(e);return}if(n.shadowRoot){for(const e of n.shadowRoot.childNodes)s(e);return}}for(const e of n.childNodes)s(e)}};for(const e of this.childNodes)s(e);const n=this.overlayPortal();return n&&s(n),t.filter(e=>{let t=e;for(;t;){const e=getComputedStyle(t);if(t.hidden||t.inert||"true"===t.getAttribute("aria-hidden")||"none"===e.display||"hidden"===e.visibility)return!1;if(t=t.assignedSlot||t.parentElement||(t.getRootNode()instanceof ShadowRoot?t.getRootNode().host:null),t===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(e=>e.owner.isConnected)}_closeOverlay(e,t){const i=this._overlays.findIndex(t=>t.token===e.token);i>=0&&this._overlays.splice(i,1),e.close(t)}registerOverlay(e){this._pruneOverlays();const t=this._overlays.find(t=>t.owner===e.owner);t&&this._overlays.splice(this._overlays.indexOf(t),1);const i=e.group||"transient";for(const e of[...this._overlays].reverse())e.group===i&&this._closeOverlay(e,"exclusive");const s={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const e=this._overlays.findIndex(e=>e.token===s.token);e>=0&&this._overlays.splice(e,1)}}closeTransientOverlays(e="outside"){this._pruneOverlays();const t=[...this._overlays].filter(e=>"transient"===(e.group||"transient"));for(const i of t.reverse())this._closeOverlay(i,e);return t.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const e=q` ${this.icon?q``:G} ${this.title} `;return this._useHaDialog?q`
-
`:q``}_openingAt(e){if(!this._openingsR.length)return null;const t=this._openingsR.flatMap(t=>{const i=t.angle*Math.PI/180,s=e[0]-t.rx,n=e[1]-t.ry,o=s*Math.cos(i)+n*Math.sin(i);return Math.abs(o)>t.rlen/2+xh(12,this._cellCm)?[]:[{o:t,localY:-s*Math.sin(i)+n*Math.cos(i)}]});if(!t.length)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s).value;return t.find(({o:e,localY:t})=>{const i="gate"===e.type?!e.flip_v:e.flip_v,s=e.partitionHost||this._spaceWalls.length||"gate"===e.type?this._openingFace(e,n,!!i):{ox:0,oy:0,cm:0,side:-1},o=d_({type:e.type,length:e.rlen,angle:e.angle,amount:this._openingAmt(e),flipH:!!e.flip_h,flipV:!!e.flip_v,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s});return Math.abs(t)<=o.hitHalf})?.o||null}_resolveOpeningPlacement(e){const t=this._openingPreset;if("opening"!==this._tool||!t)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s),o=`${n.key}|partitions:${this._cfgEpoch}`;this._openingPlacementIntervalsCache&&this._openingPlacementIntervalsCache.key===o||(this._openingPlacementIntervalsCache={key:o,value:[...gc(i.rooms,this._spaceWalls,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv),...tu(i.partitions,this._cellCm,this._gridPitch)]}),this._openingDimensionContextCache&&this._openingDimensionContextCache.key===o||(this._openingDimensionContextCache={key:o,value:ev({rooms:i.rooms,walls:this._spaceWalls,openCuts:s,partitions:i.partitions,roomOpenings:this._roomWallOpeningInputs(),partitionCuts:this._partitionOpeningCuts(i),pitch:this._wallKeyPitch,cellCm:this._cellCm,gridPitch:this._gridPitch,coordScale:Pv,epsilon:2e-4*this._gridPitch})});const a=Uf({pointer:[e[0],e[1]],preset:t,geometryRevision:this._cfgEpoch,renderedLength:this._cmToUnits(t.lengthCm),intervals:this._openingPlacementIntervalsCache.value,baseTolerance:1.5*this._gridPitch,bodyPointerPadding:this._cssPxToRender("touch"===this._pointerModality.modality||"pen"===this._pointerModality.modality?10:6),gridStep:this._gridPitch});this._openingJambBlockCm=a.jambBlockedTarget?a.jambBlockedTarget.physicalHalfWidth/this._gridPitch*this._cellCm:null;const r=a.candidate;if(!r)return null;const l="gate"===r.type?!r.flipV:r.flipV;let c;if(r.host){const e=Jp({id:"preview",type:r.type,x:r.x/Pv,y:r.y/Pv,angle:r.angle,length:r.renderedLength/Pv,host:r.host},i.partitions,Pv,this._cellCm,this._gridPitch).resolved;c=e?eu(e,l):{ox:0,oy:0,cm:0,side:-1}}else c=Vc(n.value,{x:r.x,y:r.y,angle:r.angle,length:r.renderedLength,flip_v:l});const h="mi"===this.hass?.config?.unit_system?.length,d=rv(r,this._openingDimensionContextCache.value).map(e=>({x:e.label[0],y:e.label[1],text:li(e.distance/this._gridPitch*this._cellCm,h),dimension:e}));return{...r,face:c,measure:{labels:d,guide:r.measure.guide}}}_activateOpeningPlacement(e){this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingPreset=function(e,t){return{type:e,lengthCm:Bf(e),flipH:!1,flipV:!1,revision:t}}(e,++this._openingPresetRevision),this._openingHoverCandidate=null,this._cursorPt=null)}_clearOpeningPlacement(e){this._openingHoverCandidate=null,this._openingJambBlockCm=null,e&&(this._openingPreset=null,this._openingRebindId=null)}_openingClick(e){const t=this._spaceModel();if(!t)return;const i=this._openingRebindId?null:this._openingAt(e);if(i)return void this._editOpening(i);const s=this._openingPreset;if(!s)return;const n=this._openingHoverCandidate,o=n&&Gf(n,[e[0],e[1]],s.revision,this._cfgEpoch)?n:this._resolveOpeningPlacement(e);if(!o){if(null!=this._openingJambBlockCm)return void this._showToast(this._t("opening.partition_jamb_margin",{distance:li(this._openingJambBlockCm,this._imperial)}));const i=1.5*this._gridPitch,s=ui(e,t.rooms,i);return s&&function(e,t,i,s,n){for(const o of s)if(!(Hs([e,t],o)>n)&&Nl([o[0],o[1]],[o[2],o[3]],i))return!0;return!1}(s.x,s.y,s.angle,this._openCuts(),i)?void this._showToast(this._t("toast.opening_on_zero_wall")):void this._showToast(this._t("toast.opening_no_wall"))}const a=this._openingRebindId?this._curSpaceCfg?.openings?.find(e=>e.id===this._openingRebindId):null;this._openingDialog={...a?{id:a.id,type:a.type,lengthCm:Math.round(a.length*Pv/this._gridPitch*this._cellCm),lengthTouched:!1,contact:a.contact||"",lock:a.lock||"",invert:!!a.invert,flipH:!!a.flip_h,flipV:!!a.flip_v}:{type:o.type,lengthCm:o.lengthCm,contact:"",lock:"",invert:!1,flipH:o.flipH,flipV:o.flipV},...o.host?{host:o.host}:{},x:o.x,y:o.y,angle:o.angle},this._openingRebindId=null,this._openingHoverCandidate=null,this._cursorPt=null}_editOpening(e){this._openingDialog={id:e.id,type:e.type,lengthCm:Math.round(e.rlen/this._gridPitch*this._cellCm),lengthTouched:!1,contact:e.contact||"",lock:e.lock||"",invert:!!e.invert,flipH:!!e.flip_h,flipV:!!e.flip_v,..."partition"===e.host?.kind?{host:{...e.host}}:{},x:e.rx,y:e.ry,angle:e.angle}}_opPointerDown(e,t){if("plan"===this._mode&&this._spaceModel()&&"resize"!==this._tool){e.preventDefault(),e.stopPropagation();try{Ev(e)}catch{}this._opDrag={id:t.id,moved:!1,sx:e.clientX,sy:e.clientY,dirty:!1,before:this._geometrySnapshot()}}}_opPointerMove(e,t){if(!this._opDrag||this._opDrag.id!==t.id)return;if(Math.abs(e.clientX-this._opDrag.sx)+Math.abs(e.clientY-this._opDrag.sy)<=3)return;const i=this._spaceModel();if(!i)return;const s=this._svgPoint(e),n=this._curSpaceCfg,o=n?.openings?.find(e=>e.id===t.id);if(!o)return;if("partition"===o.host?.kind){const e=i.partitions.find(e=>e.id===o.host.id);if(!e)return;const t=e.b[0]-e.a[0],n=e.b[1]-e.a[1],a=Math.hypot(t,n);if(!(a>1e-9))return;const r=t/a,l=n/a;if(Math.abs((s[0]-e.a[0])*l-(s[1]-e.a[1])*r)>4*this._gridPitch)return;const c=o.length*Pv/2+Kp(e,this._cellCm,this._gridPitch);let h=(s[0]-e.a[0])*r+(s[1]-e.a[1])*l;if(h=Math.round(h/this._gridPitch)*this._gridPitch,h=Math.max(c,Math.min(a-c,h)),a<2*c-1e-9)return;const d=h/a,p=(e.a[0]+r*h)/Pv,u=(e.a[1]+l*h)/this._spaceH;let _=180*Math.atan2(n,t)/Math.PI;_>=90?_-=180:_<-90&&(_+=180);const m=o.host.t!==d||o.x!==p||o.y!==u||o.angle!==_;return this._opDrag.moved=!0,m&&(this._opDrag.dirty=!0),o.host={...o.host,t:d},o.x=p,o.y=u,o.angle=_,this._opMeasure=null,m&&this._cfgEpoch++,void this.requestUpdate()}const a=ui(s,i.rooms,4*this._gridPitch);if(!a)return;this._opDrag.moved=!0;const r=this._opRuler(a,o.length*Pv);this._opMeasure=r.measure;const l=r.x/Pv,c=r.y/this._spaceH,h=o.x!==l||o.y!==c||o.angle!==a.angle;if(h&&(this._opDrag.dirty=!0),o.x=l,o.y=c,o.angle=a.angle,Number(this._serverCfg?.model_version||0)>=9){const e=wg(o,n?.wall_segments||[]);e?o.host=e:delete o.host}h&&this._cfgEpoch++,this.requestUpdate()}_opRuler(e,t){const i=this._spaceModel()?.rooms||[],s=this._gridPitch/2;let n=e.x,o=e.y,a=_i([n,o],e.angle,t,i,s);if(a&&a.centered&&(n!==a.wallCenter[0]||o!==a.wallCenter[1]))[n,o]=a.wallCenter,a=_i([n,o],e.angle,t,i,s);else if(a){const[r,l]=a.wallA,[c,h]=a.wallB,d=c-r,p=h-l,u=Math.hypot(d,p);if(u>0){const c=this._gridPitch,h=Math.min(t/2,u/2);let _=Math.round(((n-r)*d+(o-l)*p)/u/c)*c;_=Math.max(h,Math.min(u-h,_)),n=r+_/u*d,o=l+_/u*p,a=_i([n,o],e.angle,t,i,s)||a}}if(!a)return{x:n,y:o,angle:e.angle,measure:null};const r="mi"===this.hass?.config?.unit_system?.length,l=(e,t)=>({x:t[0],y:t[1],text:li(e/this._gridPitch*this._cellCm,r)});return{x:n,y:o,angle:e.angle,measure:{labels:[l(a.sideA,a.midA),l(a.sideB,a.midB)],guide:a.centered?{x:a.wallCenter[0],y:a.wallCenter[1],angle:e.angle}:null}}}_opPointerUp(e,t){if(!this._opDrag||this._opDrag.id!==t.id)return;const i=this._opDrag,s=i.moved;this._opMeasure=null,s&&i.dirty&&this._commitPhysicalGeometry(this._t("history.move_opening"),i.before),s?window.setTimeout(()=>this._opDrag=null,0):this._opDrag=null}_opClick(e,t){"plan"===this._mode&&"resize"===this._tool||(e.stopPropagation(),this._opDrag?.moved||"plan"===this._mode&&this._editOpening(t))}_saveOpening(){const e=this._openingDialog,t=this._curSpaceCfg,i=this._spaceModel();if(!e||!t||!i)return;const s=this._geometrySnapshot(),n=this._spaceH,o=(t.openings||[]).find(t=>t.id===e.id),a={...o||{},id:e.id||"o"+Date.now().toString(36),type:e.type,x:e.x/Pv,y:e.y/n,angle:e.angle,length:o&&!e.lengthTouched?o.length:this._cmToUnits(Math.max(20,e.lengthCm))/Pv,...e.host?{host:{...e.host}}:{}};if("partition"===a.host?.kind){const e=Zp(o,a)?Xp(a,i.partitions,Pv,this._cellCm,this._gridPitch):Jp(a,i.partitions,Pv,this._cellCm,this._gridPitch);if(!e.resolved){const t=i.partitions.find(e=>e.id===a.host.id);if("does-not-fit-jamb"===e.reason&&t){const e=Kp(t,this._cellCm,this._gridPitch);this._showToast(this._t("opening.partition_jamb_margin",{distance:li(e/this._gridPitch*this._cellCm,this._imperial)}))}else this._showToast(this._t("opening.partition_orphan"));return}const s=(t.openings||[]).flatMap(e=>{if(!e.host||e.id===a.id)return[];const t=Jp(e,i.partitions,Pv,this._cellCm,this._gridPitch).resolved;return t?[t]:[]});if(function(e,t,i=1e-9){const s=e.length/(2*e.axis.length),n=e.t-s,o=e.t+s;return t.some(t=>{if(t.host.id!==e.host.id||t.opening.id===e.opening.id)return!1;const s=t.length/(2*t.axis.length);return Math.max(n,t.t-s)=9){const e=wg(a,t.wall_segments||[]);if(!e)return void this._showToast(this._t("toast.opening_no_wall"));a.host=e}else delete a.host;"passage"===e.type?(delete a.contact,delete a.lock,delete a.invert,delete a.flip_h,delete a.flip_v):(a.contact=e.contact||null,a.lock=("door"===e.type||"gate"===e.type)&&e.lock||null,a.invert=e.invert||void 0,a.flip_h="gate"!==e.type&&e.flipH||void 0,a.flip_v=e.flipV||void 0),t.openings=t.openings||[];const r=t.openings.findIndex(e=>e.id===a.id);r>=0?t.openings[r]=a:t.openings.push(a),this._commitPhysicalGeometry(this._t(e.id?"history.edit_opening":"history.add_opening"),s),this._openingDialog=null,this.requestUpdate()}_deleteOpening(){const e=this._openingDialog,t=this._curSpaceCfg;if(!e?.id||!t?.openings)return;const i=this._geometrySnapshot();t.openings=t.openings.filter(t=>t.id!==e.id),this._commitPhysicalGeometry(this._t("history.delete_opening"),i),this._openingDialog=null,this.requestUpdate()}_contactCandidates(){const e=[];for(const t of Object.keys(this.hass.states)){if(!this._openingEntityAvailable(t))continue;const i=t.split(".")[0];if("binary_sensor"!==i&&"cover"!==i)continue;const s=this.hass.states[t],n=["door","window","opening","garage_door","garage"].includes(s?.attributes?.device_class||"");("cover"!==i||n)&&e.push([t,s?.attributes?.friendly_name||t,n?0:1])}return e.sort((e,t)=>e[2]-t[2]||e[1].localeCompare(t[1])).map(([e,t])=>({value:e,label:t}))}_lockCandidates(){return Object.keys(this.hass.states).filter(e=>e.startsWith("lock.")&&this._openingEntityAvailable(e)).map(e=>({value:e,label:this.hass.states[e]?.attributes?.friendly_name||e})).sort((e,t)=>e.label.localeCompare(t.label))}_toggleOpeningEntityPicker(e){const t=this._openingDialog;if(!t)return;const i="contact"===e?!t.contactOpen:!t.lockOpen;this._openingDialog={...t,contactOpen:"contact"===e&&i,lockOpen:"lock"===e&&i}}_filterOpeningEntities(e,t){const i=this._openingDialog;i&&(this._openingDialog="contact"===e?{...i,contactFilter:t}:{...i,lockFilter:t})}_selectOpeningEntity(e,t){const i=this._openingDialog;i&&(this._openingDialog="contact"===e?{...i,contact:t,contactOpen:!1,contactFilter:""}:{...i,lock:t,lockOpen:!1,lockFilter:""})}_mergeClick(e){const t=this._spaceModel();if(!t)return;const i=t.rooms,s=[...i].reverse().find(t=>this._pointInRoom(e,t));if(!s?.id)return;const n=s.id;if(!this._mergeSel||this._mergeSel===n)return void(this._mergeSel=this._mergeSel===n?null:n);const o=i.find(e=>e.id===this._mergeSel),a=o?hi(o):null,r=hi(s),l=a&&r?function(e,t){if(!e||!t||e.length<3||t.length<3)return null;const i=si(Ii(e),Ii(t));if(1!==i.length)return null;if(1!==i[0].length)return null;const s=i[0][0].slice(0,-1).map(e=>[e[0],e[1]]);return s.length>=3?s:null}(a,r):null;if(!l)return this._showToast(this._t("toast.merge_not_adjacent")),void(this._mergeSel=null);this._mergeDialog={aId:this._mergeSel,bId:n,poly:l,pick:"a"},this._mergeSel=null}_commitMerge(){const e=this._mergeDialog,t=this._curSpaceCfg;if(!e||!t||!this._spaceModel())return;const i=this._geometrySnapshot(),s=this._spaceH,n="a"===e.pick?e.aId:e.bId,o="a"===e.pick?e.bId:e.aId,a=t.rooms.find(e=>e.id===n);if(!a)return void(this._mergeDialog=null);a.poly=e.poly.map(e=>[e[0]/Pv,e[1]/s]),delete a.x,delete a.y,delete a.w,delete a.h,t.rooms=t.rooms.filter(e=>e.id!==o);const r=this._commitPhysicalGeometry(this._t("history.merge_rooms"),i);this._mergeDialog=null,this._regSignature="",this._maybeRebuildDevices(),r&&this._showToast(this._t("toast.rooms_merged",{name:a.name||""}))}_splitClick(e){const t=this._spaceModel();if(!t)return;const i=t.rooms;if(!this._splitSel){const t=[...i].reverse().find(t=>this._pointInRoom(e,t));if(!t?.id)return;return void(this._splitSel={roomId:t.id,pts:[]})}const s=i.find(e=>e.id===this._splitSel.roomId),n=s?hi(s):null;if(!s||!n)return void(this._splitSel=null);const o=.02*this._gridPitch,a=6*this._gridPitch,r=function(e,t){if(!t||t.length<2)return null;let i=null,s=1/0;for(let n=0;n=n)continue;n=_;const m=Math.sqrt(p),g=(i>0?Math.max(0,Math.min(m,Math.round(u*m/i)*i)):u*m)/m;s=[a+g*h,r+g*d]}return s}(r,n,this._gridPitch)||r,c=r&&l&&Math.hypot(r[0]-e[0],r[1]-e[1])<=a?l:null,h=!!c&&yi(c,n,o),d=this._splitSel.pts;if(!d.length)return h?void(this._splitSel={...this._splitSel,pts:[c]}):void this._showToast(this._t("toast.split_pick_wall"));if(!h){const t=this._snap(e);return wi(t,n,o)?void(this._splitSel={...this._splitSel,pts:[...d,t]}):void this._showToast(this._t("toast.split_pick_inside"))}const p=zi(n,[...d,c],o);if(!p)return void this._showToast(this._t("toast.split_bad_cut"));this._resetRoomDialogFields();const[u,_]=p,m=Ti(u)>=Ti(_)?u:_,g=m===u?_:u;this._pendingSplit={roomId:s.id,mainPoly:m,newPoly:g},this._cursorPt=null,this._nameSel="",this._areaSel="",this._roomDialog=!0}get _contourClosed(){return this._path.length>=4&&this._samePt(this._path[0],this._path[this._path.length-1])&&(null!=this._closingWallCm||!this._activeDraftId)}_markupMove(e){if(!this._markup)return;if("column"===this._tool)return void(this._cursorPt=this._snap(this._svgPoint(e)));if("opening"===this._tool||"wallthick"===this._tool)return void(this._cursorPt=this._svgPoint(e));const t="draw"===this._tool&&!this._contourClosed,i="split"===this._tool&&!!this._splitSel?.pts?.length;if(!t&&!i)return;const s=this._svgPoint(e);if(t){const t=this._resolvePlanDrawPoint(s,e.shiftKey);return this._planSnapHover={contextKey:t.contextKey,candidate:t.candidate,conflicts:t.conflicts},this._syncPlanSnapConflictMarkers(t.conflicts),this._path.length?void(this._cursorPt=t.point):void this._syncPlanSnapActiveMarker(t.candidate)}this._cursorPt=this._snap(s)}get _openingPreview(){const e=this._openingPreset;if("opening"!==this._tool||!e||!this._cursorPt)return null;const t=this._cursorPt,i=this._openingHoverCandidate;if(i&&Gf(i,[t[0],t[1]],e.revision,this._cfgEpoch))return i;if(this._openingAt(t))return this._openingHoverCandidate=null,null;const s=this._resolveOpeningPlacement(t);return this._openingHoverCandidate=s,s}get _opMeasureView(){return this._opMeasure||this._openingPreview?.measure||null}_saveRoom(){(this._areaSel||this._nameSel.trim())&&(this._wallFaceBatch?this._decideWallFace(!0):this._commitRoom())}_decideWallFace(e){const t=this._wallFaceBatch;if(!t)return;const i=t.candidates[t.index];if(!i)return;if(!e&&(i.existing||i.repair)&&1===t.candidates.length)return this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",void this.requestUpdate();const s=e?{candidate:i,create:!0,name:this._nameSel.trim(),area:this._areaSel||null,settings:this._roomSettingsFromDialog()?JSON.parse(JSON.stringify(this._roomSettingsFromDialog())):null}:{candidate:i,create:!1},n=[...t.decisions,s],o=t.index+1;if(o"number"==typeof e&&Number.isFinite(e)&&e>=0?e:null,n=.02*this._gridPitch,o=this._spaceModel();if(!o)return ul;for(const t of this._planSnapGeometrySnapshot().value.segments){if("room"===t.sourceKind||Hs(e,[t.a[0],t.a[1],t.b[0],t.b[1]])>n)continue;if("partition"===t.sourceKind)return s(o.partitions.find(e=>e.id===t.sourceId)?.cm)??ul;const i=t.sourceId.lastIndexOf(":"),a=i>=0?t.sourceId.slice(0,i):t.sourceId,r=i>=0?Number(t.sourceId.slice(i+1)):-1;return s(o.room_drafts.find(e=>e.id===a)?.segments[r]?.cm)??ul}const a=ku(Math.max(0,t.length-1),i,this._drawWallCm,ul);for(let i=0;i+1[...e]);if(!t?.sourceKey.startsWith("active:"))return i;const s=/:(\d+)$/.exec(t.sourceKey),n=s?Number(s[1])+("b"===t.endpoint?1:0):-1;return n>=0&&nt.key===e.sourceKey),o=s.find(t=>t.key===e.targetSourceKey);if(!n||!o)return!1;const a="a"===e.endpoint?n.a:n.b;return!(Math.hypot(a[0]-e.from[0],a[1]-e.from[1])>i)&&(!(Hs(e.to,[o.a[0],o.a[1],o.b[0],o.b[1]])>i)&&!function(e,t){if(!e.sourceKey.startsWith("static:partition|"))return!1;const i=e.sourceKey.slice(17).split("|")[0];return!!i&&t.some(e=>"partition"===e.host?.kind&&e.host.id===i)}(e,this._curSpaceCfg?.openings||[]))}_applyWallRepair(e,t){const i=this._curSpaceCfg;if(!i||!this._validateWallRepair(e,t.activePath))return!1;const s=t=>{t[0]=e.to[0]/Pv,t[1]=e.to[1]/Pv};if(e.sourceKey.startsWith("active:")){const n=/:(\d+)$/.exec(e.sourceKey),o=n?Number(n[1])+("b"===e.endpoint?1:0):-1;if(o<0||o>=t.activePath.length)return!1;t.activePath[o]=[...e.to];const a=(i.room_drafts||[]).find(e=>e.id===t.activeDraftId);return a?.points?.[o]&&s(a.points[o]),!0}if(!e.sourceKey.startsWith("static:"))return!1;const[n,o]=e.sourceKey.slice(7).split("|");if("partition"===n){const t=(i.partitions||[]).find(e=>e.id===o);if(!t)return!1;const n=[t.a[0]*Pv,t.a[1]*Pv],a=[t.b[0]*Pv,t.b[1]*Pv],r=Math.hypot(n[0]-e.from[0],n[1]-e.from[1])<=2e-4*this._gridPitch?t.a:Math.hypot(a[0]-e.from[0],a[1]-e.from[1])<=2e-4*this._gridPitch?t.b:null;return!!r&&(s(r),!0)}if("draft"===n){const t=o.lastIndexOf(":"),n=t>=0?o.slice(0,t):"",a=t>=0?Number(o.slice(t+1)):-1,r=(i.room_drafts||[]).find(e=>e.id===n);if(!r?.points?.[a]||!r?.points?.[a+1])return!1;const l=[a,a+1].find(t=>Math.hypot(r.points[t][0]*Pv-e.from[0],r.points[t][1]*Pv-e.from[1])<=2e-4*this._gridPitch);return null!=l&&(s(r.points[l]),!0)}return!1}_applyWallFaceBatch(){const e=this._wallFaceBatch,t=this._curSpaceCfg,i=this._spaceModel();if(!e||!t||!i)return;const s=(e,t)=>{this._showToast(this._t(e,t)),this._roomDialogCancel()},n=e.decisions.filter(e=>e.create),o=n.map(e=>e.candidate.ring),a=i.rooms;for(let e=0;ei.id!==t&&!!hi(i)&&Di(o[e],hi(i)));if(i)return void s("toast.room_overlap",{name:i.name||""})}if((t.rooms||[]).length+n.length>400)return void s("toast.physical_limit");if(n.some(e=>e.candidate.split&&!t.rooms.some(t=>t.id===e.candidate.split.roomId)))return void s("toast.contour_cannot_close");const r=n.map(e=>e.candidate.repair).filter(e=>!!e);if(r.length>1||r[0]&&!this._validateWallRepair(r[0],e.activePath))return void s("toast.wall_repair_changed");const l=this._activePathWithRepair(e.activePath,r[0]),c=2e-4*this._gridPitch,h=new Map;for(let t=0;te.candidate.atomKeys)),t=n.some(e=>e.candidate.consumeAllActive);for(const i of Wu(this._wallGraphSources(l),c)){const s=i.sourceKeys.find(e=>h.has(e));!s||t||e.has(i.key)||d.push({a:i.a,b:i.b,cm:h.get(s)})}}else d.push(...xu(l,ku(l.length-1,e.activeCms,this._drawWallCm,ul)));if((t.partitions||[]).length+d.length>Av)return void s("toast.physical_limit");const p=n.map(e=>e.candidate.ring.map(()=>"")),u=e.activeDraftId?(t.room_drafts||[]).find(t=>t.id===e.activeDraftId):null,_=this._draftSegmentsForPath(e.activePath,u,e.activeCms),m=(e,t)=>{const i=`${e[0].toFixed(9)},${e[1].toFixed(9)}`,s=`${t[0].toFixed(9)},${t[1].toFixed(9)}`;return i<=s?`${i}|${s}`:`${s}|${i}`};for(let t=0;t<_.length;t++){const i=_[t]?.id;if(!i)continue;const s=e.activePath[t],o=e.activePath[t+1],a=[s[0],s[1],o[0],o[1]],r=[];n.forEach((e,t)=>e.candidate.ring.forEach((i,s)=>{const n=e.candidate.ring[(s+1)%e.candidate.ring.length];Hs(i,a)<=c&&Hs(n,a)<=c&&r.push({kind:"room",owner:t,edge:s,a:i,b:n})})),d.forEach((e,t)=>{Hs(e.a,a)<=c&&Hs(e.b,a)<=c&&r.push({kind:"partition",owner:t,edge:0,a:e.a,b:e.b})});const l=[(s[0]+o[0])/2,(s[1]+o[1])/2];r.sort((e,t)=>{const i=[e.a[0],e.a[1],e.b[0],e.b[1]],n=[t.a[0],t.a[1],t.b[0],t.b[1]];return(Hs(l,i)<=c?0:1)-(Hs(l,n)<=c?0:1)||(Hs(s,i)<=c?0:1)-(Hs(s,n)<=c?0:1)||m(e.a,e.b).localeCompare(m(t.a,t.b))});const h=r[0];if(!h)continue;const u=m(h.a,h.b);for(const e of r)m(e.a,e.b)===u&&("room"===e.kind?p[e.owner][e.edge]=i:d[e.owner].id=i)}const g=this._geometrySnapshot();if(r[0]&&!this._applyWallRepair(r[0],e))return void s("toast.wall_repair_changed");const f=n.some(e=>!!e.candidate.split),v=f?fc(i.rooms,t.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Pv):null,b=f&&Array.isArray(t.walls)?t.walls:null;for(const e of n){const i=e.candidate.split;if(!i)continue;const n=t.rooms.find(e=>e.id===i.roomId);if(!n)return void s("toast.contour_cannot_close");n.poly=i.mainPoly.map(e=>[e[0]/Pv,e[1]/this._spaceH]),delete n.x,delete n.y,delete n.w,delete n.h}const y=Date.now().toString(36),w=[];if(n.forEach((e,i)=>{const s=e.area?this.hass.areas[e.area]?.name:"",n={id:`r${y}-${i}`,name:e.name||s||this._t("room.default_name"),area:e.area||null,poly:e.candidate.ring.map(e=>[e[0]/Pv,e[1]/this._spaceH]),...p[i].some(Boolean)?{wall_ids:p[i]}:{},...e.settings?{settings:JSON.parse(JSON.stringify(e.settings))}:{}};t.rooms.push(n),w.push({room:n,decision:e})}),e.activeDraftId&&Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t.id!==e.activeDraftId),t.room_drafts.length||delete t.room_drafts),d.length&&(t.partitions||=[],d.forEach((e,i)=>t.partitions.push({id:e.id||`partition-${y}-${i}`,a:[e.a[0]/Pv,e.a[1]/Pv],b:[e.b[0]/Pv,e.b[1]/Pv],cm:e.cm}))),f){const e=this._normalizeWalls(v,this._openCuts());e.length?t.walls=e:b?.length?t.walls=b:delete t.walls}if(w.length){this._cfgEpoch++;const i=this._openCuts(),s=this._spaceModel();if(!s)return;let n=t.walls;for(const{room:t,decision:o}of w){const a=o.candidate.ring,r=this._wallSourceCmAt(a[0],e.activePath,e.activeCms);n=jl(n,s.rooms,t.id,r,this._wallKeyPitch,i,Pv);for(const o of gc(s.rooms,n,i,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv)){if(o.roomId!==t.id||"outer"!==o.kind)continue;const i=[(o.a[0]+o.b[0])/2,(o.a[1]+o.b[1])/2];n=Ll(n,o.a,o.b,this._wallSourceCmAt(i,e.activePath,e.activeCms),this._wallKeyPitch,Pv)}}const o=this._normalizeWalls(n,i);o.length?t.walls=o:delete t.walls}if(!this._commitPhysicalGeometry(this._t("history.wall_face_batch"),g))return;delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices();const k=new Set(n.map(e=>e.area).filter(e=>!!e));if(k.size){const e={...this._layout};for(const t of this._devices){if(!k.has(t.area||"")||t.space!==this._space)continue;if(this._layout[t.id])continue;const i=this._defPos[t.id];i&&(e[t.id]={s:this._space,x:i.x/Pv,y:i.y/Pv},this._dirtyPos.add(t.id))}this._layout=e,this._persistLayout()}this._showToast(this._t(n.length?"toast.wall_rooms_saved":"toast.wall_chain_saved",{n:n.length}))}_commitRoom(){const e=this._curSpaceCfg,t=this._spaceModel();if(!e||!t)return;const i=this._geometrySnapshot(),s=this._spaceH,n=!!this._pendingSplit,o=n?fc(t.rooms,e.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Pv):null,a=n&&Array.isArray(e.walls)?e.walls:null;let r;if(this._pendingSplit){const t=e.rooms.find(e=>e.id===this._pendingSplit.roomId);if(!t)return this._pendingSplit=null,this._splitSel=null,void(this._roomDialog=!1);t.poly=this._pendingSplit.mainPoly.map(e=>[e[0]/Pv,e[1]/s]),delete t.x,delete t.y,delete t.w,delete t.h,r=this._pendingSplit.newPoly}else{if(!this._contourClosed)return;r=this._path.slice(0,-1)}const l=this._areaSel?this.hass.areas[this._areaSel]?.name:"",c={id:"r"+Date.now().toString(36),name:this._nameSel||l||this._t("room.default_name"),area:this._areaSel||null,poly:r.map(e=>[e[0]/Pv,e[1]/s]),...this._roomSettingsFromDialog()?{settings:this._roomSettingsFromDialog()}:{}};if(!n&&this._activeDraftId){const t=Array.isArray(e.room_drafts)?e.room_drafts.find(e=>e.id===this._activeDraftId):null,i=ku(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,ul),s=this._draftSegmentsForPath(this._path,t,i);s.length===r.length&&s.every(e=>!!e.id)&&(c.wall_ids=s.map(e=>e.id))}if(e.rooms.push(c),!n&&this._activeDraftId&&Array.isArray(e.room_drafts)&&(e.room_drafts=e.room_drafts.filter(e=>e.id!==this._activeDraftId),e.room_drafts.length||delete e.room_drafts),n){const t=this._normalizeWalls(o,this._openCuts());t.length?e.walls=t:a?.length?e.walls=a:delete e.walls}if(!n){const t=ku(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,ul),i=t[0];if(null!=i){this._cfgEpoch++;const s=this._openCuts(),n=this._spaceModel();if(!n)return;let o=jl(e.walls,n.rooms,c.id,i,this._wallKeyPitch,s,Pv);for(const e of gc(n.rooms,o,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv)){if(e.roomId!==c.id||"outer"!==e.kind)continue;const i=[(e.a[0]+e.b[0])/2,(e.a[1]+e.b[1])/2],s=r.findIndex((e,t)=>{const s=r[(t+1)%r.length];return Hs(i,[e[0],e[1],s[0],s[1]])<=.02*this._gridPitch});s>=0&&(o=Ll(o,e.a,e.b,t[s],this._wallKeyPitch,Pv))}o=this._normalizeWalls(o,s),o.length?e.walls=o:delete e.walls}}const h=this._commitPhysicalGeometry(this._t(n?"history.split_room":"history.add_room"),i);this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._pendingSplit=null,this._splitSel=null;const d=this._areaSel;if(this._areaSel="",this._nameSel="",this._roomDialog=!1,this._regSignature="",this._maybeRebuildDevices(),!h)return;let p=0;if(d){const e=Pv,t={...this._layout};for(const i of this._devices){if(i.area!==d||i.space!==this._space)continue;if(p++,this._layout[i.id])continue;const s=this._defPos[i.id];s&&(t[i.id]={s:this._space,x:s.x/Pv,y:s.y/e},this._dirtyPos.add(i.id))}this._layout=t,this._persistLayout()}const u=this._model.find(e=>e.id===this._space)?.rooms.length||0;this._showToast(d?this._t("toast.room_saved",{n:u,added:p}):this._t("toast.room_saved_no_area",{n:u}))}_cancelPath(){this._wallRepairDiagnostic=null,this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),this._roomDialog=!1,this._pendingSplit=null,this._wallFaceBatch=null,this._splitSel=null,this._mergeSel=null,this._mergeDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._clearOpeningPlacement(!0)}_resumeLastDraft(){const e=this._resumeDraftBySpace[this._space];if(!e)return;const t=this._spaceModel()?.room_drafts.find(t=>t.id===e);t?(this._activeDraftId=e,this._path=t.points.map(e=>[...e]),this._draftSegmentCms=this._adoptDraftCms(this._path,t.segments.map(e=>e.cm),t.id),this._clearPlanSnapHover()):delete this._resumeDraftBySpace[this._space]}_roomDialogCancel(){if(this._roomDialog=!1,this._roomEditId)return this._roomEditId=null,this._nameSel="",void(this._areaSel="");if(this._wallFaceBatch){const e=this._wallFaceBatch;return this._wallFaceBatch=null,this._path=e.activePath.map(e=>[...e]),this._draftSegmentCms=[...e.activeCms],this._activeDraftId=e.activeDraftId,this._nameSel="",this._areaSel="",void this.requestUpdate()}if(this._pendingSplit)return this._pendingSplit=null,void(this._splitSel=null);this._undoPoint()}get _freeAreas(){const e=new Set;for(const t of this._serverCfg?.spaces||[])for(const i of t.rooms||[])i.area&&e.add(i.area);for(const t of this._wallFaceBatch?.decisions||[])t.create&&t.area&&e.add(t.area);return Object.values(this.hass?.areas||{}).filter(t=>!e.has(t.area_id)).sort((e,t)=>(e.name||"").localeCompare(t.name||""))}_openDeviceInbox(){this._deviceInboxReturn=null,this._deviceInbox=this._deviceInbox||{tab:"on_plan",search:"",showEntities:!1,onlyNew:!1,limit:100}}_closeMarkerDialog(){if(this._markerDialog=null,this._deviceInboxReturn){const e={...this._deviceInboxReturn};this._deviceInbox=e,this._deviceInboxReturn=null,e.anchor&&this.updateComplete.then(()=>requestAnimationFrame(()=>{const t=`.device-inbox-row[data-binding="${CSS.escape(e.anchor)}"]`;this.renderRoot.querySelector(t)?.scrollIntoView({block:"nearest"})}))}}_deviceInboxCandidates(e){return gp({hass:this._planHass,devices:this._devices,markers:this._markers,showEntities:e,labels:{device:this._t("marker.sub_device"),z2mGroup:this._t("marker.sub_z2m_group"),group:this._t("marker.sub_group"),helper:this._t("marker.sub_helper"),entity:this._t("marker.sub_entity")}})}_deviceInboxRows(){const e=this._deviceInbox||this._deviceInboxReturn,t=!!e?.showEntities,i=[this._haRegistry.revision,this._cfgRev,this._cfgEpoch,this._regSignature,this._newSyncKey,t?1:0,this._showAll?1:0,ra(this.hass,this._config?.language)].join("|");if(this._deviceInboxMemo?.key===i)return this._deviceInboxMemo.rows;const s=this._deviceInboxCandidates(t),n=new Set(s.map(e=>e.value));for(const e of this._markers)e.binding&&"virtual"!==e.binding&&n.add(e.binding);for(const e of this._devices)e.bindingKind&&"virtual"!==e.bindingKind&&e.bindingRef&&n.add(`${e.bindingKind}:${e.bindingRef}`);const o=new Map;for(const e of n)o.set(e,this._bindingStatus(e));const a={};for(const[e,t]of Object.entries(this.hass?.areas||{}))a[e]=t?.name||e;const r=Object.fromEntries(this._model.map(e=>[e.id,e.title])),l=Object.fromEntries(Object.entries(this._areaToSpace).map(([e,t])=>[e,t.space])),c={},h=new Map;for(const[e,t]of Object.entries(this._fullRegistryHass.entities||{})){const i=String(t?.platform||"").trim();if(i&&(c[`entity:${e}`]=i),i&&t?.device_id){const e=h.get(t.device_id)||new Set;e.add(i),h.set(t.device_id,e)}}for(const[e,t]of h)c[`device:${e}`]=[...t].sort().join(", ");const d={};for(const[e,t]of Object.entries(this._fullRegistryHass.devices||{})){const i=`device:${e}`,s=h.get(e)||new Set,n=Array.isArray(t?.identifiers?.[0])?String(t.identifiers[0][0]||""):"",o=[n,...s].some(e=>this._excluded.has(e));"service"===t?.entry_type?d[i]="service_entry":o?d[i]="excluded_integration":"Group"===t?.model?d[i]="grouped_light":/scene/i.test(t?.model||"")?d[i]="excluded_domain":(/bridge/i.test(`${t?.model||""}${t?.name||""}`)||"myheat"===n&&t?.via_device_id)&&(d[i]="represented_by_parent")}const p=function(e){const{devices:t,markers:i,candidates:s,statuses:n,newDeviceIds:o,showHiddenOnPlan:a,areaNames:r={},spaceNames:l={},spaceByArea:c={},integrationByBinding:h={},reasonByBinding:d={}}=e,p=new Map;for(const e of t)!e.virtual&&e.bindingKind&&"virtual"!==e.bindingKind&&e.bindingRef&&p.set(`${e.bindingKind}:${e.bindingRef}`,e);const u=new Map,_=new Map;for(const e of i)e?.binding&&"virtual"!==e.binding&&(e.removed?_.set(e.binding,e):u.set(e.binding,e));const m=new Map(s.map(e=>[e.value,e])),g=new Set([...p.keys(),...u.keys(),...m.keys(),...[..._.keys()].filter(e=>m.has(e))]),f=[];for(const e of g){const t=p.get(e),i=u.get(e),s=i?void 0:_.get(e),g=m.get(e);let v;if(s&&g)v="readd";else if(!0===i?.hidden)v="hidden";else if(t||i)v="on_plan";else{if(!g)continue;v="available"}const b=t?.bindingStatus||n.get(e)||fp,y=i||s,w=vp(e),k=t?.area||g?.areaId||y?.area||"",x=t?.space||y?.space||c[k]||"",$=t?.name||y?.name||g?.label||e,S=t?.model||y?.model||g?.model||"",M=!!g?.parentDeviceId&&p.has(`device:${g.parentDeviceId}`),C="readd"===v?"removed":"hidden"===v?i&&bp(i)?d[e]||"automatic_hidden":"manual_hidden":"on_plan"===v?i?"visible_explicit":"visible_auto":d[e]||(M?"represented_by_parent":k&&x?"available":"no_bound_room"),D=!!t&&(!t.hidden||a),P="active"===b.kind,T=D&&(P||"ha_disabled"===b.kind&&a),I="device"===w||"entity"===w,R=[$,S,h[e],r[k],l[x],e,g?.sub].filter(Boolean).join(" ").toLocaleLowerCase();f.push({key:e,binding:e,category:v,status:b,reason:C,deviceId:t?.id,markerId:y?.id,name:$,icon:t?.icon||y?.icon||("entity"===w?"mdi:code-braces":"mdi:devices"),model:S,integration:h[e]||"",areaId:k,areaName:r[k]||"",spaceId:x,spaceName:l[x]||"",kind:w,isNew:!!t&&o.has(t.id),searchText:R,canFind:T,canEdit:!!t||!!i,canHide:"on_plan"===v&&P,canShow:"hidden"===v&&P,canAdd:("available"===v||"readd"===v)&&P,canOpenHa:I})}const v=e=>"active"===e.status.kind?1:0;return f.sort((e,t)=>e.category.localeCompare(t.category)||Number(t.isNew)-Number(e.isNew)||v(e)-v(t)||e.name.localeCompare(t.name)||e.binding.localeCompare(t.binding))}({devices:this._devices,markers:this._markers,candidates:s,statuses:o,newDeviceIds:this._newIds,showHiddenOnPlan:this._showAll,areaNames:a,spaceNames:r,spaceByArea:l,integrationByBinding:c,reasonByBinding:d});return this._deviceInboxMemo={key:i,rows:p},p}_deviceForInboxRow(e){const t=e.deviceId?this._devices.find(t=>t.id===e.deviceId):null;if(t)return t;const i=e.markerId?this._markers.find(t=>t.id===e.markerId):null;return!i||i.removed?null:{id:i.id,name:e.name,model:e.model,area:e.areaId,space:e.spaceId||this._space,hidden:!0===i.hidden||"ha_disabled"===e.status.kind,userHidden:!0===i.hidden,bindingStatus:e.status,icon:e.icon,entities:"active"===e.status.kind?e.status.enabledEntityIds:[],allEntities:e.status.allEntityIds,primary:"active"===e.status.kind?e.status.enabledEntityIds[0]:void 0,marker:i,bindingKind:e.kind,bindingRef:e.binding.slice(e.binding.indexOf(":")+1),pdfs:i.pdfs||[]}}_openInboxMarker(e,t=!1){const i=this._deviceInbox;if(i){if(this._deviceInboxReturn={...i,anchor:e.key},this._deviceInbox=null,!t){const t=this._deviceForInboxRow(e);return void(t?this._openMarkerDialog(t):this._closeMarkerDialog())}this._openMarkerDialog(),this._markerDialog?this._markerDialog={...this._markerDialog,bindingMode:"ha",binding:e.binding,bindingOpen:!1,showEntities:"entity"===e.kind,name:""}:this._closeMarkerDialog()}}async _setInboxHidden(e,t){const i=this._deviceInbox,s=this._serverCfg;if(!i||!s||i.busy||"active"!==e.status.kind)return;const n=s.markers||[],o=n.find(t=>!t.removed&&t.binding===e.binding);if(!t&&!o)return;const a=o?.id||Fi(e.binding,e.markerId,()=>`m_${Date.now().toString(36)}`),r=o?{...o,hidden:t}:{id:a,binding:e.binding,hidden:!0};s.markers=[...n.filter(t=>t.id!==a&&(t.binding!==e.binding||!0===t.removed)),r],this._deviceInbox={...i,busy:e.key,anchor:e.key};try{await this._saveConfigNow(),this._regSignature="",this._deviceInboxMemo=null,this._maybeRebuildDevices(),this._deviceInbox&&(this._deviceInbox={...this._deviceInbox,busy:void 0}),this._showToast(this._t("device_inbox.saved"))}catch(e){this._serverCfg===s&&(s.markers=n),this._deviceInbox&&(this._deviceInbox={...this._deviceInbox,busy:void 0}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}_findInboxDevice(e){if(!e.canFind)return;const t=this._deviceForInboxRow(e);if(!t)return;if(this._deviceInbox=null,t.space&&t.space!==this._space){if(!this._commitSpace(t.space))return;this._restoreZoom()}const i=()=>{const e=this._devices.find(e=>e.id===t.id)||t,i=this._pos(e);this._applyView(this._zoom,i.x,i.y),this._selId=e.id,this.requestUpdate(),window.setTimeout(()=>{this._selId===e.id&&(this._selId=null,this.requestUpdate())},1500)};requestAnimationFrame(()=>requestAnimationFrame(i))}_deviceInboxTabKey(e){if("ArrowLeft"!==e.key&&"ArrowRight"!==e.key)return;const t=this._deviceInbox;if(!t)return;const i=["on_plan","available","hidden","readd"],s="ArrowRight"===e.key?1:-1,n=(i.indexOf(t.tab)+s+i.length)%i.length;this._deviceInbox={...t,tab:i[n],limit:100,onlyNew:!1},e.preventDefault()}_openMarkerDialog(e){if(this._vacAllCamerasFor=null,this._vacAllCameraCache=null,e&&this._ackNewDevice(e.id),this._norm)if(e){const t=e.marker,i=Object.prototype.hasOwnProperty.call(t||{},"is_light"),s=Object.prototype.hasOwnProperty.call(t||{},"light_entity"),n=Object.prototype.hasOwnProperty.call(t||{},"glow_color"),o=Object.prototype.hasOwnProperty.call(t||{},"value_badge"),a=Object.prototype.hasOwnProperty.call(t||{},"tap_action"),r=Object.prototype.hasOwnProperty.call(t||{},"toggle_entity"),l=ks(t?.glow_color),c=this._devicePresentation(e,!0).valueBadge,h=qo(this._planHass,e,this._devices),d=Wo(this._planHass,e,h);this._markerDialog={devId:e.id,name:e.name,binding:"virtual"===e.bindingKind?"virtual":e.bindingKind+":"+e.bindingRef,bindingMode:"virtual"===e.bindingKind?"virtual":"ha",bindingOpen:!1,showEntities:"entity"===e.bindingKind&&!!this._fullRegistryHass.entities[e.bindingRef||""]?.device_id,bindingFilter:"",icon:e.marker?.icon||"",autoIcon:e.icon||"",display:Bi(e.marker?.display),rippleColor:Ie(e.marker?.ripple_color,""),rippleSize:Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,size:Number(e.marker?.size)>0?Number(e.marker.size):1,angle:Number(e.marker?.angle)||0,tapAction:Op(e.marker?.tap_action,e.primary?.split(".")[0]),tapActionTouched:!1,originalHasTapAction:a,originalTapAction:e.marker?.tap_action,tapHintAnnouncement:"",toggleEntity:t?.toggle_entity||"",toggleEntityTouched:!1,originalHasToggleEntity:r,originalToggleEntity:t?.toggle_entity,tapTarget:e.marker?.tap_target||"",tapConfirm:!0===e.marker?.tap_confirm,runFilter:"",controls:Zn(e.marker?.binding,e.marker?.controls,e.entities),controlsFilter:"",lightRole:!0===t?.is_light?"always":!1===t?.is_light?"never":"auto",lightRoleTouched:!1,originalHasIsLight:i,originalIsLight:t?.is_light,lightEntity:t?.light_entity||"",lightEntityTouched:!1,originalHasLightEntity:s,originalLightEntity:t?.light_entity,glowMode:null!=l?.bri?"fixed":l?"color":"auto",glowColor:l?.c||this._fillColors.glow_light.c,glowBrightness:Math.max(1,Math.round(100*(l?.bri??1))),glowColorDrafted:!!l,glowBrightnessDrafted:null!=l?.bri,glowTouched:!1,originalHasGlowColor:n&&(!!l||null===t?.glow_color),originalGlowColor:l||(null===t?.glow_color?null:void 0),valueBadgeEnabled:o?!0===t?.value_badge?.enabled:!!c,valueBadgeSource:t?.value_badge?.source||c?.source||d,valueBadgePosition:t?.value_badge?.position||c?.position||"right",valueBadgeTouched:!1,originalHasValueBadge:o,originalValueBadge:t?.value_badge,useClimateTemp:!0===e.marker?.use_climate_temp,glowRadius:Number(e.marker?.glow_radius_cm)>0?String(this._imperial?Math.round(Number(e.marker.glow_radius_cm)/30.48*10)/10:Math.round(Number(e.marker.glow_radius_cm))/100):"",model:e.model||"",link:e.link||"",description:e.description||"",pdfs:[...e.pdfs||[]],room:e.marker?.room_id?e.space+"#@"+e.marker.room_id:e.space&&e.area?e.space+"#"+e.area:"",hideFromPlan:!0===e.marker?.hidden,busy:!1}}else this._markerDialog={name:"",binding:"virtual",bindingMode:"virtual",bindingOpen:!1,showEntities:!1,bindingFilter:"",icon:"",autoIcon:"",display:"badge",rippleColor:"",rippleSize:1.5,size:1,angle:0,tapAction:"info",tapActionTouched:!1,originalHasTapAction:!1,originalTapAction:void 0,tapHintAnnouncement:"",toggleEntity:"",toggleEntityTouched:!1,originalHasToggleEntity:!1,originalToggleEntity:void 0,tapTarget:"",tapConfirm:!1,runFilter:"",controls:[],controlsFilter:"",lightRole:"auto",lightRoleTouched:!1,originalHasIsLight:!1,originalIsLight:void 0,lightEntity:"",lightEntityTouched:!1,originalHasLightEntity:!1,originalLightEntity:void 0,glowMode:"auto",glowColor:this._fillColors.glow_light.c,glowBrightness:100,glowColorDrafted:!1,glowBrightnessDrafted:!1,glowTouched:!1,originalHasGlowColor:!1,originalGlowColor:void 0,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgePosition:"right",valueBadgeTouched:!1,originalHasValueBadge:!1,originalValueBadge:void 0,useClimateTemp:!1,glowRadius:"",model:"",link:"",description:"",pdfs:[],room:"",hideFromPlan:!1,busy:!1,uploadId:"up_"+Date.now().toString(36)+Math.random().toString(36).slice(2,6)};else this._showToast(this._t("toast.marker_needs_server"))}_runCandidates(){const e=[];for(const t of Gi)for(const[i,s]of Object.entries(this.hass.states))i.startsWith(t+".")&&this._planEntityAvailable(i)&&e.push({value:i,label:s?.attributes?.friendly_name||i,sub:this._t("run."+t)});return e.sort((e,t)=>e.sub.localeCompare(t.sub)||e.label.localeCompare(t.label))}_bindingCandidates(){const e=gp({hass:this._planHass,devices:this._devices,markers:this._markers,showEntities:!!this._markerDialog?.showEntities,currentBinding:this._markerDialog?.binding,currentDeviceId:this._markerDialog?.devId,labels:{device:this._t("marker.sub_device"),z2mGroup:this._t("marker.sub_z2m_group"),group:this._t("marker.sub_group"),helper:this._t("marker.sub_helper"),entity:this._t("marker.sub_entity")}}),t=(this._markerDialog?.bindingFilter||"").toLowerCase().trim(),i=t?e.filter(e=>(e.label+" "+e.sub+" "+e.value).toLowerCase().includes(t)):e;return i.sort((e,t)=>e.label.localeCompare(t.label)),i.slice(0,200)}_physicalBodiesR(e=this._spaceModel()){if(!e)return[];const t=`${e.id}|${this._cfgEpoch}|${this._cellCm}|${this._gridPitch}`;if(this._physicalBodiesCache?.key===t)return this._physicalBodiesCache.all;const i=ch(e,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(e));return this._physicalBodiesCache={key:t,...i},i.all}_rawPhysicalBodiesR(e=this._spaceModel()){if(!e)return[];this._physicalBodiesR(e);const t=this._physicalBodiesCache;return t?[...t.drafts,...t.partitions,...t.columns]:[]}_cleanFloor(e,t,i=this._spaceModel()){if(!i)return{floor:t,geom:null,path:"",area:mh([[[...t,t[0]]]])};const s=e.id||`#${i.rooms.indexOf(e)}`,n=`${i.id}|${this._cfgEpoch}|${s}`;if(!this._resize.preview){const e=gv(this._cleanFloorCache,n);if(e.hit)return e.value}const o=t.map(e=>e[0]),a=t.map(e=>e[1]),r=[Math.min(...o),Math.min(...a),Math.max(...o),Math.max(...a)],l=this._physicalBodiesR(i).filter(e=>{const t=e.map(e=>e[0]),i=e.map(e=>e[1]);return Math.max(...t)>=r[0]&&Math.min(...t)<=r[2]&&Math.max(...i)>=r[1]&&Math.min(...i)<=r[3]}),c=l.length?_h(t,l):null,h={floor:t,geom:c,path:c?nh(c):"",area:mh(c||[[[...t,t[0]]]])};return this._resize.preview||fv(this._cleanFloorCache,n,h,600),h}_autoIconForBinding(e){if("virtual"===e)return"mdi:map-marker";const[t,i]=e.split(":");if(!i)return"";const s=this._fullRegistryHass,n=this._bindingStatus(e),o="active"===n.kind?n.enabledEntityIds:n.allEntityIds;if("device"===t){const e=s.devices?.[i];if(!e)return"mdi:help-circle";const t=o;return t.some(e=>e.startsWith("lock."))?"mdi:lock":yo(s,e.name_by_user||e.name||"",e.model,t,this._iconRules)}if("entity"===t){const e=s.entities?.[i],t=this.hass.states?.[i],n=e?.name||t?.attributes?.friendly_name||i;return i.startsWith("lock.")?"mdi:lock":yo(s,n,"",[i],this._iconRules)}return""}_allRoomsFlat(){const e=[];for(const t of this._serverCfg?.spaces||[])for(const i of t.rooms||[])i.area?e.push({value:t.id+"#"+i.area,label:(t.title||t.id)+" · "+i.name}):i.id&&e.push({value:t.id+"#@"+i.id,label:(t.title||t.id)+" · "+i.name+" · "+this._t("marker.subarea")});return e}_errText(e){if(!e)return this._t("err.unknown");if("string"==typeof e)return e;if("invalid_passage_fields"===e.code){const t=String(e.message||e.error||"").match(/space=([^;]*);\s*opening=([^;]*);\s*fields=([^;]*)/);if(t){const e=this._serverCfg?.spaces?.find(e=>String(e.id)===t[1]),i={contact:"opening.contact_label",lock:"opening.lock_label",invert:"opening.invert",flip_h:"opening.flip_h",flip_v:"opening.flip_v"},s=t[3].split(",").filter(Boolean).map(e=>i[e]?this._t(i[e]):e).join(", ");return this._t("opening.invalid_passage_fields",{room:e?.title||t[1],fields:s})}}if("invalid_partition_opening_jamb_margin"===e.code){const t=String(e.message||e.error||"").match(/margin_cm=([^;]*)/),i=t?Number(t[1]):NaN;if(Number.isFinite(i))return this._t("opening.partition_jamb_margin",{distance:li(i,this._imperial)})}if(e.message)return e.message;if(e.error)return e.error;if(null!=e.code)return this._t("err.code",{code:e.code});try{return JSON.stringify(e)}catch{return String(e)}}_backupErrorText(e){const t=e?.code??e?.error;if("string"==typeof t){const e=`backup.error.${t}`,i=this._t(e);if(i!==e)return i}return this._errText(e)}async _pickMarkerFiles(e){const t=e.target,i=t.files?[...t.files]:[];if(t.value="",!i.length||!this._markerDialog)return;const s=this._markerDialog.uploadId||this._markerDialog.devId||"new",n=[];for(const e of i)try{const t=new FormData;t.append("marker_id",s),t.append("file",e,e.name);const i=this.hass?.fetchWithAuth?await this.hass.fetchWithAuth("/api/houseplan/upload",{method:"POST",body:t}):await fetch("/api/houseplan/upload",{method:"POST",body:t,headers:this.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.hass.auth.data.access_token}`}:{}}),o=await i.json().catch(()=>({}));if(!i.ok||o.error){const e={too_large:this._t("err.too_large",{mb:o.max_mb||50}),bad_ext:this._t("err.bad_ext"),unauthorized:this._t("err.unauthorized")};throw new Error(e[o.error]||o.error||"HTTP "+i.status)}n.push({name:o.name||e.name,url:o.url})}catch(t){this._showToast(this._t("toast.file_failed",{name:e.name,err:this._errText(t)}))}n.length&&this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:[...this._markerDialog.pdfs,...n]},this._showToast(this._t("toast.files_attached",{n:n.length})))}_removeMarkerPdf(e){this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:this._markerDialog.pdfs.filter(t=>t.url!==e)})}_markerLightFields(e){const t={};if(e.lightRoleTouched?"always"===e.lightRole?t.is_light=!0:"never"===e.lightRole&&(t.is_light=!1):e.originalHasIsLight&&(t.is_light=e.originalIsLight??null),e.lightEntityTouched?e.lightEntity&&(t.light_entity=e.lightEntity):e.originalHasLightEntity&&(t.light_entity=e.originalLightEntity??null),e.glowTouched){if("auto"!==e.glowMode){const i={c:Ie(e.glowColor,this._fillColors.glow_light.c)};"fixed"===e.glowMode&&(i.bri=Math.max(.01,Math.min(1,Math.round(e.glowBrightness)/100))),t.glow_color=i}}else e.originalHasGlowColor&&(t.glow_color=e.originalGlowColor??null);return t}_markerTapActionFields(e){return e.tapActionTouched?{tap_action:e.tapAction||null}:e.originalHasTapAction?{tap_action:e.originalTapAction??null}:{}}_markerToggleEntityFields(e){return(t={touched:e.toggleEntityTouched,originalHas:e.originalHasToggleEntity,original:e.originalToggleEntity,value:e.toggleEntity}).touched?t.value?{toggle_entity:t.value}:{}:t.originalHas?{toggle_entity:t.original??null}:{};var t}async _saveMarker(){const e=this._markerDialog;if(!e||e.busy)return;const t=this._effectiveMarkerTapAction(e);if("ha"===e.bindingMode&&(!e.binding||"virtual"===e.binding))return;if("virtual"===e.binding&&!e.name.trim())return void this._showToast(this._t("toast.virtual_name_required"));if("run"===t&&!e.tapTarget)return void this._showToast(this._t("toast.run_target_required"));if(e.valueBadgeTouched&&e.valueBadgeEnabled&&!e.valueBadgeSource)return void this._showToast(this._t("toast.value_badge_source_required"));if("ha"===e.bindingMode){const t=this._bindingStatus(e.binding),i=e.devId?this._markers.find(t=>t.id===e.devId):null,s=!i||i.binding!==e.binding;if("active"!==t.kind&&s)return void this._showToast(this._t("ha_disabled"===t.kind?"toast.ha_disabled_add":"toast.ha_binding_unverified"));if("ha_disabled"===t.kind&&!0===i?.hidden&&!e.hideFromPlan)return this._markerDialog={...e,hideFromPlan:!0},void this._showToast(this._t("entity"===t.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device"))}const i=this._serverCfg;if(!i)return;const s=i.markers||[],n=js(e.room);let o=n?.space||null;const a=n?.area||null,r=n?.roomId||null,l=Fi(e.binding,e.devId,()=>"v_"+Date.now().toString(36)),c=e.devId,h=c?this._devices.find(e=>e.id===c):null,d=n?.space||h?.space||null,p=d?this._spaceModelById(d):this._spaceModel();if(!p)return;const u=p.id;"virtual"!==e.binding||o||(o=u),this._markerDialog={...e,busy:!0};try{const n="virtual"===e.binding?[]:s.filter(t=>t.removed&&t.binding===e.binding).map(e=>e.id),d=n.length>0,_=Zn(e.binding,e.controls,this._bindingEntities(e.binding)),m=s.find(e=>e.id===l||e.id===c)?.vacuum||null,g={id:l,vacuum:m,binding:e.binding,name:e.name.trim()||null,icon:e.icon||null,display:"badge"!==e.display?e.display:null,ripple_color:"icon_ripple"===e.display&&e.rippleColor?e.rippleColor:null,ripple_size:"icon_ripple"===e.display&&1.5!==e.rippleSize?e.rippleSize:null,size:1!==e.size?e.size:null,angle:e.angle?e.angle:null,...this._markerTapActionFields(e),...this._markerToggleEntityFields(e),tap_target:"run"===t&&e.tapTarget||null,tap_confirm:!!e.tapConfirm||null,controls:_.length?_:null,...this._markerLightFields(e),...this._markerValueBadgeFields(e),use_climate_temp:!!e.useClimateTemp||null,glow_radius_cm:(()=>{const t=mv(e.glowRadius);return null==t||t<=0?null:Math.round(this._imperial?30.48*t:100*t)})(),model:e.model.trim()||null,link:e.link.trim()||null,description:e.description.trim()||null,pdfs:e.pdfs,hidden:!!e.hideFromPlan};("virtual"===e.binding||e.room)&&(g.space=o,g.area=a,g.room_id=r);const f=h?.marker?.room_id??null,v=!!e.room&&null!=h&&(h.space!==o||h.area!==a||f!==r);let b=!1;const y=e.uploadId||c;if(y&&y!==l&&g.pdfs?.length)try{const e=await this.hass.callWS({type:"houseplan/files/migrate",from_id:y,to_id:l}),t=e?.mapping||{};g.pdfs=function(e,t,i,s){if(!t||!i||t===i)return e;const n="/files/"+t+"/",o="/files/"+i+"/";return e.map(e=>{if(!e.url.includes(n))return e;const t=e.url.split(n)[1]||"",[i,a]=[t.split("?")[0],t.includes("?")?"?"+t.split("?")[1]:""];if(s){const t=s[decodeURIComponent(i)]??s[i];return t?{...e,url:e.url.split(n+i)[0]+o+encodeURIComponent(t)+a}:e}return{...e,url:e.url.split(n).join(o)}})}(g.pdfs,y,l,t),b=Object.keys(t).length>0}catch(e){this._showToast(this._t("toast.files_migrate_failed",{err:this._errText(e)}))}i.markers=s,c&&c!==l&&(i.markers=function(e,t,i){if(!t||!i||t===i)return[...e];const s=`marker:${t}`,n=`marker:${i}`;return e.map(e=>{const t=Array.isArray(e.controls)?e.controls.map(e=>e===s?n:e):e.controls,i="derived_marker_state"===e.value_badge?.source?.kind&&e.value_badge.source.ref===s?{...e.value_badge,source:{...e.value_badge.source,ref:n}}:e.value_badge;return t===e.controls&&i===e.value_badge?e:{...e,controls:t,value_badge:i}})}(i.markers,c,l)),c&&c!==l&&"derived_marker_state"===g.value_badge?.source?.kind&&g.value_badge.source.ref===`marker:${c}`&&(g.value_badge.source={kind:"derived_marker_state",ref:`marker:${l}`}),i.markers=i.markers.filter(e=>e.id!==l&&e.id!==c&&("virtual"===g.binding||e.binding!==g.binding)),i.markers.push(g);let w=null;const k=c?this._layout[c]:null,x=k?{s:k.s||h?.space||this._space,x:k.x,y:k.y}:c&&h&&this._defPos[c]?this._normPos(h.space,this._defPos[c].x,this._defPos[c].y):null;if(!d&&x&&x.s===u)l===c&&this._layout[l]&&!v||(w={s:x.s,x:x.x,y:x.y},this._layout={...this._layout,[l]:w});else if(d||!this._layout[l]||v){let e=p.vb[0]+p.vb[2]/2,t=p.vb[1]+p.vb[3]/2;const i=r?p.rooms.find(e=>e.id===r):a?p.rooms.find(e=>e.area===a):void 0;i&&([e,t]=this._roomCenter(i)),w=this._normPos(u,e,t),this._layout={...this._layout,[l]:w}}if(await this._saveConfigNow(),w){const e=hl(w);this._layout={...this._layout,[l]:e},this._noteLayoutRev(await this.hass.callWS({type:"houseplan/layout/update",device_id:l,pos:e}))}const $=new Set(n);c&&c!==l&&$.add(c),$.delete(l);for(const e of $)delete this._layout[e],await this.hass.callWS({type:"houseplan/layout/delete",device_id:e}).then(e=>this._noteLayoutRev(e)).catch(()=>{});b&&y&&await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:y}).catch(()=>{}),this._closeMarkerDialog(),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_saved"))}catch(e){this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}async _deleteMarker(){const e=this._markerDialog;if(!e||e.busy||!e.devId)return;const t=e.devId?this._devices.find(t=>t.id===e.devId):null,i=this._markers.find(t=>t.id===e.devId);if(!t&&!i)return;const s=e.name||this._t("device.fallback");if(!confirm(this._t("confirm.remove_marker",{name:s})))return;const n=this._serverCfg;n.markers=n.markers||[];const o=n.markers,a=t?.id||i.id,r=t?"virtual"===t.bindingKind?"virtual":t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:"":i.binding;if(!r)return;const l=function(e,t,i,s){const n=new Set([t]),o=e.filter(e=>{const o=e.id===t||!s&&e.binding===i;return o&&n.add(e.id),!o});return{markers:s?o:[...o,{id:t,binding:i,removed:!0,hidden:!0}],cleanupIds:n}}(n.markers,a,r,"virtual"===r);var c,h;n.markers=(c=l.markers,h=l.cleanupIds,c.map(e=>{if(!Array.isArray(e.controls))return e;const t=e.controls.filter(e=>!("string"==typeof e&&e.startsWith("marker:")&&h.has(e.slice(7))));return t.length===e.controls.length?e:{...e,controls:t.length?t:null}}));const d=l.cleanupIds;this._markerDialog={...e,busy:!0};try{await this._saveConfigNow();for(const e of d){delete this._layout[e],delete this._defPos[e],this._dirtyPos.delete(e),this._sentPos.delete(e);const t=this._activityRt.get(e);t&&clearTimeout(t.timer),this._activityRt.delete(e),this._vacRt.delete(e),delete this._vacSrvTrails[e],await this.hass.callWS({type:"houseplan/layout/delete",device_id:e}).then(e=>this._noteLayoutRev(e)).catch(()=>{}),await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:e}).catch(()=>{}),await this.hass.callWS({type:"houseplan/trail/delete",marker_id:e}).catch(()=>{})}this._deviceInboxReturn&&(this._deviceInboxReturn={...this._deviceInboxReturn,tab:"readd",anchor:r}),this._closeMarkerDialog(),this._infoCard?.id===a&&this._closeInfoCard(),this._selId===a&&(this._selId=null),this._drag?.id===a&&(this._drag=null),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_removed"))}catch(e){this._serverCfg===n&&(n.markers=o),this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}_normPos(e,t,i){return{s:e,x:t/Pv,y:i/Pv}}_openSpaceDialog(e,t){if(this._serverStorage&&this._serverCfg)if("edit"===e){const i=this._serverCfg.spaces.find(e=>e.id===t);if(!i)return;const s=cs(i),n=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?rs(i.settings.custom_fill):null,o="none"===s.fill?{...n||as,a:0}:n;this._spaceDialog={mode:e,spaceId:t,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:s.showBorders,showNames:s.showNames,zeroWallStyle:O_(i),displayTouched:!0,hideDecor:s.hideDecor,hideOpenings:s.hideOpenings,roomColor:s.color,roomOpacity:s.opacity,fillMode:"none"===s.fill?"custom":s.fill,customFill:o,glowEnabled:s.glow,bgColor:s.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:Pr({},i.settings),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:s.tempMin,tempMax:s.tempMax,showLqi:s.showLqi??this._config?.show_signal??!0,cardFontScale:s.cardFontScale,labelTemp:s.labelTemp,labelHum:s.labelHum,labelLqi:s.labelLqi,labelLight:s.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:Sh(Number(i.cell_cm)>0?Number(i.cell_cm):5,this._imperial),cellCmTouched:!1,busy:!1}}else this._spaceDialog={mode:e,title:"",planUrl:null,planFile:null,...Gd(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:ns,roomOpacity:os,fillMode:"custom",customFill:{...as,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:20,tempMax:25,showLqi:this._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:$h(this._imperial),cellCmInput:Sh($h(this._imperial),this._imperial),cellCmTouched:!1,busy:!1};else this._showToast(this._t("toast.integration_missing"))}async _pickPlanFile(e){const t=e.target,i=t.files?.[0];if(!i||!this._spaceDialog)return;const s={"image/svg+xml":"svg","image/png":"png","image/jpeg":"jpg","image/webp":"webp"}[i.type]||(i.name.toLowerCase().endsWith(".svg")?"svg":"");if(!s)return void this._showToast(this._t("toast.plan_formats"));const n=new Uint8Array(await i.arrayBuffer());let o="";for(let e=0;e{const t=new Image;t.onload=()=>e(t.naturalWidth&&t.naturalHeight?t.naturalWidth/t.naturalHeight:1.414),t.onerror=()=>e(1.414),t.src=r});URL.revokeObjectURL(r),this._spaceDialog={...this._spaceDialog,planFile:{ext:s,b64:a,aspect:l,name:i.name}}}_useServerPlan(e){const t=this._spaceDialog;t&&(this._spaceDialog={...t,planUrl:e,planFile:null,pickSaved:!1,savedAspect:void 0},this._aspectJob=this._readPlanAspect(e))}async _readPlanAspect(e){for(let t=0;t<40;t++){const t=this._display(e);if(t){const i=await new Promise(e=>{const i=new Image;i.onload=()=>e(i.naturalWidth&&i.naturalHeight?i.naturalWidth/i.naturalHeight:0),i.onerror=()=>e(0),i.src=t}),s=this._spaceDialog;return s&&s.planUrl===e&&Number.isFinite(i)&&i>0?(this._spaceDialog={...s,savedAspect:i},i):0}if(await new Promise(e=>setTimeout(e,150)),this._spaceDialog?.planUrl!==e)return 0}return 0}async _deleteServerPlan(e){if(confirm(this._t("confirm.delete_plan",{name:e})))try{await this.hass.callWS({type:"houseplan/plans/delete",name:e});const t=this._spaceDialog;t?.saved&&(this._spaceDialog={...t,saved:t.saved.filter(t=>t.name!==e)})}catch(e){this._showToast(this._t("toast.plan_delete_failed",{err:this._errText(e)}))}}_renderServerPlans(e){if(e.savedBusy)return q`
${this._t("space.loading")}
`;const t=e.saved||[];if(!t.length)return q`
${this._t("space.no_saved")}
`;return q`
+
`:q``}_openingAt(e){if(!this._openingsR.length)return null;const t=this._openingsR.flatMap(t=>{const i=t.angle*Math.PI/180,s=e[0]-t.rx,n=e[1]-t.ry,o=s*Math.cos(i)+n*Math.sin(i);return Math.abs(o)>t.rlen/2+xh(12,this._cellCm)?[]:[{o:t,localY:-s*Math.sin(i)+n*Math.cos(i)}]});if(!t.length)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s).value;return t.find(({o:e,localY:t})=>{const i="gate"===e.type?!e.flip_v:e.flip_v,s=e.partitionHost||this._spaceWalls.length||"gate"===e.type?this._openingFace(e,n,!!i):{ox:0,oy:0,cm:0,side:-1},o=d_({type:e.type,length:e.rlen,angle:e.angle,amount:this._openingAmt(e),flipH:!!e.flip_h,flipV:!!e.flip_v,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s});return Math.abs(t)<=o.hitHalf})?.o||null}_resolveOpeningPlacement(e){const t=this._openingPreset;if("opening"!==this._tool||!t)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s),o=`${n.key}|partitions:${this._cfgEpoch}`;this._openingPlacementIntervalsCache&&this._openingPlacementIntervalsCache.key===o||(this._openingPlacementIntervalsCache={key:o,value:[...gc(i.rooms,this._spaceWalls,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv),...tu(i.partitions,this._cellCm,this._gridPitch)]}),this._openingDimensionContextCache&&this._openingDimensionContextCache.key===o||(this._openingDimensionContextCache={key:o,value:ev({rooms:i.rooms,walls:this._spaceWalls,openCuts:s,partitions:i.partitions,roomOpenings:this._roomWallOpeningInputs(),partitionCuts:this._partitionOpeningCuts(i),pitch:this._wallKeyPitch,cellCm:this._cellCm,gridPitch:this._gridPitch,coordScale:Pv,epsilon:2e-4*this._gridPitch})});const a=Uf({pointer:[e[0],e[1]],preset:t,geometryRevision:this._cfgEpoch,renderedLength:this._cmToUnits(t.lengthCm),intervals:this._openingPlacementIntervalsCache.value,baseTolerance:1.5*this._gridPitch,bodyPointerPadding:this._cssPxToRender("touch"===this._pointerModality.modality||"pen"===this._pointerModality.modality?10:6),gridStep:this._gridPitch});this._openingJambBlockCm=a.jambBlockedTarget?a.jambBlockedTarget.physicalHalfWidth/this._gridPitch*this._cellCm:null;const r=a.candidate;if(!r)return null;const l="gate"===r.type?!r.flipV:r.flipV;let c;if(r.host){const e=Jp({id:"preview",type:r.type,x:r.x/Pv,y:r.y/Pv,angle:r.angle,length:r.renderedLength/Pv,host:r.host},i.partitions,Pv,this._cellCm,this._gridPitch).resolved;c=e?eu(e,l):{ox:0,oy:0,cm:0,side:-1}}else c=Vc(n.value,{x:r.x,y:r.y,angle:r.angle,length:r.renderedLength,flip_v:l});const h="mi"===this.hass?.config?.unit_system?.length,d=rv(r,this._openingDimensionContextCache.value).map(e=>({x:e.label[0],y:e.label[1],text:li(e.distance/this._gridPitch*this._cellCm,h),dimension:e}));return{...r,face:c,measure:{labels:d,guide:r.measure.guide}}}_activateOpeningPlacement(e){this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingPreset=function(e,t){return{type:e,lengthCm:Bf(e),flipH:!1,flipV:!1,revision:t}}(e,++this._openingPresetRevision),this._openingHoverCandidate=null,this._cursorPt=null)}_clearOpeningPlacement(e){this._openingHoverCandidate=null,this._openingJambBlockCm=null,e&&(this._openingPreset=null,this._openingRebindId=null)}_openingClick(e){const t=this._spaceModel();if(!t)return;const i=this._openingRebindId?null:this._openingAt(e);if(i)return void this._editOpening(i);const s=this._openingPreset;if(!s)return;const n=this._openingHoverCandidate,o=n&&Gf(n,[e[0],e[1]],s.revision,this._cfgEpoch)?n:this._resolveOpeningPlacement(e);if(!o){if(null!=this._openingJambBlockCm)return void this._showToast(this._t("opening.partition_jamb_margin",{distance:li(this._openingJambBlockCm,this._imperial)}));const i=1.5*this._gridPitch,s=ui(e,t.rooms,i);return s&&function(e,t,i,s,n){for(const o of s)if(!(Hs([e,t],o)>n)&&Nl([o[0],o[1]],[o[2],o[3]],i))return!0;return!1}(s.x,s.y,s.angle,this._openCuts(),i)?void this._showToast(this._t("toast.opening_on_zero_wall")):void this._showToast(this._t("toast.opening_no_wall"))}const a=this._openingRebindId?this._curSpaceCfg?.openings?.find(e=>e.id===this._openingRebindId):null;this._openingDialog={...a?{id:a.id,type:a.type,lengthCm:Math.round(a.length*Pv/this._gridPitch*this._cellCm),lengthTouched:!1,contact:a.contact||"",lock:a.lock||"",invert:!!a.invert,flipH:!!a.flip_h,flipV:!!a.flip_v}:{type:o.type,lengthCm:o.lengthCm,contact:"",lock:"",invert:!1,flipH:o.flipH,flipV:o.flipV},...o.host?{host:o.host}:{},x:o.x,y:o.y,angle:o.angle},this._openingRebindId=null,this._openingHoverCandidate=null,this._cursorPt=null}_editOpening(e){this._openingDialog={id:e.id,type:e.type,lengthCm:Math.round(e.rlen/this._gridPitch*this._cellCm),lengthTouched:!1,contact:e.contact||"",lock:e.lock||"",invert:!!e.invert,flipH:!!e.flip_h,flipV:!!e.flip_v,..."partition"===e.host?.kind?{host:{...e.host}}:{},x:e.rx,y:e.ry,angle:e.angle}}_opPointerDown(e,t){if("plan"===this._mode&&this._spaceModel()&&"resize"!==this._tool){e.preventDefault(),e.stopPropagation();try{Ev(e)}catch{}this._opDrag={id:t.id,moved:!1,sx:e.clientX,sy:e.clientY,dirty:!1,before:this._geometrySnapshot()}}}_opPointerMove(e,t){if(!this._opDrag||this._opDrag.id!==t.id)return;if(Math.abs(e.clientX-this._opDrag.sx)+Math.abs(e.clientY-this._opDrag.sy)<=3)return;const i=this._spaceModel();if(!i)return;const s=this._svgPoint(e),n=this._curSpaceCfg,o=n?.openings?.find(e=>e.id===t.id);if(!o)return;if("partition"===o.host?.kind){const e=i.partitions.find(e=>e.id===o.host.id);if(!e)return;const t=e.b[0]-e.a[0],n=e.b[1]-e.a[1],a=Math.hypot(t,n);if(!(a>1e-9))return;const r=t/a,l=n/a;if(Math.abs((s[0]-e.a[0])*l-(s[1]-e.a[1])*r)>4*this._gridPitch)return;const c=o.length*Pv/2+Kp(e,this._cellCm,this._gridPitch);let h=(s[0]-e.a[0])*r+(s[1]-e.a[1])*l;if(h=Math.round(h/this._gridPitch)*this._gridPitch,h=Math.max(c,Math.min(a-c,h)),a<2*c-1e-9)return;const d=h/a,p=(e.a[0]+r*h)/Pv,u=(e.a[1]+l*h)/this._spaceH;let _=180*Math.atan2(n,t)/Math.PI;_>=90?_-=180:_<-90&&(_+=180);const m=o.host.t!==d||o.x!==p||o.y!==u||o.angle!==_;return this._opDrag.moved=!0,m&&(this._opDrag.dirty=!0),o.host={...o.host,t:d},o.x=p,o.y=u,o.angle=_,this._opMeasure=null,m&&this._cfgEpoch++,void this.requestUpdate()}const a=ui(s,i.rooms,4*this._gridPitch);if(!a)return;this._opDrag.moved=!0;const r=this._opRuler(a,o.length*Pv);this._opMeasure=r.measure;const l=r.x/Pv,c=r.y/this._spaceH,h=o.x!==l||o.y!==c||o.angle!==a.angle;if(h&&(this._opDrag.dirty=!0),o.x=l,o.y=c,o.angle=a.angle,Number(this._serverCfg?.model_version||0)>=9){const e=wg(o,n?.wall_segments||[]);e?o.host=e:delete o.host}h&&this._cfgEpoch++,this.requestUpdate()}_opRuler(e,t){const i=this._spaceModel()?.rooms||[],s=this._gridPitch/2;let n=e.x,o=e.y,a=_i([n,o],e.angle,t,i,s);if(a&&a.centered&&(n!==a.wallCenter[0]||o!==a.wallCenter[1]))[n,o]=a.wallCenter,a=_i([n,o],e.angle,t,i,s);else if(a){const[r,l]=a.wallA,[c,h]=a.wallB,d=c-r,p=h-l,u=Math.hypot(d,p);if(u>0){const c=this._gridPitch,h=Math.min(t/2,u/2);let _=Math.round(((n-r)*d+(o-l)*p)/u/c)*c;_=Math.max(h,Math.min(u-h,_)),n=r+_/u*d,o=l+_/u*p,a=_i([n,o],e.angle,t,i,s)||a}}if(!a)return{x:n,y:o,angle:e.angle,measure:null};const r="mi"===this.hass?.config?.unit_system?.length,l=(e,t)=>({x:t[0],y:t[1],text:li(e/this._gridPitch*this._cellCm,r)});return{x:n,y:o,angle:e.angle,measure:{labels:[l(a.sideA,a.midA),l(a.sideB,a.midB)],guide:a.centered?{x:a.wallCenter[0],y:a.wallCenter[1],angle:e.angle}:null}}}_opPointerUp(e,t){if(!this._opDrag||this._opDrag.id!==t.id)return;const i=this._opDrag,s=i.moved;this._opMeasure=null,s&&i.dirty&&this._commitPhysicalGeometry(this._t("history.move_opening"),i.before),s?window.setTimeout(()=>this._opDrag=null,0):this._opDrag=null}_opClick(e,t){"plan"===this._mode&&"resize"===this._tool||(e.stopPropagation(),this._opDrag?.moved||"plan"===this._mode&&this._editOpening(t))}_saveOpening(){const e=this._openingDialog,t=this._curSpaceCfg,i=this._spaceModel();if(!e||!t||!i)return;const s=this._geometrySnapshot(),n=this._spaceH,o=(t.openings||[]).find(t=>t.id===e.id),a={...o||{},id:e.id||"o"+Date.now().toString(36),type:e.type,x:e.x/Pv,y:e.y/n,angle:e.angle,length:o&&!e.lengthTouched?o.length:this._cmToUnits(Math.max(20,e.lengthCm))/Pv,...e.host?{host:{...e.host}}:{}};if("partition"===a.host?.kind){const e=Zp(o,a)?Xp(a,i.partitions,Pv,this._cellCm,this._gridPitch):Jp(a,i.partitions,Pv,this._cellCm,this._gridPitch);if(!e.resolved){const t=i.partitions.find(e=>e.id===a.host.id);if("does-not-fit-jamb"===e.reason&&t){const e=Kp(t,this._cellCm,this._gridPitch);this._showToast(this._t("opening.partition_jamb_margin",{distance:li(e/this._gridPitch*this._cellCm,this._imperial)}))}else this._showToast(this._t("opening.partition_orphan"));return}const s=(t.openings||[]).flatMap(e=>{if(!e.host||e.id===a.id)return[];const t=Jp(e,i.partitions,Pv,this._cellCm,this._gridPitch).resolved;return t?[t]:[]});if(function(e,t,i=1e-9){const s=e.length/(2*e.axis.length),n=e.t-s,o=e.t+s;return t.some(t=>{if(t.host.id!==e.host.id||t.opening.id===e.opening.id)return!1;const s=t.length/(2*t.axis.length);return Math.max(n,t.t-s)=9){const e=wg(a,t.wall_segments||[]);if(!e)return void this._showToast(this._t("toast.opening_no_wall"));a.host=e}else delete a.host;"passage"===e.type?(delete a.contact,delete a.lock,delete a.invert,delete a.flip_h,delete a.flip_v):(a.contact=e.contact||null,a.lock=("door"===e.type||"gate"===e.type)&&e.lock||null,a.invert=e.invert||void 0,a.flip_h="gate"!==e.type&&e.flipH||void 0,a.flip_v=e.flipV||void 0),t.openings=t.openings||[];const r=t.openings.findIndex(e=>e.id===a.id);r>=0?t.openings[r]=a:t.openings.push(a),this._commitPhysicalGeometry(this._t(e.id?"history.edit_opening":"history.add_opening"),s),this._openingDialog=null,this.requestUpdate()}_deleteOpening(){const e=this._openingDialog,t=this._curSpaceCfg;if(!e?.id||!t?.openings)return;const i=this._geometrySnapshot();t.openings=t.openings.filter(t=>t.id!==e.id),this._commitPhysicalGeometry(this._t("history.delete_opening"),i),this._openingDialog=null,this.requestUpdate()}_contactCandidates(){const e=[];for(const t of Object.keys(this.hass.states)){if(!this._openingEntityAvailable(t))continue;const i=t.split(".")[0];if("binary_sensor"!==i&&"cover"!==i)continue;const s=this.hass.states[t],n=["door","window","opening","garage_door","garage"].includes(s?.attributes?.device_class||"");("cover"!==i||n)&&e.push([t,s?.attributes?.friendly_name||t,n?0:1])}return e.sort((e,t)=>e[2]-t[2]||e[1].localeCompare(t[1])).map(([e,t])=>({value:e,label:t}))}_lockCandidates(){return Object.keys(this.hass.states).filter(e=>e.startsWith("lock.")&&this._openingEntityAvailable(e)).map(e=>({value:e,label:this.hass.states[e]?.attributes?.friendly_name||e})).sort((e,t)=>e.label.localeCompare(t.label))}_toggleOpeningEntityPicker(e){const t=this._openingDialog;if(!t)return;const i="contact"===e?!t.contactOpen:!t.lockOpen;this._openingDialog={...t,contactOpen:"contact"===e&&i,lockOpen:"lock"===e&&i}}_filterOpeningEntities(e,t){const i=this._openingDialog;i&&(this._openingDialog="contact"===e?{...i,contactFilter:t}:{...i,lockFilter:t})}_selectOpeningEntity(e,t){const i=this._openingDialog;i&&(this._openingDialog="contact"===e?{...i,contact:t,contactOpen:!1,contactFilter:""}:{...i,lock:t,lockOpen:!1,lockFilter:""})}_mergeClick(e){const t=this._spaceModel();if(!t)return;const i=t.rooms,s=[...i].reverse().find(t=>this._pointInRoom(e,t));if(!s?.id)return;const n=s.id;if(!this._mergeSel||this._mergeSel===n)return void(this._mergeSel=this._mergeSel===n?null:n);const o=i.find(e=>e.id===this._mergeSel),a=o?hi(o):null,r=hi(s),l=a&&r?function(e,t){if(!e||!t||e.length<3||t.length<3)return null;const i=si(Ii(e),Ii(t));if(1!==i.length)return null;if(1!==i[0].length)return null;const s=i[0][0].slice(0,-1).map(e=>[e[0],e[1]]);return s.length>=3?s:null}(a,r):null;if(!l)return this._showToast(this._t("toast.merge_not_adjacent")),void(this._mergeSel=null);this._mergeDialog={aId:this._mergeSel,bId:n,poly:l,pick:"a"},this._mergeSel=null}_commitMerge(){const e=this._mergeDialog,t=this._curSpaceCfg;if(!e||!t||!this._spaceModel())return;const i=this._geometrySnapshot(),s=this._spaceH,n="a"===e.pick?e.aId:e.bId,o="a"===e.pick?e.bId:e.aId,a=t.rooms.find(e=>e.id===n);if(!a)return void(this._mergeDialog=null);a.poly=e.poly.map(e=>[e[0]/Pv,e[1]/s]),delete a.x,delete a.y,delete a.w,delete a.h,t.rooms=t.rooms.filter(e=>e.id!==o);const r=this._commitPhysicalGeometry(this._t("history.merge_rooms"),i);this._mergeDialog=null,this._regSignature="",this._maybeRebuildDevices(),r&&this._showToast(this._t("toast.rooms_merged",{name:a.name||""}))}_splitClick(e){const t=this._spaceModel();if(!t)return;const i=t.rooms;if(!this._splitSel){const t=[...i].reverse().find(t=>this._pointInRoom(e,t));if(!t?.id)return;return void(this._splitSel={roomId:t.id,pts:[]})}const s=i.find(e=>e.id===this._splitSel.roomId),n=s?hi(s):null;if(!s||!n)return void(this._splitSel=null);const o=.02*this._gridPitch,a=6*this._gridPitch,r=function(e,t){if(!t||t.length<2)return null;let i=null,s=1/0;for(let n=0;n=n)continue;n=_;const m=Math.sqrt(p),g=(i>0?Math.max(0,Math.min(m,Math.round(u*m/i)*i)):u*m)/m;s=[a+g*h,r+g*d]}return s}(r,n,this._gridPitch)||r,c=r&&l&&Math.hypot(r[0]-e[0],r[1]-e[1])<=a?l:null,h=!!c&&yi(c,n,o),d=this._splitSel.pts;if(!d.length)return h?void(this._splitSel={...this._splitSel,pts:[c]}):void this._showToast(this._t("toast.split_pick_wall"));if(!h){const t=this._snap(e);return wi(t,n,o)?void(this._splitSel={...this._splitSel,pts:[...d,t]}):void this._showToast(this._t("toast.split_pick_inside"))}const p=zi(n,[...d,c],o);if(!p)return void this._showToast(this._t("toast.split_bad_cut"));this._resetRoomDialogFields();const[u,_]=p,m=Ti(u)>=Ti(_)?u:_,g=m===u?_:u;this._pendingSplit={roomId:s.id,mainPoly:m,newPoly:g},this._cursorPt=null,this._nameSel="",this._areaSel="",this._roomDialog=!0}get _contourClosed(){return this._path.length>=4&&this._samePt(this._path[0],this._path[this._path.length-1])&&(null!=this._closingWallCm||!this._activeDraftId)}_markupMove(e){if(!this._markup)return;if("column"===this._tool)return void(this._cursorPt=this._snap(this._svgPoint(e)));if("opening"===this._tool||"wallthick"===this._tool)return void(this._cursorPt=this._svgPoint(e));const t="draw"===this._tool&&!this._contourClosed,i="split"===this._tool&&!!this._splitSel?.pts?.length;if(!t&&!i)return;const s=this._svgPoint(e);if(t){const t=this._resolvePlanDrawPoint(s,e.shiftKey);return this._planSnapHover={contextKey:t.contextKey,candidate:t.candidate,conflicts:t.conflicts},this._syncPlanSnapConflictMarkers(t.conflicts),this._path.length?void(this._cursorPt=t.point):void this._syncPlanSnapActiveMarker(t.candidate)}this._cursorPt=this._snap(s)}get _openingPreview(){const e=this._openingPreset;if("opening"!==this._tool||!e||!this._cursorPt)return null;const t=this._cursorPt,i=this._openingHoverCandidate;if(i&&Gf(i,[t[0],t[1]],e.revision,this._cfgEpoch))return i;if(this._openingAt(t))return this._openingHoverCandidate=null,null;const s=this._resolveOpeningPlacement(t);return this._openingHoverCandidate=s,s}get _opMeasureView(){return this._opMeasure||this._openingPreview?.measure||null}_saveRoom(){(this._areaSel||this._nameSel.trim())&&(this._wallFaceBatch?this._decideWallFace(!0):this._commitRoom())}_decideWallFace(e){const t=this._wallFaceBatch;if(!t)return;const i=t.candidates[t.index];if(!i)return;if(!e&&(i.existing||i.repair)&&1===t.candidates.length)return this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",void this.requestUpdate();const s=e?{candidate:i,create:!0,name:this._nameSel.trim(),area:this._areaSel||null,settings:this._roomSettingsFromDialog()?JSON.parse(JSON.stringify(this._roomSettingsFromDialog())):null}:{candidate:i,create:!1},n=[...t.decisions,s],o=t.index+1;if(o"number"==typeof e&&Number.isFinite(e)&&e>=0?e:null,n=.02*this._gridPitch,o=this._spaceModel();if(!o)return ul;for(const t of this._planSnapGeometrySnapshot().value.segments){if("room"===t.sourceKind||Hs(e,[t.a[0],t.a[1],t.b[0],t.b[1]])>n)continue;if("partition"===t.sourceKind)return s(o.partitions.find(e=>e.id===t.sourceId)?.cm)??ul;const i=t.sourceId.lastIndexOf(":"),a=i>=0?t.sourceId.slice(0,i):t.sourceId,r=i>=0?Number(t.sourceId.slice(i+1)):-1;return s(o.room_drafts.find(e=>e.id===a)?.segments[r]?.cm)??ul}const a=ku(Math.max(0,t.length-1),i,this._drawWallCm,ul);for(let i=0;i+1[...e]);if(!t?.sourceKey.startsWith("active:"))return i;const s=/:(\d+)$/.exec(t.sourceKey),n=s?Number(s[1])+("b"===t.endpoint?1:0):-1;return n>=0&&nt.key===e.sourceKey),o=s.find(t=>t.key===e.targetSourceKey);if(!n||!o)return!1;const a="a"===e.endpoint?n.a:n.b;return!(Math.hypot(a[0]-e.from[0],a[1]-e.from[1])>i)&&(!(Hs(e.to,[o.a[0],o.a[1],o.b[0],o.b[1]])>i)&&!function(e,t){if(!e.sourceKey.startsWith("static:partition|"))return!1;const i=e.sourceKey.slice(17).split("|")[0];return!!i&&t.some(e=>"partition"===e.host?.kind&&e.host.id===i)}(e,this._curSpaceCfg?.openings||[]))}_applyWallRepair(e,t){const i=this._curSpaceCfg;if(!i||!this._validateWallRepair(e,t.activePath))return!1;const s=t=>{t[0]=e.to[0]/Pv,t[1]=e.to[1]/Pv};if(e.sourceKey.startsWith("active:")){const n=/:(\d+)$/.exec(e.sourceKey),o=n?Number(n[1])+("b"===e.endpoint?1:0):-1;if(o<0||o>=t.activePath.length)return!1;t.activePath[o]=[...e.to];const a=(i.room_drafts||[]).find(e=>e.id===t.activeDraftId);return a?.points?.[o]&&s(a.points[o]),!0}if(!e.sourceKey.startsWith("static:"))return!1;const[n,o]=e.sourceKey.slice(7).split("|");if("partition"===n){const t=(i.partitions||[]).find(e=>e.id===o);if(!t)return!1;const n=[t.a[0]*Pv,t.a[1]*Pv],a=[t.b[0]*Pv,t.b[1]*Pv],r=Math.hypot(n[0]-e.from[0],n[1]-e.from[1])<=2e-4*this._gridPitch?t.a:Math.hypot(a[0]-e.from[0],a[1]-e.from[1])<=2e-4*this._gridPitch?t.b:null;return!!r&&(s(r),!0)}if("draft"===n){const t=o.lastIndexOf(":"),n=t>=0?o.slice(0,t):"",a=t>=0?Number(o.slice(t+1)):-1,r=(i.room_drafts||[]).find(e=>e.id===n);if(!r?.points?.[a]||!r?.points?.[a+1])return!1;const l=[a,a+1].find(t=>Math.hypot(r.points[t][0]*Pv-e.from[0],r.points[t][1]*Pv-e.from[1])<=2e-4*this._gridPitch);return null!=l&&(s(r.points[l]),!0)}return!1}_applyWallFaceBatch(){const e=this._wallFaceBatch,t=this._curSpaceCfg,i=this._spaceModel();if(!e||!t||!i)return;const s=(e,t)=>{this._showToast(this._t(e,t)),this._roomDialogCancel()},n=e.decisions.filter(e=>e.create),o=n.map(e=>e.candidate.ring),a=i.rooms;for(let e=0;ei.id!==t&&!!hi(i)&&Di(o[e],hi(i)));if(i)return void s("toast.room_overlap",{name:i.name||""})}if((t.rooms||[]).length+n.length>400)return void s("toast.physical_limit");if(n.some(e=>e.candidate.split&&!t.rooms.some(t=>t.id===e.candidate.split.roomId)))return void s("toast.contour_cannot_close");const r=n.map(e=>e.candidate.repair).filter(e=>!!e);if(r.length>1||r[0]&&!this._validateWallRepair(r[0],e.activePath))return void s("toast.wall_repair_changed");const l=this._activePathWithRepair(e.activePath,r[0]),c=2e-4*this._gridPitch,h=new Map;for(let t=0;te.candidate.atomKeys)),t=n.some(e=>e.candidate.consumeAllActive);for(const i of Wu(this._wallGraphSources(l),c)){const s=i.sourceKeys.find(e=>h.has(e));!s||t||e.has(i.key)||d.push({a:i.a,b:i.b,cm:h.get(s)})}}else d.push(...xu(l,ku(l.length-1,e.activeCms,this._drawWallCm,ul)));if((t.partitions||[]).length+d.length>Av)return void s("toast.physical_limit");const p=n.map(e=>e.candidate.ring.map(()=>"")),u=e.activeDraftId?(t.room_drafts||[]).find(t=>t.id===e.activeDraftId):null,_=this._draftSegmentsForPath(e.activePath,u,e.activeCms),m=(e,t)=>{const i=`${e[0].toFixed(9)},${e[1].toFixed(9)}`,s=`${t[0].toFixed(9)},${t[1].toFixed(9)}`;return i<=s?`${i}|${s}`:`${s}|${i}`};for(let t=0;t<_.length;t++){const i=_[t]?.id;if(!i)continue;const s=e.activePath[t],o=e.activePath[t+1],a=[s[0],s[1],o[0],o[1]],r=[];n.forEach((e,t)=>e.candidate.ring.forEach((i,s)=>{const n=e.candidate.ring[(s+1)%e.candidate.ring.length];Hs(i,a)<=c&&Hs(n,a)<=c&&r.push({kind:"room",owner:t,edge:s,a:i,b:n})})),d.forEach((e,t)=>{Hs(e.a,a)<=c&&Hs(e.b,a)<=c&&r.push({kind:"partition",owner:t,edge:0,a:e.a,b:e.b})});const l=[(s[0]+o[0])/2,(s[1]+o[1])/2];r.sort((e,t)=>{const i=[e.a[0],e.a[1],e.b[0],e.b[1]],n=[t.a[0],t.a[1],t.b[0],t.b[1]];return(Hs(l,i)<=c?0:1)-(Hs(l,n)<=c?0:1)||(Hs(s,i)<=c?0:1)-(Hs(s,n)<=c?0:1)||m(e.a,e.b).localeCompare(m(t.a,t.b))});const h=r[0];if(!h)continue;const u=m(h.a,h.b);for(const e of r)m(e.a,e.b)===u&&("room"===e.kind?p[e.owner][e.edge]=i:d[e.owner].id=i)}const g=this._geometrySnapshot();if(r[0]&&!this._applyWallRepair(r[0],e))return void s("toast.wall_repair_changed");const f=n.some(e=>!!e.candidate.split),v=f?fc(i.rooms,t.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Pv):null,b=f&&Array.isArray(t.walls)?t.walls:null;for(const e of n){const i=e.candidate.split;if(!i)continue;const n=t.rooms.find(e=>e.id===i.roomId);if(!n)return void s("toast.contour_cannot_close");n.poly=i.mainPoly.map(e=>[e[0]/Pv,e[1]/this._spaceH]),delete n.x,delete n.y,delete n.w,delete n.h}const y=Date.now().toString(36),w=[];if(n.forEach((e,i)=>{const s=e.area?this.hass.areas[e.area]?.name:"",n={id:`r${y}-${i}`,name:e.name||s||this._t("room.default_name"),area:e.area||null,poly:e.candidate.ring.map(e=>[e[0]/Pv,e[1]/this._spaceH]),...p[i].some(Boolean)?{wall_ids:p[i]}:{},...e.settings?{settings:JSON.parse(JSON.stringify(e.settings))}:{}};t.rooms.push(n),w.push({room:n,decision:e})}),e.activeDraftId&&Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t.id!==e.activeDraftId),t.room_drafts.length||delete t.room_drafts),d.length&&(t.partitions||=[],d.forEach((e,i)=>t.partitions.push({id:e.id||`partition-${y}-${i}`,a:[e.a[0]/Pv,e.a[1]/Pv],b:[e.b[0]/Pv,e.b[1]/Pv],cm:e.cm}))),f){const e=this._normalizeWalls(v,this._openCuts());e.length?t.walls=e:b?.length?t.walls=b:delete t.walls}if(w.length){this._cfgEpoch++;const i=this._openCuts(),s=this._spaceModel();if(!s)return;let n=t.walls;for(const{room:t,decision:o}of w){const a=o.candidate.ring,r=this._wallSourceCmAt(a[0],e.activePath,e.activeCms);n=jl(n,s.rooms,t.id,r,this._wallKeyPitch,i,Pv);for(const o of gc(s.rooms,n,i,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv)){if(o.roomId!==t.id||"outer"!==o.kind)continue;const i=[(o.a[0]+o.b[0])/2,(o.a[1]+o.b[1])/2];n=Ll(n,o.a,o.b,this._wallSourceCmAt(i,e.activePath,e.activeCms),this._wallKeyPitch,Pv)}}const o=this._normalizeWalls(n,i);o.length?t.walls=o:delete t.walls}if(!this._commitPhysicalGeometry(this._t("history.wall_face_batch"),g))return;delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices();const k=new Set(n.map(e=>e.area).filter(e=>!!e));if(k.size){const e={...this._layout};for(const t of this._devices){if(!k.has(t.area||"")||t.space!==this._space)continue;if(this._layout[t.id])continue;const i=this._defPos[t.id];i&&(e[t.id]={s:this._space,x:i.x/Pv,y:i.y/Pv},this._dirtyPos.add(t.id))}this._layout=e,this._persistLayout()}this._showToast(this._t(n.length?"toast.wall_rooms_saved":"toast.wall_chain_saved",{n:n.length}))}_commitRoom(){const e=this._curSpaceCfg,t=this._spaceModel();if(!e||!t)return;const i=this._geometrySnapshot(),s=this._spaceH,n=!!this._pendingSplit,o=n?fc(t.rooms,e.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Pv):null,a=n&&Array.isArray(e.walls)?e.walls:null;let r;if(this._pendingSplit){const t=e.rooms.find(e=>e.id===this._pendingSplit.roomId);if(!t)return this._pendingSplit=null,this._splitSel=null,void(this._roomDialog=!1);t.poly=this._pendingSplit.mainPoly.map(e=>[e[0]/Pv,e[1]/s]),delete t.x,delete t.y,delete t.w,delete t.h,r=this._pendingSplit.newPoly}else{if(!this._contourClosed)return;r=this._path.slice(0,-1)}const l=this._areaSel?this.hass.areas[this._areaSel]?.name:"",c={id:"r"+Date.now().toString(36),name:this._nameSel||l||this._t("room.default_name"),area:this._areaSel||null,poly:r.map(e=>[e[0]/Pv,e[1]/s]),...this._roomSettingsFromDialog()?{settings:this._roomSettingsFromDialog()}:{}};if(!n&&this._activeDraftId){const t=Array.isArray(e.room_drafts)?e.room_drafts.find(e=>e.id===this._activeDraftId):null,i=ku(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,ul),s=this._draftSegmentsForPath(this._path,t,i);s.length===r.length&&s.every(e=>!!e.id)&&(c.wall_ids=s.map(e=>e.id))}if(e.rooms.push(c),!n&&this._activeDraftId&&Array.isArray(e.room_drafts)&&(e.room_drafts=e.room_drafts.filter(e=>e.id!==this._activeDraftId),e.room_drafts.length||delete e.room_drafts),n){const t=this._normalizeWalls(o,this._openCuts());t.length?e.walls=t:a?.length?e.walls=a:delete e.walls}if(!n){const t=ku(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,ul),i=t[0];if(null!=i){this._cfgEpoch++;const s=this._openCuts(),n=this._spaceModel();if(!n)return;let o=jl(e.walls,n.rooms,c.id,i,this._wallKeyPitch,s,Pv);for(const e of gc(n.rooms,o,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Pv)){if(e.roomId!==c.id||"outer"!==e.kind)continue;const i=[(e.a[0]+e.b[0])/2,(e.a[1]+e.b[1])/2],s=r.findIndex((e,t)=>{const s=r[(t+1)%r.length];return Hs(i,[e[0],e[1],s[0],s[1]])<=.02*this._gridPitch});s>=0&&(o=Ll(o,e.a,e.b,t[s],this._wallKeyPitch,Pv))}o=this._normalizeWalls(o,s),o.length?e.walls=o:delete e.walls}}const h=this._commitPhysicalGeometry(this._t(n?"history.split_room":"history.add_room"),i);this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._pendingSplit=null,this._splitSel=null;const d=this._areaSel;if(this._areaSel="",this._nameSel="",this._roomDialog=!1,this._regSignature="",this._maybeRebuildDevices(),!h)return;let p=0;if(d){const e=Pv,t={...this._layout};for(const i of this._devices){if(i.area!==d||i.space!==this._space)continue;if(p++,this._layout[i.id])continue;const s=this._defPos[i.id];s&&(t[i.id]={s:this._space,x:s.x/Pv,y:s.y/e},this._dirtyPos.add(i.id))}this._layout=t,this._persistLayout()}const u=this._model.find(e=>e.id===this._space)?.rooms.length||0;this._showToast(d?this._t("toast.room_saved",{n:u,added:p}):this._t("toast.room_saved_no_area",{n:u}))}_cancelPath(){this._wallRepairDiagnostic=null,this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),this._roomDialog=!1,this._pendingSplit=null,this._wallFaceBatch=null,this._splitSel=null,this._mergeSel=null,this._mergeDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._clearOpeningPlacement(!0)}_resumeLastDraft(){const e=this._resumeDraftBySpace[this._space];if(!e)return;const t=this._spaceModel()?.room_drafts.find(t=>t.id===e);t?(this._activeDraftId=e,this._path=t.points.map(e=>[...e]),this._draftSegmentCms=this._adoptDraftCms(this._path,t.segments.map(e=>e.cm),t.id),this._clearPlanSnapHover()):delete this._resumeDraftBySpace[this._space]}_roomDialogCancel(){if(this._roomDialog=!1,this._roomEditId)return this._roomEditId=null,this._nameSel="",void(this._areaSel="");if(this._wallFaceBatch){const e=this._wallFaceBatch;return this._wallFaceBatch=null,this._path=e.activePath.map(e=>[...e]),this._draftSegmentCms=[...e.activeCms],this._activeDraftId=e.activeDraftId,this._nameSel="",this._areaSel="",void this.requestUpdate()}if(this._pendingSplit)return this._pendingSplit=null,void(this._splitSel=null);this._undoPoint()}get _freeAreas(){const e=new Set;for(const t of this._serverCfg?.spaces||[])for(const i of t.rooms||[])i.area&&e.add(i.area);for(const t of this._wallFaceBatch?.decisions||[])t.create&&t.area&&e.add(t.area);return Object.values(this.hass?.areas||{}).filter(t=>!e.has(t.area_id)).sort((e,t)=>(e.name||"").localeCompare(t.name||""))}_openDeviceInbox(){this._deviceInboxReturn=null,this._deviceInbox=this._deviceInbox||{tab:"on_plan",search:"",showEntities:!1,onlyNew:!1,limit:100}}_closeMarkerDialog(){if(this._markerDialog=null,this._deviceInboxReturn){const e={...this._deviceInboxReturn};this._deviceInbox=e,this._deviceInboxReturn=null,e.anchor&&this.updateComplete.then(()=>requestAnimationFrame(()=>{const t=`.device-inbox-row[data-binding="${CSS.escape(e.anchor)}"]`;this.renderRoot.querySelector(t)?.scrollIntoView({block:"nearest"})}))}}_deviceInboxCandidates(e){return gp({hass:this._planHass,devices:this._devices,markers:this._markers,showEntities:e,labels:{device:this._t("marker.sub_device"),z2mGroup:this._t("marker.sub_z2m_group"),group:this._t("marker.sub_group"),helper:this._t("marker.sub_helper"),entity:this._t("marker.sub_entity")}})}_deviceInboxRows(){const e=this._deviceInbox||this._deviceInboxReturn,t=!!e?.showEntities,i=[this._haRegistry.revision,this._cfgRev,this._cfgEpoch,this._regSignature,this._newSyncKey,t?1:0,this._showAll?1:0,ra(this.hass,this._config?.language)].join("|");if(this._deviceInboxMemo?.key===i)return this._deviceInboxMemo.rows;const s=this._deviceInboxCandidates(t),n=new Set(s.map(e=>e.value));for(const e of this._markers)e.binding&&"virtual"!==e.binding&&n.add(e.binding);for(const e of this._devices)e.bindingKind&&"virtual"!==e.bindingKind&&e.bindingRef&&n.add(`${e.bindingKind}:${e.bindingRef}`);const o=new Map;for(const e of n)o.set(e,this._bindingStatus(e));const a=this._areaToSpace,r={};for(const[e,t]of Object.entries(this.hass?.areas||{}))r[e]=a[e]?.room?.name||t?.name||e;for(const[e,t]of Object.entries(a))r[e]=t.room.name||r[e]||e;const l=Object.fromEntries(this._model.map(e=>[e.id,e.title])),c=Object.fromEntries(Object.entries(a).map(([e,t])=>[e,t.space])),h={},d=new Map;for(const[e,t]of Object.entries(this._fullRegistryHass.entities||{})){const i=String(t?.platform||"").trim();if(i&&(h[`entity:${e}`]=i),i&&t?.device_id){const e=d.get(t.device_id)||new Set;e.add(i),d.set(t.device_id,e)}}for(const[e,t]of d)h[`device:${e}`]=[...t].sort().join(", ");const p={};for(const[e,t]of Object.entries(this._fullRegistryHass.devices||{})){const i=`device:${e}`,s=d.get(e)||new Set,n=Array.isArray(t?.identifiers?.[0])?String(t.identifiers[0][0]||""):"",o=[n,...s].some(e=>this._excluded.has(e));"service"===t?.entry_type?p[i]="service_entry":o?p[i]="excluded_integration":"Group"===t?.model?p[i]="grouped_light":/scene/i.test(t?.model||"")?p[i]="excluded_domain":(/bridge/i.test(`${t?.model||""}${t?.name||""}`)||"myheat"===n&&t?.via_device_id)&&(p[i]="represented_by_parent")}const u=function(e){const{devices:t,markers:i,candidates:s,statuses:n,newDeviceIds:o,showHiddenOnPlan:a,areaNames:r={},spaceNames:l={},spaceByArea:c={},integrationByBinding:h={},reasonByBinding:d={}}=e,p=new Map;for(const e of t)!e.virtual&&e.bindingKind&&"virtual"!==e.bindingKind&&e.bindingRef&&p.set(`${e.bindingKind}:${e.bindingRef}`,e);const u=new Map,_=new Map;for(const e of i)e?.binding&&"virtual"!==e.binding&&(e.removed?_.set(e.binding,e):u.set(e.binding,e));const m=new Map(s.map(e=>[e.value,e])),g=new Set([...p.keys(),...u.keys(),...m.keys(),...[..._.keys()].filter(e=>m.has(e))]),f=[];for(const e of g){const t=p.get(e),i=u.get(e),s=i?void 0:_.get(e),g=m.get(e);let v;if(s&&g)v="readd";else if(!0===i?.hidden)v="hidden";else if(t||i)v="on_plan";else{if(!g)continue;v="available"}const b=t?.bindingStatus||n.get(e)||fp,y=i||s,w=vp(e),k=t?.area||g?.areaId||y?.area||"",x=t?.space||y?.space||c[k]||"",$=t?.name||y?.name||g?.label||e,S=t?.model||y?.model||g?.model||"",M=!!g?.parentDeviceId&&p.has(`device:${g.parentDeviceId}`),C="readd"===v?"removed":"hidden"===v?i&&bp(i)?d[e]||"automatic_hidden":"manual_hidden":"on_plan"===v?i?"visible_explicit":"visible_auto":d[e]||(M?"represented_by_parent":k&&x?"available":"no_bound_room"),D=!!t&&(!t.hidden||a),P="active"===b.kind,T=D&&(P||"ha_disabled"===b.kind&&a),I=[$,S,h[e],r[k],l[x],e,g?.sub].filter(Boolean).join(" ").toLocaleLowerCase();f.push({key:e,binding:e,category:v,status:b,reason:C,deviceId:t?.id,markerId:y?.id,name:$,icon:t?.icon||y?.icon||("entity"===w?"mdi:code-braces":"mdi:devices"),model:S,integration:h[e]||"",areaId:k,areaName:r[k]||"",spaceId:x,spaceName:l[x]||"",kind:w,isNew:!!t&&o.has(t.id),searchText:I,canFind:T,canEdit:!!t||!!i,canHide:"on_plan"===v&&P,canShow:"hidden"===v&&P,canAdd:("available"===v||"readd"===v)&&P})}const v=e=>"active"===e.status.kind?1:0;return f.sort((e,t)=>e.category.localeCompare(t.category)||Number(t.isNew)-Number(e.isNew)||v(e)-v(t)||e.name.localeCompare(t.name)||e.binding.localeCompare(t.binding))}({devices:this._devices,markers:this._markers,candidates:s,statuses:o,newDeviceIds:this._newIds,showHiddenOnPlan:this._showAll,areaNames:r,spaceNames:l,spaceByArea:c,integrationByBinding:h,reasonByBinding:p});return this._deviceInboxMemo={key:i,rows:u},u}_deviceForInboxRow(e){const t=e.deviceId?this._devices.find(t=>t.id===e.deviceId):null;if(t)return t;const i=e.markerId?this._markers.find(t=>t.id===e.markerId):null;return!i||i.removed?null:{id:i.id,name:e.name,model:e.model,area:e.areaId,space:e.spaceId||this._space,hidden:!0===i.hidden||"ha_disabled"===e.status.kind,userHidden:!0===i.hidden,bindingStatus:e.status,icon:e.icon,entities:"active"===e.status.kind?e.status.enabledEntityIds:[],allEntities:e.status.allEntityIds,primary:"active"===e.status.kind?e.status.enabledEntityIds[0]:void 0,marker:i,bindingKind:e.kind,bindingRef:e.binding.slice(e.binding.indexOf(":")+1),pdfs:i.pdfs||[]}}_openInboxMarker(e,t=!1){const i=this._deviceInbox;if(i){if(this._deviceInboxReturn={...i,anchor:e.key},this._deviceInbox=null,!t){const t=this._deviceForInboxRow(e);return void(t?this._openMarkerDialog(t):this._closeMarkerDialog())}this._openMarkerDialog(),this._markerDialog?this._markerDialog={...this._markerDialog,bindingMode:"ha",binding:e.binding,bindingOpen:!1,showEntities:"entity"===e.kind,name:""}:this._closeMarkerDialog()}}async _setInboxHidden(e,t){const i=this._deviceInbox,s=this._serverCfg;if(!i||!s||i.busy||"active"!==e.status.kind)return;const n=s.markers||[],o=n.find(t=>!t.removed&&t.binding===e.binding);if(!t&&!o)return;const a=o?.id||Fi(e.binding,e.markerId,()=>`m_${Date.now().toString(36)}`),r=o?{...o,hidden:t}:{id:a,binding:e.binding,hidden:!0};s.markers=[...n.filter(t=>t.id!==a&&(t.binding!==e.binding||!0===t.removed)),r],this._deviceInbox={...i,busy:e.key,anchor:e.key};try{await this._saveConfigNow(),this._regSignature="",this._deviceInboxMemo=null,this._maybeRebuildDevices(),this._deviceInbox&&(this._deviceInbox={...this._deviceInbox,busy:void 0}),this._showToast(this._t("device_inbox.saved"))}catch(e){this._serverCfg===s&&(s.markers=n),this._deviceInbox&&(this._deviceInbox={...this._deviceInbox,busy:void 0}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}_findInboxDevice(e){if(!e.canFind)return;const t=this._deviceForInboxRow(e);if(!t)return;if(this._deviceInbox=null,t.space&&t.space!==this._space){if(!this._commitSpace(t.space))return;this._restoreZoom()}const i=()=>{const e=this._devices.find(e=>e.id===t.id)||t,i=this._pos(e);this._applyView(this._zoom,i.x,i.y),this._selId=e.id,this.requestUpdate(),window.setTimeout(()=>{this._selId===e.id&&(this._selId=null,this.requestUpdate())},1500)};requestAnimationFrame(()=>requestAnimationFrame(i))}_deviceInboxTabKey(e){if("ArrowLeft"!==e.key&&"ArrowRight"!==e.key)return;const t=this._deviceInbox;if(!t)return;const i=["on_plan","available","hidden","readd"],s="ArrowRight"===e.key?1:-1,n=(i.indexOf(t.tab)+s+i.length)%i.length;this._deviceInbox={...t,tab:i[n],limit:100,onlyNew:!1},e.preventDefault()}_openMarkerDialog(e){if(this._vacAllCamerasFor=null,this._vacAllCameraCache=null,e&&this._ackNewDevice(e.id),this._norm)if(e){const t=e.marker,i=Object.prototype.hasOwnProperty.call(t||{},"is_light"),s=Object.prototype.hasOwnProperty.call(t||{},"light_entity"),n=Object.prototype.hasOwnProperty.call(t||{},"glow_color"),o=Object.prototype.hasOwnProperty.call(t||{},"value_badge"),a=Object.prototype.hasOwnProperty.call(t||{},"tap_action"),r=Object.prototype.hasOwnProperty.call(t||{},"toggle_entity"),l=ks(t?.glow_color),c=this._devicePresentation(e,!0).valueBadge,h=qo(this._planHass,e,this._devices),d=Wo(this._planHass,e,h);this._markerDialog={devId:e.id,name:e.name,binding:"virtual"===e.bindingKind?"virtual":e.bindingKind+":"+e.bindingRef,bindingMode:"virtual"===e.bindingKind?"virtual":"ha",bindingOpen:!1,showEntities:"entity"===e.bindingKind&&!!this._fullRegistryHass.entities[e.bindingRef||""]?.device_id,bindingFilter:"",icon:e.marker?.icon||"",autoIcon:e.icon||"",display:Bi(e.marker?.display),rippleColor:Ie(e.marker?.ripple_color,""),rippleSize:Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,size:Number(e.marker?.size)>0?Number(e.marker.size):1,angle:Number(e.marker?.angle)||0,tapAction:Op(e.marker?.tap_action,e.primary?.split(".")[0]),tapActionTouched:!1,originalHasTapAction:a,originalTapAction:e.marker?.tap_action,tapHintAnnouncement:"",toggleEntity:t?.toggle_entity||"",toggleEntityTouched:!1,originalHasToggleEntity:r,originalToggleEntity:t?.toggle_entity,tapTarget:e.marker?.tap_target||"",tapConfirm:!0===e.marker?.tap_confirm,runFilter:"",controls:Zn(e.marker?.binding,e.marker?.controls,e.entities),controlsFilter:"",lightRole:!0===t?.is_light?"always":!1===t?.is_light?"never":"auto",lightRoleTouched:!1,originalHasIsLight:i,originalIsLight:t?.is_light,lightEntity:t?.light_entity||"",lightEntityTouched:!1,originalHasLightEntity:s,originalLightEntity:t?.light_entity,glowMode:null!=l?.bri?"fixed":l?"color":"auto",glowColor:l?.c||this._fillColors.glow_light.c,glowBrightness:Math.max(1,Math.round(100*(l?.bri??1))),glowColorDrafted:!!l,glowBrightnessDrafted:null!=l?.bri,glowTouched:!1,originalHasGlowColor:n&&(!!l||null===t?.glow_color),originalGlowColor:l||(null===t?.glow_color?null:void 0),valueBadgeEnabled:o?!0===t?.value_badge?.enabled:!!c,valueBadgeSource:t?.value_badge?.source||c?.source||d,valueBadgePosition:t?.value_badge?.position||c?.position||"right",valueBadgeTouched:!1,originalHasValueBadge:o,originalValueBadge:t?.value_badge,useClimateTemp:!0===e.marker?.use_climate_temp,glowRadius:Number(e.marker?.glow_radius_cm)>0?String(this._imperial?Math.round(Number(e.marker.glow_radius_cm)/30.48*10)/10:Math.round(Number(e.marker.glow_radius_cm))/100):"",model:e.model||"",link:e.link||"",description:e.description||"",pdfs:[...e.pdfs||[]],room:e.marker?.room_id?e.space+"#@"+e.marker.room_id:e.space&&e.area?e.space+"#"+e.area:"",hideFromPlan:!0===e.marker?.hidden,busy:!1}}else this._markerDialog={name:"",binding:"virtual",bindingMode:"virtual",bindingOpen:!1,showEntities:!1,bindingFilter:"",icon:"",autoIcon:"",display:"badge",rippleColor:"",rippleSize:1.5,size:1,angle:0,tapAction:"info",tapActionTouched:!1,originalHasTapAction:!1,originalTapAction:void 0,tapHintAnnouncement:"",toggleEntity:"",toggleEntityTouched:!1,originalHasToggleEntity:!1,originalToggleEntity:void 0,tapTarget:"",tapConfirm:!1,runFilter:"",controls:[],controlsFilter:"",lightRole:"auto",lightRoleTouched:!1,originalHasIsLight:!1,originalIsLight:void 0,lightEntity:"",lightEntityTouched:!1,originalHasLightEntity:!1,originalLightEntity:void 0,glowMode:"auto",glowColor:this._fillColors.glow_light.c,glowBrightness:100,glowColorDrafted:!1,glowBrightnessDrafted:!1,glowTouched:!1,originalHasGlowColor:!1,originalGlowColor:void 0,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgePosition:"right",valueBadgeTouched:!1,originalHasValueBadge:!1,originalValueBadge:void 0,useClimateTemp:!1,glowRadius:"",model:"",link:"",description:"",pdfs:[],room:"",hideFromPlan:!1,busy:!1,uploadId:"up_"+Date.now().toString(36)+Math.random().toString(36).slice(2,6)};else this._showToast(this._t("toast.marker_needs_server"))}_runCandidates(){const e=[];for(const t of Gi)for(const[i,s]of Object.entries(this.hass.states))i.startsWith(t+".")&&this._planEntityAvailable(i)&&e.push({value:i,label:s?.attributes?.friendly_name||i,sub:this._t("run."+t)});return e.sort((e,t)=>e.sub.localeCompare(t.sub)||e.label.localeCompare(t.label))}_bindingCandidates(){const e=gp({hass:this._planHass,devices:this._devices,markers:this._markers,showEntities:!!this._markerDialog?.showEntities,currentBinding:this._markerDialog?.binding,currentDeviceId:this._markerDialog?.devId,labels:{device:this._t("marker.sub_device"),z2mGroup:this._t("marker.sub_z2m_group"),group:this._t("marker.sub_group"),helper:this._t("marker.sub_helper"),entity:this._t("marker.sub_entity")}}),t=(this._markerDialog?.bindingFilter||"").toLowerCase().trim(),i=t?e.filter(e=>(e.label+" "+e.sub+" "+e.value).toLowerCase().includes(t)):e;return i.sort((e,t)=>e.label.localeCompare(t.label)),i.slice(0,200)}_physicalBodiesR(e=this._spaceModel()){if(!e)return[];const t=`${e.id}|${this._cfgEpoch}|${this._cellCm}|${this._gridPitch}`;if(this._physicalBodiesCache?.key===t)return this._physicalBodiesCache.all;const i=ch(e,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(e));return this._physicalBodiesCache={key:t,...i},i.all}_rawPhysicalBodiesR(e=this._spaceModel()){if(!e)return[];this._physicalBodiesR(e);const t=this._physicalBodiesCache;return t?[...t.drafts,...t.partitions,...t.columns]:[]}_cleanFloor(e,t,i=this._spaceModel()){if(!i)return{floor:t,geom:null,path:"",area:mh([[[...t,t[0]]]])};const s=e.id||`#${i.rooms.indexOf(e)}`,n=`${i.id}|${this._cfgEpoch}|${s}`;if(!this._resize.preview){const e=gv(this._cleanFloorCache,n);if(e.hit)return e.value}const o=t.map(e=>e[0]),a=t.map(e=>e[1]),r=[Math.min(...o),Math.min(...a),Math.max(...o),Math.max(...a)],l=this._physicalBodiesR(i).filter(e=>{const t=e.map(e=>e[0]),i=e.map(e=>e[1]);return Math.max(...t)>=r[0]&&Math.min(...t)<=r[2]&&Math.max(...i)>=r[1]&&Math.min(...i)<=r[3]}),c=l.length?_h(t,l):null,h={floor:t,geom:c,path:c?nh(c):"",area:mh(c||[[[...t,t[0]]]])};return this._resize.preview||fv(this._cleanFloorCache,n,h,600),h}_autoIconForBinding(e){if("virtual"===e)return"mdi:map-marker";const[t,i]=e.split(":");if(!i)return"";const s=this._fullRegistryHass,n=this._bindingStatus(e),o="active"===n.kind?n.enabledEntityIds:n.allEntityIds;if("device"===t){const e=s.devices?.[i];if(!e)return"mdi:help-circle";const t=o;return t.some(e=>e.startsWith("lock."))?"mdi:lock":yo(s,e.name_by_user||e.name||"",e.model,t,this._iconRules)}if("entity"===t){const e=s.entities?.[i],t=this.hass.states?.[i],n=e?.name||t?.attributes?.friendly_name||i;return i.startsWith("lock.")?"mdi:lock":yo(s,n,"",[i],this._iconRules)}return""}_allRoomsFlat(){const e=[];for(const t of this._serverCfg?.spaces||[])for(const i of t.rooms||[])i.area?e.push({value:t.id+"#"+i.area,label:(t.title||t.id)+" · "+i.name}):i.id&&e.push({value:t.id+"#@"+i.id,label:(t.title||t.id)+" · "+i.name+" · "+this._t("marker.subarea")});return e}_errText(e){if(!e)return this._t("err.unknown");if("string"==typeof e)return e;if("invalid_passage_fields"===e.code){const t=String(e.message||e.error||"").match(/space=([^;]*);\s*opening=([^;]*);\s*fields=([^;]*)/);if(t){const e=this._serverCfg?.spaces?.find(e=>String(e.id)===t[1]),i={contact:"opening.contact_label",lock:"opening.lock_label",invert:"opening.invert",flip_h:"opening.flip_h",flip_v:"opening.flip_v"},s=t[3].split(",").filter(Boolean).map(e=>i[e]?this._t(i[e]):e).join(", ");return this._t("opening.invalid_passage_fields",{room:e?.title||t[1],fields:s})}}if("invalid_partition_opening_jamb_margin"===e.code){const t=String(e.message||e.error||"").match(/margin_cm=([^;]*)/),i=t?Number(t[1]):NaN;if(Number.isFinite(i))return this._t("opening.partition_jamb_margin",{distance:li(i,this._imperial)})}if(e.message)return e.message;if(e.error)return e.error;if(null!=e.code)return this._t("err.code",{code:e.code});try{return JSON.stringify(e)}catch{return String(e)}}_backupErrorText(e){const t=e?.code??e?.error;if("string"==typeof t){const e=`backup.error.${t}`,i=this._t(e);if(i!==e)return i}return this._errText(e)}async _pickMarkerFiles(e){const t=e.target,i=t.files?[...t.files]:[];if(t.value="",!i.length||!this._markerDialog)return;const s=this._markerDialog.uploadId||this._markerDialog.devId||"new",n=[];for(const e of i)try{const t=new FormData;t.append("marker_id",s),t.append("file",e,e.name);const i=this.hass?.fetchWithAuth?await this.hass.fetchWithAuth("/api/houseplan/upload",{method:"POST",body:t}):await fetch("/api/houseplan/upload",{method:"POST",body:t,headers:this.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.hass.auth.data.access_token}`}:{}}),o=await i.json().catch(()=>({}));if(!i.ok||o.error){const e={too_large:this._t("err.too_large",{mb:o.max_mb||50}),bad_ext:this._t("err.bad_ext"),unauthorized:this._t("err.unauthorized")};throw new Error(e[o.error]||o.error||"HTTP "+i.status)}n.push({name:o.name||e.name,url:o.url})}catch(t){this._showToast(this._t("toast.file_failed",{name:e.name,err:this._errText(t)}))}n.length&&this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:[...this._markerDialog.pdfs,...n]},this._showToast(this._t("toast.files_attached",{n:n.length})))}_removeMarkerPdf(e){this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:this._markerDialog.pdfs.filter(t=>t.url!==e)})}_markerLightFields(e){const t={};if(e.lightRoleTouched?"always"===e.lightRole?t.is_light=!0:"never"===e.lightRole&&(t.is_light=!1):e.originalHasIsLight&&(t.is_light=e.originalIsLight??null),e.lightEntityTouched?e.lightEntity&&(t.light_entity=e.lightEntity):e.originalHasLightEntity&&(t.light_entity=e.originalLightEntity??null),e.glowTouched){if("auto"!==e.glowMode){const i={c:Ie(e.glowColor,this._fillColors.glow_light.c)};"fixed"===e.glowMode&&(i.bri=Math.max(.01,Math.min(1,Math.round(e.glowBrightness)/100))),t.glow_color=i}}else e.originalHasGlowColor&&(t.glow_color=e.originalGlowColor??null);return t}_markerTapActionFields(e){return e.tapActionTouched?{tap_action:e.tapAction||null}:e.originalHasTapAction?{tap_action:e.originalTapAction??null}:{}}_markerToggleEntityFields(e){return(t={touched:e.toggleEntityTouched,originalHas:e.originalHasToggleEntity,original:e.originalToggleEntity,value:e.toggleEntity}).touched?t.value?{toggle_entity:t.value}:{}:t.originalHas?{toggle_entity:t.original??null}:{};var t}async _saveMarker(){const e=this._markerDialog;if(!e||e.busy)return;const t=this._effectiveMarkerTapAction(e);if("ha"===e.bindingMode&&(!e.binding||"virtual"===e.binding))return;if("virtual"===e.binding&&!e.name.trim())return void this._showToast(this._t("toast.virtual_name_required"));if("run"===t&&!e.tapTarget)return void this._showToast(this._t("toast.run_target_required"));if(e.valueBadgeTouched&&e.valueBadgeEnabled&&!e.valueBadgeSource)return void this._showToast(this._t("toast.value_badge_source_required"));if("ha"===e.bindingMode){const t=this._bindingStatus(e.binding),i=e.devId?this._markers.find(t=>t.id===e.devId):null,s=!i||i.binding!==e.binding;if("active"!==t.kind&&s)return void this._showToast(this._t("ha_disabled"===t.kind?"toast.ha_disabled_add":"toast.ha_binding_unverified"));if("ha_disabled"===t.kind&&!0===i?.hidden&&!e.hideFromPlan)return this._markerDialog={...e,hideFromPlan:!0},void this._showToast(this._t("entity"===t.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device"))}const i=this._serverCfg;if(!i)return;const s=i.markers||[],n=js(e.room);let o=n?.space||null;const a=n?.area||null,r=n?.roomId||null,l=Fi(e.binding,e.devId,()=>"v_"+Date.now().toString(36)),c=e.devId,h=c?this._devices.find(e=>e.id===c):null,d=n?.space||h?.space||null,p=d?this._spaceModelById(d):this._spaceModel();if(!p)return;const u=p.id;"virtual"!==e.binding||o||(o=u),this._markerDialog={...e,busy:!0};try{const n="virtual"===e.binding?[]:s.filter(t=>t.removed&&t.binding===e.binding).map(e=>e.id),d=n.length>0,_=Zn(e.binding,e.controls,this._bindingEntities(e.binding)),m=s.find(e=>e.id===l||e.id===c)?.vacuum||null,g={id:l,vacuum:m,binding:e.binding,name:e.name.trim()||null,icon:e.icon||null,display:"badge"!==e.display?e.display:null,ripple_color:"icon_ripple"===e.display&&e.rippleColor?e.rippleColor:null,ripple_size:"icon_ripple"===e.display&&1.5!==e.rippleSize?e.rippleSize:null,size:1!==e.size?e.size:null,angle:e.angle?e.angle:null,...this._markerTapActionFields(e),...this._markerToggleEntityFields(e),tap_target:"run"===t&&e.tapTarget||null,tap_confirm:!!e.tapConfirm||null,controls:_.length?_:null,...this._markerLightFields(e),...this._markerValueBadgeFields(e),use_climate_temp:!!e.useClimateTemp||null,glow_radius_cm:(()=>{const t=mv(e.glowRadius);return null==t||t<=0?null:Math.round(this._imperial?30.48*t:100*t)})(),model:e.model.trim()||null,link:e.link.trim()||null,description:e.description.trim()||null,pdfs:e.pdfs,hidden:!!e.hideFromPlan};("virtual"===e.binding||e.room)&&(g.space=o,g.area=a,g.room_id=r);const f=h?.marker?.room_id??null,v=!!e.room&&null!=h&&(h.space!==o||h.area!==a||f!==r);let b=!1;const y=e.uploadId||c;if(y&&y!==l&&g.pdfs?.length)try{const e=await this.hass.callWS({type:"houseplan/files/migrate",from_id:y,to_id:l}),t=e?.mapping||{};g.pdfs=function(e,t,i,s){if(!t||!i||t===i)return e;const n="/files/"+t+"/",o="/files/"+i+"/";return e.map(e=>{if(!e.url.includes(n))return e;const t=e.url.split(n)[1]||"",[i,a]=[t.split("?")[0],t.includes("?")?"?"+t.split("?")[1]:""];if(s){const t=s[decodeURIComponent(i)]??s[i];return t?{...e,url:e.url.split(n+i)[0]+o+encodeURIComponent(t)+a}:e}return{...e,url:e.url.split(n).join(o)}})}(g.pdfs,y,l,t),b=Object.keys(t).length>0}catch(e){this._showToast(this._t("toast.files_migrate_failed",{err:this._errText(e)}))}i.markers=s,c&&c!==l&&(i.markers=function(e,t,i){if(!t||!i||t===i)return[...e];const s=`marker:${t}`,n=`marker:${i}`;return e.map(e=>{const t=Array.isArray(e.controls)?e.controls.map(e=>e===s?n:e):e.controls,i="derived_marker_state"===e.value_badge?.source?.kind&&e.value_badge.source.ref===s?{...e.value_badge,source:{...e.value_badge.source,ref:n}}:e.value_badge;return t===e.controls&&i===e.value_badge?e:{...e,controls:t,value_badge:i}})}(i.markers,c,l)),c&&c!==l&&"derived_marker_state"===g.value_badge?.source?.kind&&g.value_badge.source.ref===`marker:${c}`&&(g.value_badge.source={kind:"derived_marker_state",ref:`marker:${l}`}),i.markers=i.markers.filter(e=>e.id!==l&&e.id!==c&&("virtual"===g.binding||e.binding!==g.binding)),i.markers.push(g);let w=null;const k=c?this._layout[c]:null,x=k?{s:k.s||h?.space||this._space,x:k.x,y:k.y}:c&&h&&this._defPos[c]?this._normPos(h.space,this._defPos[c].x,this._defPos[c].y):null;if(!d&&x&&x.s===u)l===c&&this._layout[l]&&!v||(w={s:x.s,x:x.x,y:x.y},this._layout={...this._layout,[l]:w});else if(d||!this._layout[l]||v){let e=p.vb[0]+p.vb[2]/2,t=p.vb[1]+p.vb[3]/2;const i=r?p.rooms.find(e=>e.id===r):a?p.rooms.find(e=>e.area===a):void 0;i&&([e,t]=this._roomCenter(i)),w=this._normPos(u,e,t),this._layout={...this._layout,[l]:w}}if(await this._saveConfigNow(),w){const e=hl(w);this._layout={...this._layout,[l]:e},this._noteLayoutRev(await this.hass.callWS({type:"houseplan/layout/update",device_id:l,pos:e}))}const $=new Set(n);c&&c!==l&&$.add(c),$.delete(l);for(const e of $)delete this._layout[e],await this.hass.callWS({type:"houseplan/layout/delete",device_id:e}).then(e=>this._noteLayoutRev(e)).catch(()=>{});b&&y&&await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:y}).catch(()=>{}),this._closeMarkerDialog(),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_saved"))}catch(e){this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}async _deleteMarker(){const e=this._markerDialog;if(!e||e.busy||!e.devId)return;const t=e.devId?this._devices.find(t=>t.id===e.devId):null,i=this._markers.find(t=>t.id===e.devId);if(!t&&!i)return;const s=e.name||this._t("device.fallback");if(!confirm(this._t("confirm.remove_marker",{name:s})))return;const n=this._serverCfg;n.markers=n.markers||[];const o=n.markers,a=t?.id||i.id,r=t?"virtual"===t.bindingKind?"virtual":t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:"":i.binding;if(!r)return;const l=function(e,t,i,s){const n=new Set([t]),o=e.filter(e=>{const o=e.id===t||!s&&e.binding===i;return o&&n.add(e.id),!o});return{markers:s?o:[...o,{id:t,binding:i,removed:!0,hidden:!0}],cleanupIds:n}}(n.markers,a,r,"virtual"===r);var c,h;n.markers=(c=l.markers,h=l.cleanupIds,c.map(e=>{if(!Array.isArray(e.controls))return e;const t=e.controls.filter(e=>!("string"==typeof e&&e.startsWith("marker:")&&h.has(e.slice(7))));return t.length===e.controls.length?e:{...e,controls:t.length?t:null}}));const d=l.cleanupIds;this._markerDialog={...e,busy:!0};try{await this._saveConfigNow();for(const e of d){delete this._layout[e],delete this._defPos[e],this._dirtyPos.delete(e),this._sentPos.delete(e);const t=this._activityRt.get(e);t&&clearTimeout(t.timer),this._activityRt.delete(e),this._vacRt.delete(e),delete this._vacSrvTrails[e],await this.hass.callWS({type:"houseplan/layout/delete",device_id:e}).then(e=>this._noteLayoutRev(e)).catch(()=>{}),await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:e}).catch(()=>{}),await this.hass.callWS({type:"houseplan/trail/delete",marker_id:e}).catch(()=>{})}this._deviceInboxReturn&&(this._deviceInboxReturn={...this._deviceInboxReturn,tab:"readd",anchor:r}),this._closeMarkerDialog(),this._infoCard?.id===a&&this._closeInfoCard(),this._selId===a&&(this._selId=null),this._drag?.id===a&&(this._drag=null),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_removed"))}catch(e){this._serverCfg===n&&(n.markers=o),this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(e)}))}}_normPos(e,t,i){return{s:e,x:t/Pv,y:i/Pv}}_openSpaceDialog(e,t){if(this._serverStorage&&this._serverCfg)if("edit"===e){const i=this._serverCfg.spaces.find(e=>e.id===t);if(!i)return;const s=cs(i),n=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?rs(i.settings.custom_fill):null,o="none"===s.fill?{...n||as,a:0}:n;this._spaceDialog={mode:e,spaceId:t,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:s.showBorders,showNames:s.showNames,zeroWallStyle:O_(i),displayTouched:!0,hideDecor:s.hideDecor,hideOpenings:s.hideOpenings,roomColor:s.color,roomOpacity:s.opacity,fillMode:"none"===s.fill?"custom":s.fill,customFill:o,glowEnabled:s.glow,bgColor:s.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:Pr({},i.settings),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:s.tempMin,tempMax:s.tempMax,showLqi:s.showLqi??this._config?.show_signal??!0,cardFontScale:s.cardFontScale,labelTemp:s.labelTemp,labelHum:s.labelHum,labelLqi:s.labelLqi,labelLight:s.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:Sh(Number(i.cell_cm)>0?Number(i.cell_cm):5,this._imperial),cellCmTouched:!1,busy:!1}}else this._spaceDialog={mode:e,title:"",planUrl:null,planFile:null,...Gd(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:ns,roomOpacity:os,fillMode:"custom",customFill:{...as,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:20,tempMax:25,showLqi:this._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:$h(this._imperial),cellCmInput:Sh($h(this._imperial),this._imperial),cellCmTouched:!1,busy:!1};else this._showToast(this._t("toast.integration_missing"))}async _pickPlanFile(e){const t=e.target,i=t.files?.[0];if(!i||!this._spaceDialog)return;const s={"image/svg+xml":"svg","image/png":"png","image/jpeg":"jpg","image/webp":"webp"}[i.type]||(i.name.toLowerCase().endsWith(".svg")?"svg":"");if(!s)return void this._showToast(this._t("toast.plan_formats"));const n=new Uint8Array(await i.arrayBuffer());let o="";for(let e=0;e{const t=new Image;t.onload=()=>e(t.naturalWidth&&t.naturalHeight?t.naturalWidth/t.naturalHeight:1.414),t.onerror=()=>e(1.414),t.src=r});URL.revokeObjectURL(r),this._spaceDialog={...this._spaceDialog,planFile:{ext:s,b64:a,aspect:l,name:i.name}}}_useServerPlan(e){const t=this._spaceDialog;t&&(this._spaceDialog={...t,planUrl:e,planFile:null,pickSaved:!1,savedAspect:void 0},this._aspectJob=this._readPlanAspect(e))}async _readPlanAspect(e){for(let t=0;t<40;t++){const t=this._display(e);if(t){const i=await new Promise(e=>{const i=new Image;i.onload=()=>e(i.naturalWidth&&i.naturalHeight?i.naturalWidth/i.naturalHeight:0),i.onerror=()=>e(0),i.src=t}),s=this._spaceDialog;return s&&s.planUrl===e&&Number.isFinite(i)&&i>0?(this._spaceDialog={...s,savedAspect:i},i):0}if(await new Promise(e=>setTimeout(e,150)),this._spaceDialog?.planUrl!==e)return 0}return 0}async _deleteServerPlan(e){if(confirm(this._t("confirm.delete_plan",{name:e})))try{await this.hass.callWS({type:"houseplan/plans/delete",name:e});const t=this._spaceDialog;t?.saved&&(this._spaceDialog={...t,saved:t.saved.filter(t=>t.name!==e)})}catch(e){this._showToast(this._t("toast.plan_delete_failed",{err:this._errText(e)}))}}_renderServerPlans(e){if(e.savedBusy)return q`
${this._t("space.loading")}
`;const t=e.saved||[];if(!t.length)return q`
${this._t("space.no_saved")}
`;return q`
${t.map(t=>q`
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 55280d18..576f63e5 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -12,7 +12,7 @@ - The Device editor now has one searchable lifecycle catalog for devices on the plan, available bindings, hidden markers and bindings available to add again. It explains Home Assistant status separately, can find markers on the - plan, and keeps hide/show/add/re-add flows in one place + plan using the room names visible there, and keeps hide/show/add/re-add flows in one place ([#29](https://github.com/Matysh/houseplan-card/issues/29)). ## v1.68.1 — 2026-08-27 diff --git a/docs/CHANGELOG.ru.md b/docs/CHANGELOG.ru.md index fcf8bcfb..dde5ecf6 100755 --- a/docs/CHANGELOG.ru.md +++ b/docs/CHANGELOG.ru.md @@ -18,7 +18,7 @@ - В редакторе устройств появился единый каталог с поиском: устройства на плане, доступные привязки, скрытые маркеры и привязки для повторного добавления. Статус Home Assistant объясняется отдельно, а - поиск на плане, скрытие, показ и повторное добавление собраны в одном + поиск использует видимые на плане имена комнат; скрытие, показ и повторное добавление собраны в одном месте ([#29](https://github.com/Matysh/houseplan-card/issues/29)). ## v1.68.1 — 2026-08-27 diff --git a/docs/images/06-device-editor.png b/docs/images/06-device-editor.png index 501d4f71..942cd481 100644 Binary files a/docs/images/06-device-editor.png and b/docs/images/06-device-editor.png differ diff --git a/docs/images/screenshots.json b/docs/images/screenshots.json index f02b032c..201c831e 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": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceFingerprint": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "captureScriptSha256": "ce2e9542fed9dade3085be87d16f69adb2ac8262893ad78ad966b1b9673f2983", "command": "npm run build && node demo/docs/capture.mjs", "scenarios": { @@ -14,7 +14,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "36223106c073f07d8cc3ecf8eaab37192ebb2687daba65c5c21047d0b7890de0" }, "view-touch": { @@ -25,7 +25,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "41e3ba67f8db0e98f26f484293af83ef937c369ca5ca6a59a3350d8954c906f4" }, "space-create": { @@ -36,7 +36,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "0dc024726327f60f4a9ceaf3044381691f81f1090af81d1812e870f22d9343ba" }, "room-contour-close": { @@ -47,7 +47,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "44cfaa95bd51e2cd628400e28db0ad8b2f0cd904385845bd402494f3f5c0d93c" }, "plan-context-tray": { @@ -58,7 +58,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "e0662429b423fb74151b583dcc2c8635b001b637d03bbf7a6b16aec46399c3f8" }, "device-editor": { @@ -69,8 +69,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", - "imageSha256": "d0ffd31ce80bfde21ab75da356a5fc1af38246f2b301030880320620c228d89d" + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", + "imageSha256": "827a5f0cd6f1c122a63a51d83569a2dbd87b70b3753266a3eb0a9f2986b1b911" }, "device-display-preview": { "file": "06-device-display-preview.png", @@ -80,7 +80,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "2cdabae1f89c3286e4fac0ce30f757ee1690b707ab8a5488748b7cd420626160" }, "background-editor": { @@ -91,7 +91,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "30147bb00a90eea7136b4cee30995f6e6a9217b5132f3e8d3ad7471413b1af8a" }, "room-card": { @@ -102,7 +102,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "029a3e69ec647a8a370d99e6bb7f9225833c526739076022f6b52ba54bff30ea" }, "device-info": { @@ -113,7 +113,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "78c24f3a8aef0c2bad01bebc701a8127c43fb40f1a298df7b769375bc5b081fa", + "sourceSha256": "6d094396ebd90fad934bace295f8eee0e6dafda27d8f38dd31beac954ff93880", "imageSha256": "dd492f53150b7149085daada5cce9eeae9bde9e7ea1d86679a54b3041f72f517" } } diff --git a/src/device-inbox.ts b/src/device-inbox.ts index 89f5f8df..abe9ae5b 100644 --- a/src/device-inbox.ts +++ b/src/device-inbox.ts @@ -152,7 +152,6 @@ export interface DeviceInboxRow { canHide: boolean; canShow: boolean; canAdd: boolean; - canOpenHa: boolean; } export interface DeviceInboxInput { @@ -242,7 +241,6 @@ export function buildDeviceInbox(input: DeviceInboxInput): DeviceInboxRow[] { const active = status.kind === 'active'; const canFind = isRendered && (active || (status.kind === 'ha_disabled' && showHiddenOnPlan)); - const canOpenHa = kind === 'device' || kind === 'entity'; const searchText = [ name, model, integrationByBinding[binding], areaNames[areaId], spaceNames[spaceId], binding, candidate?.sub, @@ -261,7 +259,6 @@ export function buildDeviceInbox(input: DeviceInboxInput): DeviceInboxRow[] { canHide: category === 'on_plan' && active, canShow: category === 'hidden' && active, canAdd: (category === 'available' || category === 'readd') && active, - canOpenHa, }); } const statusRank = (row: DeviceInboxRow): number => row.status.kind === 'active' ? 1 : 0; diff --git a/src/houseplan-card.ts b/src/houseplan-card.ts index 1c7614a4..96750179 100755 --- a/src/houseplan-card.ts +++ b/src/houseplan-card.ts @@ -14097,11 +14097,20 @@ class HouseplanCard extends LitElement { const statuses = new Map(); for (const binding of bindings) statuses.set(binding, this._bindingStatus(binding)); + const areaMap = this._areaToSpace; const areaNames: Record = {}; - for (const [id, area] of Object.entries(this.hass?.areas || {})) areaNames[id] = area?.name || id; + for (const [id, area] of Object.entries(this.hass?.areas || {})) { + areaNames[id] = areaMap[id]?.room?.name || area?.name || id; + } + // A room may keep a valid HA area reference even when the current user has + // only a limited area-registry snapshot. Its plan-visible name is still + // authoritative for the catalog and search. + for (const [id, target] of Object.entries(areaMap)) { + areaNames[id] = target.room.name || areaNames[id] || id; + } const spaceNames = Object.fromEntries(this._model.map((space) => [space.id, space.title])); const spaceByArea = Object.fromEntries( - Object.entries(this._areaToSpace).map(([area, value]) => [area, value.space]), + Object.entries(areaMap).map(([area, value]) => [area, value.space]), ); const integrationByBinding: Record = {}; const devicePlatforms = new Map>();