diff --git a/custom_components/houseplan/frontend/houseplan-assets.json b/custom_components/houseplan/frontend/houseplan-assets.json index bd14f84e..85519d88 100644 --- a/custom_components/houseplan/frontend/houseplan-assets.json +++ b/custom_components/houseplan/frontend/houseplan-assets.json @@ -1,215 +1,232 @@ { "schema": 1, - "fingerprint": "884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87", + "fingerprint": "0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64", "entry": "houseplan-card.js", "initialViewFiles": [ - "houseplan-assets/houseplan-card-CODdCIWj.js", + "houseplan-assets/houseplan-card-Bhpi71t0.js", "houseplan-card.js" ], - "initialViewGzipBytes": 299595, + "initialViewGzipBytes": 289760, "lazyFiles": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/de-3MG52yOu.js", - "houseplan-assets/editor-BWu14hMI.js", - "houseplan-assets/fr-w8JLXMgW.js", - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js", - "houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js", - "houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js", - "houseplan-assets/iso-scene-render-DXu89PMK.js", - "houseplan-assets/live-interaction-runtime-D5KHv4hp.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js", - "houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/de-D9kcw9QI.js", + "houseplan-assets/editor-CT75Pe-x.js", + "houseplan-assets/fr-D7aFj5IX.js", + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js", + "houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js", + "houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js", + "houseplan-assets/iso-scene-render-DQnNhHBF.js", + "houseplan-assets/live-interaction-runtime-DNx7W_iY.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js", + "houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js" ], - "lazyGzipBytes": 264984, + "lazyGzipBytes": 275381, "lazyEditorFiles": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/editor-BWu14hMI.js", - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/editor-CT75Pe-x.js", + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js" ], - "lazyEditorGzipBytes": 187115, + "lazyEditorGzipBytes": 197465, "lazyOnboardingFiles": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js" ], - "lazyOnboardingGzipBytes": 14328, + "lazyOnboardingGzipBytes": 14323, "lazyLocaleFiles": [ - "houseplan-assets/de-3MG52yOu.js", - "houseplan-assets/fr-w8JLXMgW.js" + "houseplan-assets/de-D9kcw9QI.js", + "houseplan-assets/fr-D7aFj5IX.js" ], - "lazyLocaleGzipBytes": 50178, + "lazyLocaleGzipBytes": 50237, "lazyIsometricFiles": [ - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/iso-scene-render-DXu89PMK.js" + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/iso-scene-render-DQnNhHBF.js" ], - "lazyIsometricGzipBytes": 13467, + "lazyIsometricGzipBytes": 13463, + "lazyFurnitureArtFiles": [ + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js" + ], + "lazyFurnitureArtGzipBytes": 10254, "files": [ { - "path": "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "sha256": "a1a1925a3567418f9f3e3b6541987ecf947ab98d672476a7ecd24468180ed8c7", + "path": "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "sha256": "4fea377a7c8633abf3a619c1fe8218df648376fa7effbd59a51f6102be3d01af", "rawBytes": 21592, - "gzipBytes": 7359, + "gzipBytes": 7357, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/de-3MG52yOu.js", - "sha256": "d85a610248c36842c44cc0b851c62f8aeb8e9431cd71c12b9900d8372b17f8dd", - "rawBytes": 84260, - "gzipBytes": 25368, + "path": "houseplan-assets/de-D9kcw9QI.js", + "sha256": "7371299fa8b9eeb09138acec33d1bf89a1ab890df042ed57b0bd2921c4c6fe29", + "rawBytes": 84392, + "gzipBytes": 25401, "isEntry": false, "imports": [], "dynamicImports": [] }, { - "path": "houseplan-assets/editor-BWu14hMI.js", - "sha256": "e793d2607239b96cbf314e36e4dd1c03017b5c9c7ae47b9d710dd7f47423011d", + "path": "houseplan-assets/editor-CT75Pe-x.js", + "sha256": "ab5edd25d3cd65ad5b312f897ed1a74e6a15331d99d531bf6c1165f6606cc5a3", "rawBytes": 3837, - "gzipBytes": 1589, + "gzipBytes": 1586, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/fr-w8JLXMgW.js", - "sha256": "78da22924a9d38e19e0787ce4c171bfba7df6c18f5460ccd4a2726bc1c415d8e", - "rawBytes": 86301, - "gzipBytes": 24810, + "path": "houseplan-assets/fr-D7aFj5IX.js", + "sha256": "2b946e58a3bee760c5e9cb67a1882456227345d4c091bb2452a0d5c2994e4120", + "rawBytes": 86420, + "gzipBytes": 24836, "isEntry": false, "imports": [], "dynamicImports": [] }, { - "path": "houseplan-assets/guard-BR4mAQsM.js", - "sha256": "31e7c009b3f724ca776293fef20b8ccc3d9f58d6afecb7d1d20be169e827d0a0", + "path": "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "sha256": "b939f374bee1fa1629e6be4bf9cb8d80051b1d13d03990f296dcc77d199a63e7", + "rawBytes": 33655, + "gzipBytes": 10254, + "isEntry": false, + "imports": [], + "dynamicImports": [] + }, + { + "path": "houseplan-assets/guard-BgTQLSGB.js", + "sha256": "dc0c81d0a7167dd708b220e776cab0ad48ec6a1b462918ff984acd347e7beae4", "rawBytes": 518, - "gzipBytes": 371, + "gzipBytes": 369, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/houseplan-card-CODdCIWj.js", - "sha256": "6011cb913b94cd0bb918c28928886a514af39a2162214423e467faf4b8ac31fe", - "rawBytes": 1072122, - "gzipBytes": 298799, + "path": "houseplan-assets/houseplan-card-Bhpi71t0.js", + "sha256": "5e21b20e0a8a762637f9d4360db79ae24d214e3c0ca1dbd59cca4d98116657a7", + "rawBytes": 1041955, + "gzipBytes": 288965, "isEntry": false, "imports": [], "dynamicImports": [ - "houseplan-assets/de-3MG52yOu.js", - "houseplan-assets/editor-BWu14hMI.js", - "houseplan-assets/fr-w8JLXMgW.js", - "houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js", - "houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js", - "houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js", - "houseplan-assets/iso-scene-render-DXu89PMK.js", - "houseplan-assets/live-interaction-runtime-D5KHv4hp.js" + "houseplan-assets/de-D9kcw9QI.js", + "houseplan-assets/editor-CT75Pe-x.js", + "houseplan-assets/fr-D7aFj5IX.js", + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js", + "houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js", + "houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js", + "houseplan-assets/iso-scene-render-DQnNhHBF.js", + "houseplan-assets/live-interaction-runtime-DNx7W_iY.js" ] }, { - "path": "houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js", - "sha256": "f124de9f93faf2aac6f6dcc8d7dfc5d40e7f4d887274843446f6aadb19dae52a", - "rawBytes": 640495, - "gzipBytes": 170365, + "path": "houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js", + "sha256": "06105a4f3e351baeea2b1dac6ec266c0f9bbf53cba6ff6516ec14ae424239f4c", + "rawBytes": 640655, + "gzipBytes": 170475, "isEntry": false, "imports": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/houseplan-card-CODdCIWj.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/houseplan-card-Bhpi71t0.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js" ], "dynamicImports": [ - "houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js" + "houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js" ] }, { - "path": "houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js", - "sha256": "7c7a9304466c21ec27ec027f5b3947e0c307538a016f20f4a407e9a43a81a18c", + "path": "houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js", + "sha256": "568a4fd971e96b124d91fae6f250e196cc6da4458e079bbbef0f27a76865fd81", "rawBytes": 28071, - "gzipBytes": 6969, + "gzipBytes": 6966, "isEntry": false, "imports": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js", - "sha256": "e6be2493d605f81e321c5ccd18cfba70dd86ed1816ea54deefa77be48c5e40dd", + "path": "houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js", + "sha256": "55c0f380d7812d8a5dd2cda810d7938eb3b7e2871c23d2d48efe965099b72ba7", "rawBytes": 11034, - "gzipBytes": 3732, + "gzipBytes": 3730, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js", - "houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js", + "houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/iso-scene-render-DXu89PMK.js", - "sha256": "96f20eb2404fd8f6c116de5bfff6a2b109bcd0a250e918eecdf0968df3c6ed9c", + "path": "houseplan-assets/iso-scene-render-DQnNhHBF.js", + "sha256": "49dc2cb9a2866fa2ed4a0cdd7acb5324efff7ddaac932c137bab2907b3f405e0", "rawBytes": 38593, - "gzipBytes": 13096, + "gzipBytes": 13094, "isEntry": false, "imports": [ - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/live-interaction-runtime-D5KHv4hp.js", - "sha256": "da0e12640b26ae3ebe05677db6238847813d5c8a7ec0dc7c7149922bc7deac66", + "path": "houseplan-assets/live-interaction-runtime-DNx7W_iY.js", + "sha256": "f6bc3e6f1d8e8528f93c10927e0f81f2cf8d08a3cdc364253cb436ccbc768cc5", "rawBytes": 5196, - "gzipBytes": 2129, + "gzipBytes": 2126, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/zigbee-topology-BUFPOnoy.js", - "sha256": "b497afdec2059b962c9f1a329e7f417650bfa5b28e684544c1ae415340fd208f", + "path": "houseplan-assets/zigbee-topology-B-C5QCCD.js", + "sha256": "f6ba19da3cacff0d88bddf98cf1ee260706ebe3c25c34cfbb24fc8b81c05528e", "rawBytes": 18961, - "gzipBytes": 7431, + "gzipBytes": 7424, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js", - "sha256": "ba8f56e776f1d47bea1c211a262154c31c4e13483857e3397ad9f951a8d7f8ce", + "path": "houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js", + "sha256": "71762abfaa68282eba7d584d945c9a9343775143161e8fe9f63bdc90dca1e883", "rawBytes": 3941, - "gzipBytes": 1765, + "gzipBytes": 1763, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js" ], "dynamicImports": [] }, { "path": "houseplan-card.js", - "sha256": "6e4f5e3ebbe429b4d330f3aff542aa4867fd87f0f249a5185c7429a00670b6d5", + "sha256": "76b219cf7fbba29d64cea0af6400a2ad9d07ab0e08dd46bcd00e4e0856350f0f", "rawBytes": 1183, - "gzipBytes": 796, + "gzipBytes": 795, "isEntry": true, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] } diff --git a/custom_components/houseplan/frontend/houseplan-assets/backdrop-pick-BnsHKWaS.js b/custom_components/houseplan/frontend/houseplan-assets/backdrop-pick-CV_as5Xh.js similarity index 99% rename from custom_components/houseplan/frontend/houseplan-assets/backdrop-pick-BnsHKWaS.js rename to custom_components/houseplan/frontend/houseplan-assets/backdrop-pick-CV_as5Xh.js index 19c56567..ba125214 100644 --- a/custom_components/houseplan/frontend/houseplan-assets/backdrop-pick-BnsHKWaS.js +++ b/custom_components/houseplan/frontend/houseplan-assets/backdrop-pick-CV_as5Xh.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{D as e,b as t,A as i,q as o,t as n,dp as r}from"./houseplan-card-CODdCIWj.js";function s(e){const t=e.visualViewport;return t&&Number.isFinite(t.width)&&Number.isFinite(t.height)?{left:Number(t.offsetLeft)||0,top:Number(t.offsetTop)||0,width:Math.max(0,Number(t.width)||0),height:Math.max(0,Number(t.height)||0)}:{left:0,top:0,width:e.innerWidth,height:e.innerHeight}}function a(e,t,i,o=7,n=8){const r=i.left+n,s=i.top+n,a=Math.max(r,i.left+i.width-n),l=Math.max(s,i.top+i.height-n),h=Math.max(0,a-r),d=Math.max(0,l-s),c=Math.min(Math.max(0,t.width),h),u=Math.min(Math.max(0,t.height),d);let p=e.left;p+c>a&&(p=e.right-c),p=Math.min(Math.max(r,p),Math.max(r,a-c));const g=e.bottom+o,_=e.top-o-u;let m="bottom",f=g;return g+u>l&&_>=s?(m="top",f=Math.min(Math.max(s,_),Math.max(s,l-u))):f=Math.min(Math.max(s,g),Math.max(s,l-u)),{left:Math.round(p),top:Math.round(f),side:m,maxWidth:Math.round(h),maxHeight:Math.round(d)}}class l{constructor(e,t,i){this.owner=e,this.name=t,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(e=!1){const t=this.window();return!e&&!!t&&function(e){const t=e.HTMLElement?.prototype;return"function"==typeof t?.showPopover&&"function"==typeof t?.hidePopover}(t)}get hasFallback(){return!!this.host}containsPath(e){return e.includes(this.owner)||!!this.host&&e.includes(this.host)}ownsActiveElement(){let e=this.owner.ownerDocument.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return!(!e||e!==this.owner&&!this.owner.shadowRoot?.contains(e)&&!this.root?.contains(e))}renderFallback(i,o){const n=this.ensureFallback();return n?(e(t`${i}`,n),n):null}surface(e,t){return t?this.owner.shadowRoot?.querySelector(e)||null:this.root?.querySelector(e)||null}destroy(){this.root&&e(i,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const e=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!e)return null;const t=this.owner.ownerDocument.createElement("div");return t.dataset.hpOverlay=this.name,t.style.display="contents",this.keydown&&t.addEventListener("keydown",this.keydown,!0),e.append(t),this.host=t,this.root=t.attachShadow({mode:"open"}),this.root}}let h=0;class d extends n{constructor(){super(...arguments),this.text="",this.ariaLabel="",this.pointerHover=!1,this._open=!1,this._openTimer=0,this._closeTimer=0,this._positionRaf=0,this._forceFallback=!1,this._hoverOwned=!1,this._overlayDispose=null,this._scrollDialog=null,this._descriptionId="hp-help-description-"+ ++h,this._surfacePointerEnter=()=>{const e=this._window();this._closeTimer&&e?.clearTimeout(this._closeTimer),this._closeTimer=0},this._surfacePointerLeave=()=>{this._scheduleClose()},this._outsidePointerDown=e=>{if(!this._open)return;const t=e.composedPath();this._floating.containsPath(t)||this._closeHelp(!1,"outside")},this._dialogScroll=e=>{const t=this._floating.containsPath(e.composedPath()),i=e.target,o=this._dialog(),n=i instanceof Node&&(i===o||i instanceof Element&&i.contains(this));var r;this._open&&(r=n,!t&&r)&&this._closeHelp(!1,"scroll")},this._keyDown=e=>{if(!this._open||e.defaultPrevented)return;if("Escape"===e.key)return e.preventDefault(),e.stopImmediatePropagation(),void this._closeHelp(this._floating.ownsActiveElement(),"escape");const t=this.renderRoot.querySelector(".trigger");if(!t||!e.composedPath().includes(t))return;const i=this._surface();if(!i||i.scrollHeight<=i.clientHeight)return;const o=Math.max(40,.8*i.clientHeight),n={ArrowDown:40,ArrowUp:-40,PageDown:o,PageUp:-o};if("Home"===e.key)i.scrollTop=0;else if("End"===e.key)i.scrollTop=i.scrollHeight;else{if(!(e.key in n))return;i.scrollBy({top:n[e.key],behavior:"auto"})}e.preventDefault(),e.stopImmediatePropagation()},this._floating=new l(this,"help",this._keyDown),this._queuePosition=()=>{if(!this._open||this._positionRaf)return;const e=this._window();e&&(this._positionRaf=e.requestAnimationFrame(()=>{this._positionRaf=0,this._position()||this._closeHelp()}))}}connectedCallback(){super.connectedCallback(),this.addEventListener("keydown",this._keyDown,!0)}willUpdate(){this.toggleAttribute("data-has-content",this._hasContent())}disconnectedCallback(){const e=this.ownerDocument.defaultView;this._unsubscribeOpenListeners(),this.removeEventListener("keydown",this._keyDown,!0),this._clearTimers(),this._positionRaf&&e?.cancelAnimationFrame(this._positionRaf),this._positionRaf=0,this._closeHelp(!1,"disconnect"),super.disconnectedCallback()}updated(e){if(e.has("pointerHover")&&!this.pointerHover){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._openTimer=0,this._hoverOwned&&this._closeHelp(!1,"outside")}this._hasContent()||!this._open?this._open&&e.has("text")&&(this._usesPopover()||this._renderFallback(),this._queuePosition()):this._closeHelp()}_window(){return this._floating.window()}_dialog(){return this._floating.dialog()}_usesPopover(){return this._floating.usesPopover(this._forceFallback)}_hasContent(){return e=this.text,t=this.ariaLabel,"string"==typeof e&&e.trim().length>0&&"string"==typeof t&&t.trim().length>0;var e,t}_clearTimers(){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._closeTimer&&e?.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=0}_scheduleOpen(){const e=this._window();this.pointerHover&&e&&!this._open&&!this._openTimer&&(this._closeTimer&&e.clearTimeout(this._closeTimer),this._closeTimer=0,this._openTimer=e.setTimeout(()=>{this._openTimer=0,this.isConnected&&(this._hoverOwned=!0,this._openHelp())},300))}_scheduleClose(){const e=this._window(),t=this.renderRoot.querySelector(".trigger");e&&!t?.matches(":focus-visible")&&(this._openTimer&&e.clearTimeout(this._openTimer),this._closeTimer&&e.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=e.setTimeout(()=>{this._closeTimer=0,this.isConnected&&this._closeHelp()},150))}_triggerPointerEnter(e){this.pointerHover&&"mouse"===e.pointerType&&this._scheduleOpen()}_triggerPointerLeave(e){"mouse"===e.pointerType&&this._scheduleClose()}_triggerFocus(){queueMicrotask(()=>{const e=this.renderRoot.querySelector(".trigger");e?.matches(":focus-visible")&&(this._hoverOwned=!1,this._openHelp())})}_triggerBlur(){this._scheduleClose()}_triggerClick(){this._open?this._closeHelp():(this._hoverOwned=!1,this._openHelp())}_subscribeOpenListeners(){this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("keydown",this._keyDown,!0);const e=this._window();e?.addEventListener("resize",this._queuePosition),e?.addEventListener("orientationchange",this._queuePosition),e?.visualViewport?.addEventListener("resize",this._queuePosition),e?.visualViewport?.addEventListener("scroll",this._queuePosition),this._scrollDialog=this._dialog(),this._scrollDialog?.addEventListener("scroll",this._dialogScroll,!0)}_unsubscribeOpenListeners(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("keydown",this._keyDown,!0);const e=this._window();e?.removeEventListener("resize",this._queuePosition),e?.removeEventListener("orientationchange",this._queuePosition),e?.visualViewport?.removeEventListener("resize",this._queuePosition),e?.visualViewport?.removeEventListener("scroll",this._queuePosition),this._scrollDialog?.removeEventListener("scroll",this._dialogScroll,!0),this._scrollDialog=null}async _openHelp(){!this._open&&this._hasContent()&&(this._clearTimers(),this._forceFallback=!1,this._open=!0,this._subscribeOpenListeners(),await this.updateComplete,this._open&&(this._usesPopover()||this._renderFallback(),this._position()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:e=>this._closeHelp("escape"===e&&this._floating.ownsActiveElement(),e)})||null:this._closeHelp()))}_closeHelp(e=!1,t="exclusive"){if(!this._open&&!this._floating.hasFallback)return;this._clearTimers();const i=this._overlayDispose;this._overlayDispose=null,i?.();const o=this.renderRoot.querySelector(".tooltip");if(o?.hidePopover)try{o.matches(":popover-open")&&o.hidePopover()}catch{}this._open=!1,this._hoverOwned=!1,this._unsubscribeOpenListeners(),this._floating.destroy(),e&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_tooltipTemplate(e){return t`
a&&(p=e.right-c),p=Math.min(Math.max(r,p),Math.max(r,a-c));const g=e.bottom+o,_=e.top-o-u;let m="bottom",f=g;return g+u>l&&_>=s?(m="top",f=Math.min(Math.max(s,_),Math.max(s,l-u))):f=Math.min(Math.max(s,g),Math.max(s,l-u)),{left:Math.round(p),top:Math.round(f),side:m,maxWidth:Math.round(h),maxHeight:Math.round(d)}}class l{constructor(e,t,i){this.owner=e,this.name=t,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(e=!1){const t=this.window();return!e&&!!t&&function(e){const t=e.HTMLElement?.prototype;return"function"==typeof t?.showPopover&&"function"==typeof t?.hidePopover}(t)}get hasFallback(){return!!this.host}containsPath(e){return e.includes(this.owner)||!!this.host&&e.includes(this.host)}ownsActiveElement(){let e=this.owner.ownerDocument.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return!(!e||e!==this.owner&&!this.owner.shadowRoot?.contains(e)&&!this.root?.contains(e))}renderFallback(i,o){const n=this.ensureFallback();return n?(e(t`${i}`,n),n):null}surface(e,t){return t?this.owner.shadowRoot?.querySelector(e)||null:this.root?.querySelector(e)||null}destroy(){this.root&&e(i,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const e=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!e)return null;const t=this.owner.ownerDocument.createElement("div");return t.dataset.hpOverlay=this.name,t.style.display="contents",this.keydown&&t.addEventListener("keydown",this.keydown,!0),e.append(t),this.host=t,this.root=t.attachShadow({mode:"open"}),this.root}}let h=0;class d extends n{constructor(){super(...arguments),this.text="",this.ariaLabel="",this.pointerHover=!1,this._open=!1,this._openTimer=0,this._closeTimer=0,this._positionRaf=0,this._forceFallback=!1,this._hoverOwned=!1,this._overlayDispose=null,this._scrollDialog=null,this._descriptionId="hp-help-description-"+ ++h,this._surfacePointerEnter=()=>{const e=this._window();this._closeTimer&&e?.clearTimeout(this._closeTimer),this._closeTimer=0},this._surfacePointerLeave=()=>{this._scheduleClose()},this._outsidePointerDown=e=>{if(!this._open)return;const t=e.composedPath();this._floating.containsPath(t)||this._closeHelp(!1,"outside")},this._dialogScroll=e=>{const t=this._floating.containsPath(e.composedPath()),i=e.target,o=this._dialog(),n=i instanceof Node&&(i===o||i instanceof Element&&i.contains(this));var r;this._open&&(r=n,!t&&r)&&this._closeHelp(!1,"scroll")},this._keyDown=e=>{if(!this._open||e.defaultPrevented)return;if("Escape"===e.key)return e.preventDefault(),e.stopImmediatePropagation(),void this._closeHelp(this._floating.ownsActiveElement(),"escape");const t=this.renderRoot.querySelector(".trigger");if(!t||!e.composedPath().includes(t))return;const i=this._surface();if(!i||i.scrollHeight<=i.clientHeight)return;const o=Math.max(40,.8*i.clientHeight),n={ArrowDown:40,ArrowUp:-40,PageDown:o,PageUp:-o};if("Home"===e.key)i.scrollTop=0;else if("End"===e.key)i.scrollTop=i.scrollHeight;else{if(!(e.key in n))return;i.scrollBy({top:n[e.key],behavior:"auto"})}e.preventDefault(),e.stopImmediatePropagation()},this._floating=new l(this,"help",this._keyDown),this._queuePosition=()=>{if(!this._open||this._positionRaf)return;const e=this._window();e&&(this._positionRaf=e.requestAnimationFrame(()=>{this._positionRaf=0,this._position()||this._closeHelp()}))}}connectedCallback(){super.connectedCallback(),this.addEventListener("keydown",this._keyDown,!0)}willUpdate(){this.toggleAttribute("data-has-content",this._hasContent())}disconnectedCallback(){const e=this.ownerDocument.defaultView;this._unsubscribeOpenListeners(),this.removeEventListener("keydown",this._keyDown,!0),this._clearTimers(),this._positionRaf&&e?.cancelAnimationFrame(this._positionRaf),this._positionRaf=0,this._closeHelp(!1,"disconnect"),super.disconnectedCallback()}updated(e){if(e.has("pointerHover")&&!this.pointerHover){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._openTimer=0,this._hoverOwned&&this._closeHelp(!1,"outside")}this._hasContent()||!this._open?this._open&&e.has("text")&&(this._usesPopover()||this._renderFallback(),this._queuePosition()):this._closeHelp()}_window(){return this._floating.window()}_dialog(){return this._floating.dialog()}_usesPopover(){return this._floating.usesPopover(this._forceFallback)}_hasContent(){return e=this.text,t=this.ariaLabel,"string"==typeof e&&e.trim().length>0&&"string"==typeof t&&t.trim().length>0;var e,t}_clearTimers(){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._closeTimer&&e?.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=0}_scheduleOpen(){const e=this._window();this.pointerHover&&e&&!this._open&&!this._openTimer&&(this._closeTimer&&e.clearTimeout(this._closeTimer),this._closeTimer=0,this._openTimer=e.setTimeout(()=>{this._openTimer=0,this.isConnected&&(this._hoverOwned=!0,this._openHelp())},300))}_scheduleClose(){const e=this._window(),t=this.renderRoot.querySelector(".trigger");e&&!t?.matches(":focus-visible")&&(this._openTimer&&e.clearTimeout(this._openTimer),this._closeTimer&&e.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=e.setTimeout(()=>{this._closeTimer=0,this.isConnected&&this._closeHelp()},150))}_triggerPointerEnter(e){this.pointerHover&&"mouse"===e.pointerType&&this._scheduleOpen()}_triggerPointerLeave(e){"mouse"===e.pointerType&&this._scheduleClose()}_triggerFocus(){queueMicrotask(()=>{const e=this.renderRoot.querySelector(".trigger");e?.matches(":focus-visible")&&(this._hoverOwned=!1,this._openHelp())})}_triggerBlur(){this._scheduleClose()}_triggerClick(){this._open?this._closeHelp():(this._hoverOwned=!1,this._openHelp())}_subscribeOpenListeners(){this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("keydown",this._keyDown,!0);const e=this._window();e?.addEventListener("resize",this._queuePosition),e?.addEventListener("orientationchange",this._queuePosition),e?.visualViewport?.addEventListener("resize",this._queuePosition),e?.visualViewport?.addEventListener("scroll",this._queuePosition),this._scrollDialog=this._dialog(),this._scrollDialog?.addEventListener("scroll",this._dialogScroll,!0)}_unsubscribeOpenListeners(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("keydown",this._keyDown,!0);const e=this._window();e?.removeEventListener("resize",this._queuePosition),e?.removeEventListener("orientationchange",this._queuePosition),e?.visualViewport?.removeEventListener("resize",this._queuePosition),e?.visualViewport?.removeEventListener("scroll",this._queuePosition),this._scrollDialog?.removeEventListener("scroll",this._dialogScroll,!0),this._scrollDialog=null}async _openHelp(){!this._open&&this._hasContent()&&(this._clearTimers(),this._forceFallback=!1,this._open=!0,this._subscribeOpenListeners(),await this.updateComplete,this._open&&(this._usesPopover()||this._renderFallback(),this._position()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:e=>this._closeHelp("escape"===e&&this._floating.ownsActiveElement(),e)})||null:this._closeHelp()))}_closeHelp(e=!1,t="exclusive"){if(!this._open&&!this._floating.hasFallback)return;this._clearTimers();const i=this._overlayDispose;this._overlayDispose=null,i?.();const o=this.renderRoot.querySelector(".tooltip");if(o?.hidePopover)try{o.matches(":popover-open")&&o.hidePopover()}catch{}this._open=!1,this._hoverOwned=!1,this._unsubscribeOpenListeners(),this._floating.destroy(),e&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_tooltipTemplate(e){return t``}_renderFallback(){const e=d.styles.cssText;this._floating.renderFallback(this._tooltipTemplate(!1),e)}_surface(){return this._floating.surface(".tooltip",this._usesPopover())}_position(){if(!this._open)return!1;const e=this._window(),t=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!e||!t?.isConnected||!i?.isConnected)return!1;const o=s(e);if(i.style.maxWidth=`${Math.max(0,Math.min(320,o.width-16))}px`,i.style.maxHeight=`${Math.max(0,o.height-16)}px`,i.style.visibility="hidden",this._usesPopover()&&i.showPopover)try{i.matches(":popover-open")||i.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),i=this._surface(),!i?.isConnected)return!1;i.style.visibility="hidden"}const n=t.getBoundingClientRect(),r=i.getBoundingClientRect();if(!(n.width&&n.height&&r.width&&r.height))return!1;const l=a(n,r,o);return i.style.left=`${l.left}px`,i.style.top=`${l.top}px`,i.dataset.side=l.side,i.style.visibility="",!0}render(){if(!this._hasContent())return i;const e=this.ariaLabel.trim();return t` ({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`r===this.ot[t]))return e}else if(this.ot===t)return e;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,s)}});export{a as i}; diff --git a/custom_components/houseplan/frontend/houseplan-assets/guard-BgTQLSGB.js b/custom_components/houseplan/frontend/houseplan-assets/guard-BgTQLSGB.js new file mode 100644 index 00000000..512a5480 --- /dev/null +++ b/custom_components/houseplan/frontend/houseplan-assets/guard-BgTQLSGB.js @@ -0,0 +1 @@ +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{dJ as r,dK as t,dL as s}from"./houseplan-card-Bhpi71t0.js";const a={},e=r(class extends t{constructor(){super(...arguments),this.ot=a}render(r,t){return t()}update(r,[t,a]){if(Array.isArray(t)){if(Array.isArray(this.ot)&&this.ot.length===t.length&&t.every((r,t)=>r===this.ot[t]))return s}else if(this.ot===t)return s;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,a)}});export{e as i}; diff --git a/custom_components/houseplan/frontend/houseplan-assets/houseplan-card-CODdCIWj.js b/custom_components/houseplan/frontend/houseplan-assets/houseplan-card-Bhpi71t0.js similarity index 60% rename from custom_components/houseplan/frontend/houseplan-assets/houseplan-card-CODdCIWj.js rename to custom_components/houseplan/frontend/houseplan-assets/houseplan-card-Bhpi71t0.js index ccdb8d1a..4248bacc 100644 --- a/custom_components/houseplan/frontend/houseplan-assets/houseplan-card-CODdCIWj.js +++ b/custom_components/houseplan/frontend/houseplan-assets/houseplan-card-Bhpi71t0.js @@ -1,7 +1,7 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),n=new WeakMap;let r=class{constructor(e,t,n){if(this._$cssResult$=!0,n!==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=n.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&n.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const n=1===e.length?e[0]:t.reduce((t,i,n)=>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[n+1],e[0]);return new r(n,e,i)},s=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new r("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:u}=Object,p=globalThis,_=p.trustedTypes,m=_?_.emptyScript:"",g=p.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}},y=(e,t)=>!a(e,t),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.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=b){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(),n=this.getPropertyDescriptor(e,i,t);void 0!==n&&l(this.prototype,e,n)}}static getPropertyDescriptor(e,t,i){const{get:n,set:r}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:n,set(t){const o=n?.call(this);r?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=u(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(s(e))}else void 0!==e&&t.push(s(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,n)=>{if(t)i.adoptedStyleSheets=n.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of n){const n=document.createElement("style"),r=e.litNonce;void 0!==r&&n.setAttribute("nonce",r),n.textContent=t.cssText,i.appendChild(n)}})(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),n=this.constructor._$Eu(e,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(e,t){const i=this.constructor,n=i._$Eh.get(e);if(void 0!==n&&this._$Em!==n){const e=i.getPropertyOptions(n),r="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=n;const o=r.fromAttribute(t,e.type);this[n]=o??this._$Ej?.get(n)??o,this._$Em=null}}requestUpdate(e,t,i,n=!1,r){if(void 0!==e){const o=this.constructor;if(!1===n&&(r=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??y)(r,t)||i.useDefault&&i.reflect&&r===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:n,wrapped:r},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==r||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===n&&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,n=this[t];!0!==e||this._$AL.has(t)||void 0===n||this.C(t,void 0,i,n)}}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}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,S=k.trustedTypes,$=S?S.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",R=`lit$${Math.random().toFixed(9).slice(2)}$`,C="?"+R,T=`<${C}>`,D=document,z=()=>D.createComment(""),A=e=>null===e||"object"!=typeof e&&"function"!=typeof e,P=Array.isArray,F="[ \t\n\f\r]",I=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,O=/-->/g,E=/>/g,H=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),N=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),W=q(1),j=q(2),U=Symbol.for("lit-noChange"),V=Symbol.for("lit-nothing"),G=new WeakMap,K=D.createTreeWalker(D,129);function Y(e,t){if(!P(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==$?$.createHTML(t):t}const X=(e,t)=>{const i=e.length-1,n=[];let r,o=2===t?"":3===t?"":"",s=I;for(let t=0;t"===l[0]?(s=r??I,c=-1):void 0===l[1]?c=-2:(c=s.lastIndex-l[2].length,a=l[1],s=void 0===l[3]?H:'"'===l[3]?L:N):s===L||s===N?s=H:s===O||s===E?s=I:(s=H,r=void 0);const d=s===H&&e[t+1].startsWith("/>")?" ":"";o+=s===I?i+T:c>=0?(n.push(a),i.slice(0,c)+M+i.slice(c)+R+d):i+R+(-2===c?t:d)}return[Y(e,o+(e[i]||"")+(2===t?"":3===t?"":"")),n]};class Z{constructor({strings:e,_$litType$:t},i){let n;this.parts=[];let r=0,o=0;const s=e.length-1,a=this.parts,[l,c]=X(e,t);if(this.el=Z.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(n=K.nextNode())&&a.length0){n.textContent=S?S.emptyScript:"";for(let i=0;iP(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!==V&&A(this._$AH)?this._$AA.nextSibling.data=e:this.T(D.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,n="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=Z.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(t);else{const e=new Q(n,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=G.get(e.strings);return void 0===t&&G.set(e.strings,t=new Z(e)),t}k(e){P(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,n=0;for(const r of e)n===t.length?t.push(i=new ee(this.O(z()),this.O(z()),this,this.options)):i=t[n],i._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=V}_$AI(e,t=this,i,n){const r=this.strings;let o=!1;if(void 0===r)e=J(this,e,t,0),o=!A(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const n=e;let s,a;for(e=r[0],s=0;s{const n=i?.renderBefore??t;let r=n._$litPart$;if(void 0===r){const e=i?.renderBefore??null;n._$litPart$=r=new ee(t.insertBefore(z(),e),e,void 0,i??{})}return r._$AI(e),r},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 ue=2,pe=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{I:me}=se,ge=e=>e,fe=(e,t)=>void 0!==e?._$litType$,ve=()=>document.createComment(""),ye=(e,t,i)=>{const n=e._$AA.parentNode,r=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=n.insertBefore(ve(),r),o=n.insertBefore(ve(),r);i=new me(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,s=o!==e;if(s){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==r||s){let e=i._$AA;for(;e!==t;){const t=ge(e).nextSibling;ge(n).insertBefore(e,r),e=t}}}return i},be=(e,t,i=e)=>(e._$AI(t,i),e),we={},ke=(e,t=we)=>e._$AH=t,xe=e=>e._$AH,Se=e=>{e._$AR(),e._$AA.remove()},$e=e=>(e=>null!=e?._$litType$?.h)(e)?e._$litType$.h:e.strings,Me=pe(class extends _e{constructor(e){super(e),this.et=new WeakMap}render(e){return[e]}update(e,[t]){const i=fe(this.it)?$e(this.it):null,n=fe(t)?$e(t):null;if(null!==i&&(null===n||i!==n)){const t=xe(e).pop();let n=this.et.get(i);if(void 0===n){const e=document.createDocumentFragment();n=le(V,e),n.setConnected(!1),this.et.set(i,n)}ke(n,[t]),ye(n,void 0,t)}if(null!==n){if(null===i||i!==n){const t=this.et.get(n);if(void 0!==t){const i=xe(t).pop();(e=>{e._$AR()})(e),ye(e,void 0,i),ke(e,[i])}}this.it=t}else this.it=void 0;return this.render(t)}}),Re=new WeakMap;let Ce=0;class Te extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=null,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Ce,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._usesHaDialog()?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._usesHaDialog())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 n=this._deepActiveElement(),r=i[0],o=i[i.length-1];!e.shiftKey||n!==r&&i.includes(n)?e.shiftKey||n!==o||(e.preventDefault(),r.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}_usesHaDialog(){return!0===this._useHaDialog&&!this.alert}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Re.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Re.set(e,t),null===this._useHaDialog&&(this._useHaDialog=!!customElements.get("ha-dialog")),this.addEventListener("keydown",this._onKeyDown,!0),queueMicrotask(()=>{this._ensureNativeModal()&&this._focusInitial()})}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 n=t?Re.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=Re.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Re.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){super.firstUpdated(e),this._ensureNativeModal(),queueMicrotask(()=>this._focusInitial())}updated(e){super.updated(e),this._ensureNativeModal()}_ensureNativeModal(){if(this._usesHaDialog()||!this.isConnected)return!1;const e=this.renderRoot.querySelector("dialog");if(!e?.isConnected)return!1;try{return!e.matches(":modal")&&(e.open&&e.close(),e.showModal(),!0)}catch{return!1}}_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,n=r=>{if(!i.has(r)){if(i.add(r),r instanceof HTMLElement){if(r.matches(e)&&t.push(r),r instanceof HTMLSlotElement){for(const e of r.assignedNodes({flatten:!0}))n(e);return}if(r.shadowRoot){for(const e of r.shadowRoot.childNodes)n(e);return}}for(const e of r.childNodes)n(e)}};for(const e of this.childNodes)n(e);const r=this.overlayPortal();return r&&n(r),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})}rejectClose(){this._closing=!1,this.requestUpdate()}_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 n={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(n);let r=!1;return()=>{if(r)return;r=!0;const e=this._overlays.findIndex(e=>e.token===n.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=W` - ${this.icon?W``:V} +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),n=new WeakMap;let r=class{constructor(e,t,n){if(this._$cssResult$=!0,n!==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=n.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&n.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const n=1===e.length?e[0]:t.reduce((t,i,n)=>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[n+1],e[0]);return new r(n,e,i)},s=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new r("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:u}=Object,p=globalThis,_=p.trustedTypes,m=_?_.emptyScript:"",g=p.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}},y=(e,t)=>!a(e,t),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.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=b){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(),n=this.getPropertyDescriptor(e,i,t);void 0!==n&&l(this.prototype,e,n)}}static getPropertyDescriptor(e,t,i){const{get:n,set:r}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:n,set(t){const o=n?.call(this);r?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=u(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(s(e))}else void 0!==e&&t.push(s(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,n)=>{if(t)i.adoptedStyleSheets=n.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of n){const n=document.createElement("style"),r=e.litNonce;void 0!==r&&n.setAttribute("nonce",r),n.textContent=t.cssText,i.appendChild(n)}})(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),n=this.constructor._$Eu(e,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(e,t){const i=this.constructor,n=i._$Eh.get(e);if(void 0!==n&&this._$Em!==n){const e=i.getPropertyOptions(n),r="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=n;const o=r.fromAttribute(t,e.type);this[n]=o??this._$Ej?.get(n)??o,this._$Em=null}}requestUpdate(e,t,i,n=!1,r){if(void 0!==e){const o=this.constructor;if(!1===n&&(r=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??y)(r,t)||i.useDefault&&i.reflect&&r===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:n,wrapped:r},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==r||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===n&&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,n=this[t];!0!==e||this._$AL.has(t)||void 0===n||this.C(t,void 0,i,n)}}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}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,S=k.trustedTypes,$=S?S.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",R=`lit$${Math.random().toFixed(9).slice(2)}$`,C="?"+R,T=`<${C}>`,D=document,A=()=>D.createComment(""),P=e=>null===e||"object"!=typeof e&&"function"!=typeof e,F=Array.isArray,z="[ \t\n\f\r]",I=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,O=/-->/g,E=/>/g,N=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),j=q(1),W=q(2),U=Symbol.for("lit-noChange"),V=Symbol.for("lit-nothing"),G=new WeakMap,K=D.createTreeWalker(D,129);function Y(e,t){if(!F(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==$?$.createHTML(t):t}const X=(e,t)=>{const i=e.length-1,n=[];let r,o=2===t?"":3===t?"":"",s=I;for(let t=0;t"===l[0]?(s=r??I,c=-1):void 0===l[1]?c=-2:(c=s.lastIndex-l[2].length,a=l[1],s=void 0===l[3]?N:'"'===l[3]?L:H):s===L||s===H?s=N:s===O||s===E?s=I:(s=N,r=void 0);const d=s===N&&e[t+1].startsWith("/>")?" ":"";o+=s===I?i+T:c>=0?(n.push(a),i.slice(0,c)+M+i.slice(c)+R+d):i+R+(-2===c?t:d)}return[Y(e,o+(e[i]||"")+(2===t?"":3===t?"":"")),n]};class Z{constructor({strings:e,_$litType$:t},i){let n;this.parts=[];let r=0,o=0;const s=e.length-1,a=this.parts,[l,c]=X(e,t);if(this.el=Z.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(n=K.nextNode())&&a.length0){n.textContent=S?S.emptyScript:"";for(let i=0;iF(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!==V&&P(this._$AH)?this._$AA.nextSibling.data=e:this.T(D.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,n="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=Z.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(t);else{const e=new Q(n,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=G.get(e.strings);return void 0===t&&G.set(e.strings,t=new Z(e)),t}k(e){F(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,n=0;for(const r of e)n===t.length?t.push(i=new ee(this.O(A()),this.O(A()),this,this.options)):i=t[n],i._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=V}_$AI(e,t=this,i,n){const r=this.strings;let o=!1;if(void 0===r)e=J(this,e,t,0),o=!P(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const n=e;let s,a;for(e=r[0],s=0;s{const n=i?.renderBefore??t;let r=n._$litPart$;if(void 0===r){const e=i?.renderBefore??null;n._$litPart$=r=new ee(t.insertBefore(A(),e),e,void 0,i??{})}return r._$AI(e),r},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 ue=2,pe=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{I:me}=se,ge=e=>e,fe=(e,t)=>void 0!==e?._$litType$,ve=()=>document.createComment(""),ye=(e,t,i)=>{const n=e._$AA.parentNode,r=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=n.insertBefore(ve(),r),o=n.insertBefore(ve(),r);i=new me(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,s=o!==e;if(s){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==r||s){let e=i._$AA;for(;e!==t;){const t=ge(e).nextSibling;ge(n).insertBefore(e,r),e=t}}}return i},be=(e,t,i=e)=>(e._$AI(t,i),e),we={},ke=(e,t=we)=>e._$AH=t,xe=e=>e._$AH,Se=e=>{e._$AR(),e._$AA.remove()},$e=e=>(e=>null!=e?._$litType$?.h)(e)?e._$litType$.h:e.strings,Me=pe(class extends _e{constructor(e){super(e),this.et=new WeakMap}render(e){return[e]}update(e,[t]){const i=fe(this.it)?$e(this.it):null,n=fe(t)?$e(t):null;if(null!==i&&(null===n||i!==n)){const t=xe(e).pop();let n=this.et.get(i);if(void 0===n){const e=document.createDocumentFragment();n=le(V,e),n.setConnected(!1),this.et.set(i,n)}ke(n,[t]),ye(n,void 0,t)}if(null!==n){if(null===i||i!==n){const t=this.et.get(n);if(void 0!==t){const i=xe(t).pop();(e=>{e._$AR()})(e),ye(e,void 0,i),ke(e,[i])}}this.it=t}else this.it=void 0;return this.render(t)}}),Re=new WeakMap;let Ce=0;class Te extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=null,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Ce,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._usesHaDialog()?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._usesHaDialog())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 n=this._deepActiveElement(),r=i[0],o=i[i.length-1];!e.shiftKey||n!==r&&i.includes(n)?e.shiftKey||n!==o||(e.preventDefault(),r.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}_usesHaDialog(){return!0===this._useHaDialog&&!this.alert}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Re.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Re.set(e,t),null===this._useHaDialog&&(this._useHaDialog=!!customElements.get("ha-dialog")),this.addEventListener("keydown",this._onKeyDown,!0),queueMicrotask(()=>{this._ensureNativeModal()&&this._focusInitial()})}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 n=t?Re.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=Re.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Re.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){super.firstUpdated(e),this._ensureNativeModal(),queueMicrotask(()=>this._focusInitial())}updated(e){super.updated(e),this._ensureNativeModal()}_ensureNativeModal(){if(this._usesHaDialog()||!this.isConnected)return!1;const e=this.renderRoot.querySelector("dialog");if(!e?.isConnected)return!1;try{return!e.matches(":modal")&&(e.open&&e.close(),e.showModal(),!0)}catch{return!1}}_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,n=r=>{if(!i.has(r)){if(i.add(r),r instanceof HTMLElement){if(r.matches(e)&&t.push(r),r instanceof HTMLSlotElement){for(const e of r.assignedNodes({flatten:!0}))n(e);return}if(r.shadowRoot){for(const e of r.shadowRoot.childNodes)n(e);return}}for(const e of r.childNodes)n(e)}};for(const e of this.childNodes)n(e);const r=this.overlayPortal();return r&&n(r),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})}rejectClose(){this._closing=!1,this.requestUpdate()}_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 n={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(n);let r=!1;return()=>{if(r)return;r=!0;const e=this._overlays.findIndex(e=>e.token===n.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=j` + ${this.icon?j``:V} ${this.title} - `;return this._usesHaDialog()?this.describedBy?W``;return this._usesHaDialog()?this.describedBy?j`${e} -
`:W`
`:j`${e}
-
`:W`
`:j` - ${e.objectName?W`${e.objectName}`:null} + ${e.objectName?j`${e.objectName}`:null}

${e.message}

- `}}De.properties={hass:{attribute:!1},request:{attribute:!1},token:{type:Number}},customElements.get("hp-confirm")||customElements.define("hp-confirm",De);class ze{constructor(e){this._changed=e,this._sequence=0,this._active=null}get state(){return this._active?{token:this._active.token,request:this._active.request}:null}confirm(e){this.cancel();const t={token:++this._sequence,request:Object.freeze({...e})};return new Promise(e=>{this._active={...t,resolve:e},this._changed(t)})}resolve(e,t){const i=this._active;return!(!i||i.token!==e)&&(this._active=null,this._changed(null),i.resolve(t),!0)}cancel(){const e=this._active;return!!e&&this.resolve(e.token,!1)}}const Ae=new Set(["hacs","sun","backup","hassio","met","telegram_bot","mobile_app","systemmonitor","better_thermostat","adaptive_lighting","yandex_pogoda","upnp_serial_number"]),Pe=[{pattern:"протечк|leak|water sensor",icon:"mdi:water-alert"},{pattern:"клапан|valve",icon:"mdi:pipe-valve"},{pattern:"дым|smoke",icon:"mdi:smoke-detector"},{pattern:"термоголов|trv|radiator",icon:"mdi:radiator"},{pattern:"чайник|kettle|термопот",icon:"mdi:kettle"},{pattern:"сауна|sauna|harvia|парная|парилк",icon:"mdi:hot-tub"},{pattern:"температ|temperature|thermometer|climate sensor",icon:"mdi:thermometer"},{pattern:"qingping|air monitor|молекул|air quality",icon:"mdi:air-filter"},{pattern:"штор|curtain|blind|shade",icon:"mdi:roller-shade"},{pattern:"розетк|plug|socket|outlet",icon:"mdi:power-socket-de"},{pattern:"выключат|switch",icon:"mdi:light-switch"},{pattern:"лампа|лампочк|bulb|gx53|светильник|rgb|lamp|light strip",icon:"mdi:lightbulb"},{pattern:"камер|camera",icon:"mdi:cctv"},{pattern:"замок|ttlock|lock|sn609|sn9161",icon:"mdi:lock"},{pattern:"ворота|garage|gate",icon:"mdi:garage-variant"},{pattern:"калитк|door|открыт|contact",icon:"mdi:door"},{pattern:"счётчик|счетчик|kws|meter",icon:"mdi:meter-electric"},{pattern:"вводный автомат|breaker|wifimcbn",icon:"mdi:electric-switch"},{pattern:"myheat|котёл|котел|boiler|отоплен|heating",icon:"mdi:water-boiler"},{pattern:"холодильник|fridge",icon:"mdi:fridge"},{pattern:"стиральн|washer|washing",icon:"mdi:washing-machine"},{pattern:"сушилк|dryer",icon:"mdi:tumble-dryer"},{pattern:"пылесос|vacuum|dreame|roborock",icon:"mdi:robot-vacuum"},{pattern:"soundbar",icon:"mdi:soundbar"},{pattern:"колонк|станц|speaker|яндекс|yandex|алиса|alice",icon:"mdi:speaker"},{pattern:"tv|телевизор|hyundaitv|mitv|television",icon:"mdi:television"},{pattern:"keenetic|роутер|router|mesh|access point",icon:"mdi:router-wireless"},{pattern:"ибп|ups|kirpich",icon:"mdi:battery-charging-high"},{pattern:"slzb|координат|zigbee|coordinator",icon:"mdi:zigbee"},{pattern:"motion|движен|presence|присутств",icon:"mdi:motion-sensor"},{pattern:"humidity|влажн",icon:"mdi:water-percent"}];function Fe(e){const t=[];for(const i of e)if(i&&"string"==typeof i.pattern&&i.icon)try{t.push({re:new RegExp(i.pattern,"i"),icon:i.icon})}catch{}return t}function Ie(e){try{return new RegExp(e,"i"),!0}catch{return!1}}const Oe=Fe(Pe),Ee={temperature:"mdi:thermometer",humidity:"mdi:water-percent",motion:"mdi:motion-sensor",occupancy:"mdi:motion-sensor",presence:"mdi:motion-sensor",door:"mdi:door",window:"mdi:window-closed",garage_door:"mdi:garage-variant",smoke:"mdi:smoke-detector",moisture:"mdi:water-alert",gas:"mdi:gas-cylinder",power:"mdi:meter-electric",energy:"mdi:meter-electric",illuminance:"mdi:brightness-5",co2:"mdi:molecule-co2",pm25:"mdi:air-filter",battery:"mdi:battery"},He="mdi:chip";function Ne(e,t,i){const n=((e||"")+" "+(t||"")).toLowerCase();for(const{re:e,icon:t}of i??Oe)if(e.test(n))return t;return He}const Le=["light","switch","cover","valve","lock","climate","fan","media_player","camera","vacuum","humidifier","water_heater","alarm_control_panel","sensor","binary_sensor","event","button","number","select","update"];var Be=/^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i,qe=Math.ceil,We=Math.floor,je="[BigNumber Error] ",Ue=je+"Number primitive has more than 15 significant digits: ",Ve=1e14,Ge=14,Ke=9007199254740991,Ye=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],Xe=1e7,Ze=1e9;function Je(e){var t=0|e;return e>0||e===t?t:t-1}function Qe(e){for(var t,i,n=1,r=e.length,o=e[0]+"";nc^i?1:-1;for(a=(l=r.length)<(c=o.length)?l:c,s=0;so[s]^i?1:-1;return l==c?0:l>c^i?1:-1}function tt(e,t,i,n){if(ei||e!==We(e))throw Error(je+(n||"Argument")+("number"==typeof e?ei?" out of range: ":" not an integer: ":" not a primitive number: ")+String(e))}function it(e){var t=e.c.length-1;return Je(e.e/Ge)==t&&e.c[t]%2!=0}function nt(e,t){return(e.length>1?e.charAt(0)+"."+e.slice(1):e)+(t<0?"e":"e+")+t}function rt(e,t,i){var n,r;if(t<0){for(r=i+".";++t;r+=i);e=r+e}else if(++t>(n=e.length)){for(r=i,t-=n;--t;r+=i);e+=r}else ty?u.c=u.e=null:e.e=10;l/=10,a++);return void(a>y?u.c=u.e=null:(u.e=a,u.c=[e]))}d=String(e)}else{if(!Be.test(d=String(e)))return r(u,d,c);u.s=45==d.charCodeAt(0)?(d=d.slice(1),-1):1}(a=d.indexOf("."))>-1&&(d=d.replace(".","")),(l=d.search(/e/i))>0?(a<0&&(a=l),a+=+d.slice(l+1),d=d.substring(0,l)):a<0&&(a=d.length)}else{if(tt(t,2,S.length,"Base"),10==t&&$)return D(u=new M(e),_+u.e+1,m);if(d=String(e),c="number"==typeof e){if(0*e!=0)return r(u,d,c,t);if(u.s=1/e<0?(d=d.slice(1),-1):1,M.DEBUG&&d.replace(/^0\.0*|\./,"").length>15)throw Error(Ue+e)}else u.s=45===d.charCodeAt(0)?(d=d.slice(1),-1):1;for(i=S.slice(0,t),a=l=0,h=d.length;la){a=h;continue}}else if(!s&&(d==d.toUpperCase()&&(d=d.toLowerCase())||d==d.toLowerCase()&&(d=d.toUpperCase()))){s=!0,l=-1,a=0;continue}return r(u,String(e),c,t)}c=!1,(a=(d=n(d,t,10,u.s)).indexOf("."))>-1?d=d.replace(".",""):a=d.length}for(l=0;48===d.charCodeAt(l);l++);for(h=d.length;48===d.charCodeAt(--h););if(d=d.slice(l,++h)){if(h-=l,c&&M.DEBUG&&h>15&&(e>Ke||e!==We(e)))throw Error(Ue+u.s*e);if((a=a-l-1)>y)u.c=u.e=null;else if(a=f)?nt(l,s):rt(l,s,"0");else if(o=(e=D(new M(e),t,i)).e,a=(l=Qe(e.c)).length,1==n||2==n&&(t<=o||o<=g)){for(;as),l=rt(l,o,"0"),o+1>a){if(--t>0)for(l+=".";t--;l+="0");}else if((t+=o-a)>0)for(o+1==a&&(l+=".");t--;l+="0");return e.s<0&&r?"-"+l:l}function C(e,t){for(var i,n,r=1,o=new M(e[0]);r=10;r/=10,n++);return(i=n+i*Ge-1)>y?e.c=e.e=null:i=10;a/=10,r++);if((o=t-r)<0)o+=Ge,s=t,l=d[c=0],h=We(l/u[r-s-1]%10);else if((c=qe((o+1)/Ge))>=d.length){if(!n)break e;for(;d.length<=c;d.push(0));l=h=0,r=1,s=(o%=Ge)-Ge+1}else{for(l=a=d[c],r=1;a>=10;a/=10,r++);h=(s=(o%=Ge)-Ge+r)<0?0:We(l/u[r-s-1]%10)}if(n=n||t<0||null!=d[c+1]||(s<0?l:l%u[r-s-1]),n=i<4?(h||n)&&(0==i||i==(e.s<0?3:2)):h>5||5==h&&(4==i||n||6==i&&(o>0?s>0?l/u[r-s]:0:d[c-1])%10&1||i==(e.s<0?8:7)),t<1||!d[0])return d.length=0,n?(t-=e.e+1,d[0]=u[(Ge-t%Ge)%Ge],e.e=-t||0):d[0]=e.e=0,e;if(0==o?(d.length=c,a=1,c--):(d.length=c+1,a=u[Ge-o],d[c]=s>0?We(l/u[r-s]%u[s])*a:0),n)for(;;){if(0==c){for(o=1,s=d[0];s>=10;s/=10,o++);for(s=d[0]+=a,a=1;s>=10;s/=10,a++);o!=a&&(e.e++,d[0]==Ve&&(d[0]=1));break}if(d[c]+=a,d[c]!=Ve)break;d[c--]=0,a=1}for(o=d.length;0===d[--o];d.pop());}e.e>y?e.c=e.e=null:e.e=f?nt(t,i):rt(t,i,"0"),e.s<0?"-"+t:t)}return M.clone=e,M.ROUND_UP=0,M.ROUND_DOWN=1,M.ROUND_CEIL=2,M.ROUND_FLOOR=3,M.ROUND_HALF_UP=4,M.ROUND_HALF_DOWN=5,M.ROUND_HALF_EVEN=6,M.ROUND_HALF_CEIL=7,M.ROUND_HALF_FLOOR=8,M.EUCLID=9,M.config=M.set=function(e){var t,i;if(null!=e){if("object"!=typeof e)throw Error(je+"Object expected: "+e);if(e.hasOwnProperty(t="DECIMAL_PLACES")&&(tt(i=e[t],0,Ze,t),_=i),e.hasOwnProperty(t="ROUNDING_MODE")&&(tt(i=e[t],0,8,t),m=i),e.hasOwnProperty(t="EXPONENTIAL_AT")&&((i=e[t])&&i.pop?(tt(i[0],-Ze,0,t),tt(i[1],0,Ze,t),g=i[0],f=i[1]):(tt(i,-Ze,Ze,t),g=-(f=i<0?-i:i))),e.hasOwnProperty(t="RANGE"))if((i=e[t])&&i.pop)tt(i[0],-Ze,-1,t),tt(i[1],1,Ze,t),v=i[0],y=i[1];else{if(tt(i,-Ze,Ze,t),!i)throw Error(je+t+" cannot be zero: "+i);v=-(y=i<0?-i:i)}if(e.hasOwnProperty(t="CRYPTO")){if((i=e[t])!==!!i)throw Error(je+t+" not true or false: "+i);if(i){if("undefined"==typeof crypto||!crypto||!crypto.getRandomValues&&!crypto.randomBytes)throw b=!i,Error(je+"crypto unavailable");b=i}else b=i}if(e.hasOwnProperty(t="MODULO_MODE")&&(tt(i=e[t],0,9,t),w=i),e.hasOwnProperty(t="POW_PRECISION")&&(tt(i=e[t],0,Ze,t),k=i),e.hasOwnProperty(t="FORMAT")){if("object"!=typeof(i=e[t]))throw Error(je+t+" not an object: "+i);x=i}if(e.hasOwnProperty(t="ALPHABET")){if("string"!=typeof(i=e[t])||/^.?$|[+\-.\s]|(.).*\1/.test(i))throw Error(je+t+" invalid: "+i);$="0123456789"==i.slice(0,10),S=i}}return{DECIMAL_PLACES:_,ROUNDING_MODE:m,EXPONENTIAL_AT:[g,f],RANGE:[v,y],CRYPTO:b,MODULO_MODE:w,POW_PRECISION:k,FORMAT:x,ALPHABET:S}},M.isBigNumber=function(e){if(!e||!0!==e._isBigNumber)return!1;if(!M.DEBUG)return!0;var t,i,n=e.c,r=e.e,o=e.s;e:if("[object Array]"=={}.toString.call(n)){if((1===o||-1===o)&&r>=-Ze&&r<=Ze&&r===We(r)){if(0===n[0]){if(0===r&&1===n.length)return!0;break e}if((t=(r+1)%Ge)<1&&(t+=Ge),String(n[0]).length==t){for(t=0;t=Ve||i!==We(i))break e;if(0!==i)return!0}}}else if(null===n&&null===r&&(null===o||1===o||-1===o))return!0;throw Error(je+"Invalid BigNumber: "+e)},M.maximum=M.max=function(){return C(arguments,-1)},M.minimum=M.min=function(){return C(arguments,1)},M.random=(o=9007199254740992,s=Math.random()*o&2097151?function(){return We(Math.random()*o)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)},function(e){var t,i,n,r,o,a=0,l=[],c=new M(p);if(null==e?e=_:tt(e,0,Ze),r=qe(e/Ge),b)if(crypto.getRandomValues){for(t=crypto.getRandomValues(new Uint32Array(r*=2));a>>11))>=9e15?(i=crypto.getRandomValues(new Uint32Array(2)),t[a]=i[0],t[a+1]=i[1]):(l.push(o%1e14),a+=2);a=r/2}else{if(!crypto.randomBytes)throw b=!1,Error(je+"crypto unavailable");for(t=crypto.randomBytes(r*=7);a=9e15?crypto.randomBytes(7).copy(t,a):(l.push(o%1e14),a+=7);a=r/7}if(!b)for(;a=10;o/=10,a++);ai-1&&(null==s[r+1]&&(s[r+1]=0),s[r+1]+=s[r]/i|0,s[r]%=i)}return s.reverse()}return function(n,r,o,s,a){var l,c,h,d,u,p,g,f,v=n.indexOf("."),y=_,b=m;for(v>=0&&(d=k,k=0,n=n.replace(".",""),p=(f=new M(r)).pow(n.length-v),k=d,f.c=t(rt(Qe(p.c),p.e,"0"),10,o,e),f.e=f.c.length),h=d=(g=t(n,r,o,a?(l=S,e):(l=e,S))).length;0==g[--d];g.pop());if(!g[0])return l.charAt(0);if(v<0?--h:(p.c=g,p.e=h,p.s=s,g=(p=i(p,f,y,b,o)).c,u=p.r,h=p.e),v=g[c=h+y+1],d=o/2,u=u||c<0||null!=g[c+1],u=b<4?(null!=v||u)&&(0==b||b==(p.s<0?3:2)):v>d||v==d&&(4==b||u||6==b&&1&g[c-1]||b==(p.s<0?8:7)),c<1||!g[0])n=u?rt(l.charAt(1),-y,l.charAt(0)):l.charAt(0);else{if(g.length=c,u)for(--o;++g[--c]>o;)g[c]=0,c||(++h,g=[1].concat(g));for(d=g.length;!g[--d];);for(v=0,n="";v<=d;n+=l.charAt(g[v++]));n=rt(n,h,l.charAt(0))}return n}}(),i=function(){function e(e,t,i){var n,r,o,s,a=0,l=e.length,c=t%Xe,h=t/Xe|0;for(e=e.slice();l--;)a=((r=c*(o=e[l]%Xe)+(n=h*o+(s=e[l]/Xe|0)*c)%Xe*Xe+a)/i|0)+(n/Xe|0)+h*s,e[l]=r%i;return a&&(e=[a].concat(e)),e}function t(e,t,i,n){var r,o;if(i!=n)o=i>n?1:-1;else for(r=o=0;rt[r]?1:-1;break}return o}function i(e,t,i,n){for(var r=0;i--;)e[i]-=r,r=e[i]1;e.splice(0,1));}return function(n,r,o,s,a){var l,c,h,d,u,p,_,m,g,f,v,y,b,w,k,x,S,$=n.s==r.s?1:-1,R=n.c,C=r.c;if(!(R&&R[0]&&C&&C[0]))return new M(n.s&&r.s&&(R?!C||R[0]!=C[0]:C)?R&&0==R[0]||!C?0*$:$/0:NaN);for(g=(m=new M($)).c=[],$=o+(c=n.e-r.e)+1,a||(a=Ve,c=Je(n.e/Ge)-Je(r.e/Ge),$=$/Ge|0),h=0;C[h]==(R[h]||0);h++);if(C[h]>(R[h]||0)&&c--,$<0)g.push(1),d=!0;else{for(w=R.length,x=C.length,h=0,$+=2,(u=We(a/(C[0]+1)))>1&&(C=e(C,u,a),R=e(R,u,a),x=C.length,w=R.length),b=x,v=(f=R.slice(0,x)).length;v=a/2&&k++;do{if(u=0,(l=t(C,f,x,v))<0){if(y=f[0],x!=v&&(y=y*a+(f[1]||0)),(u=We(y/k))>1)for(u>=a&&(u=a-1),_=(p=e(C,u,a)).length,v=f.length;1==t(p,f,_,v);)u--,i(p,x<_?S:C,_,a),_=p.length,l=1;else 0==u&&(l=u=1),_=(p=C.slice()).length;if(_=10;$/=10,h++);D(m,o+(m.e=h+c*Ge-1)+1,s,d)}else m.e=c,m.r=+d;return m}}(),a=/^(-?)0([xbo])(?=\w[\w.]*$)/i,l=/^([^.]+)\.$/,c=/^\.([^.]+)$/,h=/^-?(Infinity|NaN)$/,d=/^\s*\+(?=[\w.])|^\s+|\s+$/g,r=function(e,t,i,n){var r,o=i?t:t.replace(d,"");if(h.test(o))e.s=isNaN(o)?null:o<0?-1:1;else{if(!i&&(o=o.replace(a,function(e,t,i){return r="x"==(i=i.toLowerCase())?16:"b"==i?2:8,n&&n!=r?e:t}),n&&(r=n,o=o.replace(l,"$1").replace(c,"0.$1")),t!=o))return new M(o,r);if(M.DEBUG)throw Error(je+"Not a"+(n?" base "+n:"")+" number: "+t);e.s=null}e.c=e.e=null},u.absoluteValue=u.abs=function(){var e=new M(this);return e.s<0&&(e.s=1),e},u.comparedTo=function(e,t){return et(this,new M(e,t))},u.decimalPlaces=u.dp=function(e,t){var i,n,r,o=this;if(null!=e)return tt(e,0,Ze),null==t?t=m:tt(t,0,8),D(new M(o),e+o.e+1,t);if(!(i=o.c))return null;if(n=((r=i.length-1)-Je(this.e/Ge))*Ge,r=i[r])for(;r%10==0;r/=10,n--);return n<0&&(n=0),n},u.dividedBy=u.div=function(e,t){return i(this,new M(e,t),_,m)},u.dividedToIntegerBy=u.idiv=function(e,t){return i(this,new M(e,t),0,1)},u.exponentiatedBy=u.pow=function(e,t){var i,n,r,o,s,a,l,c,h=this;if((e=new M(e)).c&&!e.isInteger())throw Error(je+"Exponent not an integer: "+z(e));if(null!=t&&(t=new M(t)),s=e.e>14,!h.c||!h.c[0]||1==h.c[0]&&!h.e&&1==h.c.length||!e.c||!e.c[0])return c=new M(Math.pow(+z(h),s?e.s*(2-it(e)):+z(e))),t?c.mod(t):c;if(a=e.s<0,t){if(t.c?!t.c[0]:!t.s)return new M(NaN);(n=!a&&h.isInteger()&&t.isInteger())&&(h=h.mod(t))}else{if(e.e>9&&(h.e>0||h.e<-1||(0==h.e?h.c[0]>1||s&&h.c[1]>=24e7:h.c[0]<8e13||s&&h.c[0]<=9999975e7)))return o=h.s<0&&it(e)?-0:0,h.e>-1&&(o=1/o),new M(a?1/o:o);k&&(o=qe(k/Ge+2))}for(s?(i=new M(.5),a&&(e.s=1),l=it(e)):l=(r=Math.abs(+z(e)))%2,c=new M(p);;){if(l){if(!(c=c.times(h)).c)break;o?c.c.length>o&&(c.c.length=o):n&&(c=c.mod(t))}if(r){if(0===(r=We(r/2)))break;l=r%2}else if(D(e=e.times(i),e.e+1,1),e.e>14)l=it(e);else{if(0===(r=+z(e)))break;l=r%2}h=h.times(h),o?h.c&&h.c.length>o&&(h.c.length=o):n&&(h=h.mod(t))}return n?c:(a&&(c=p.div(c)),t?c.mod(t):o?D(c,k,m,void 0):c)},u.integerValue=function(e){var t=new M(this);return null==e?e=m:tt(e,0,8),D(t,t.e+1,e)},u.isEqualTo=u.eq=function(e,t){return 0===et(this,new M(e,t))},u.isFinite=function(){return!!this.c},u.isGreaterThan=u.gt=function(e,t){return et(this,new M(e,t))>0},u.isGreaterThanOrEqualTo=u.gte=function(e,t){return 1===(t=et(this,new M(e,t)))||0===t},u.isInteger=function(){return!!this.c&&Je(this.e/Ge)>this.c.length-2},u.isLessThan=u.lt=function(e,t){return et(this,new M(e,t))<0},u.isLessThanOrEqualTo=u.lte=function(e,t){return-1===(t=et(this,new M(e,t)))||0===t},u.isNaN=function(){return!this.s},u.isNegative=function(){return this.s<0},u.isPositive=function(){return this.s>0},u.isZero=function(){return!!this.c&&0==this.c[0]},u.minus=function(e,t){var i,n,r,o,s=this,a=s.s;if(t=(e=new M(e,t)).s,!a||!t)return new M(NaN);if(a!=t)return e.s=-t,s.plus(e);var l=s.e/Ge,c=e.e/Ge,h=s.c,d=e.c;if(!l||!c){if(!h||!d)return h?(e.s=-t,e):new M(d?s:NaN);if(!h[0]||!d[0])return d[0]?(e.s=-t,e):new M(h[0]?s:3==m?-0:0)}if(l=Je(l),c=Je(c),h=h.slice(),a=l-c){for((o=a<0)?(a=-a,r=h):(c=l,r=d),r.reverse(),t=a;t--;r.push(0));r.reverse()}else for(n=(o=(a=h.length)<(t=d.length))?a:t,a=t=0;t0)for(;t--;h[i++]=0);for(t=Ve-1;n>a;){if(h[--n]=0;){for(i=0,u=y[r]%g,p=y[r]/g|0,o=r+(s=l);o>r;)i=((c=u*(c=v[--s]%g)+(a=p*c+(h=v[s]/g|0)*u)%g*g+_[o]+i)/m|0)+(a/g|0)+p*h,_[o--]=c%m;_[o]=i}return i?++n:_.splice(0,1),T(e,_,n)},u.negated=function(){var e=new M(this);return e.s=-e.s||null,e},u.plus=function(e,t){var i,n=this,r=n.s;if(t=(e=new M(e,t)).s,!r||!t)return new M(NaN);if(r!=t)return e.s=-t,n.minus(e);var o=n.e/Ge,s=e.e/Ge,a=n.c,l=e.c;if(!o||!s){if(!a||!l)return new M(r/0);if(!a[0]||!l[0])return l[0]?e:new M(a[0]?n:0*r)}if(o=Je(o),s=Je(s),a=a.slice(),r=o-s){for(r>0?(s=o,i=l):(r=-r,i=a),i.reverse();r--;i.push(0));i.reverse()}for((r=a.length)-(t=l.length)<0&&(i=l,l=a,a=i,t=r),r=0;t;)r=(a[--t]=a[t]+l[t]+r)/Ve|0,a[t]=Ve===a[t]?0:a[t]%Ve;return r&&(a=[r].concat(a),++s),T(e,a,s)},u.precision=u.sd=function(e,t){var i,n,r,o=this;if(null!=e&&e!==!!e)return tt(e,1,Ze),null==t?t=m:tt(t,0,8),D(new M(o),e,t);if(!(i=o.c))return null;if(n=(r=i.length-1)*Ge+1,r=i[r]){for(;r%10==0;r/=10,n--);for(r=i[0];r>=10;r/=10,n++);}return e&&o.e+1>n&&(n=o.e+1),n},u.shiftedBy=function(e){return tt(e,-9007199254740991,Ke),this.times("1e"+e)},u.squareRoot=u.sqrt=function(){var e,t,n,r,o,s=this,a=s.c,l=s.s,c=s.e,h=_+4,d=new M("0.5");if(1!==l||!a||!a[0])return new M(!l||l<0&&(!a||a[0])?NaN:a?s:1/0);if(0==(l=Math.sqrt(+z(s)))||l==1/0?(((t=Qe(a)).length+c)%2==0&&(t+="0"),l=Math.sqrt(+t),c=Je((c+1)/2)-(c<0||c%2),n=new M(t=l==1/0?"5e"+c:(t=l.toExponential()).slice(0,t.indexOf("e")+1)+c)):n=new M(l+""),n.c[0])for((l=(c=n.e)+h)<3&&(l=0);;)if(o=n,n=d.times(o.plus(i(s,o,h,1))),Qe(o.c).slice(0,l)===(t=Qe(n.c)).slice(0,l)){if(n.e0&&_>0){for(o=_%a||a,h=p.substr(0,o);o<_;o+=a)h+=c+p.substr(o,a);l>0&&(h+=c+p.slice(o)),u&&(h="-"+h)}n=d?h+(i.decimalSeparator||"")+((l=+i.fractionGroupSize)?d.replace(new RegExp("\\d{"+l+"}\\B","g"),"$&"+(i.fractionGroupSeparator||"")):d):h}return(i.prefix||"")+n+(i.suffix||"")},u.toFraction=function(e){var t,n,r,o,s,a,l,c,h,d,u,_,g=this,f=g.c;if(null!=e&&(!(l=new M(e)).isInteger()&&(l.c||1!==l.s)||l.lt(p)))throw Error(je+"Argument "+(l.isInteger()?"out of range: ":"not an integer: ")+z(l));if(!f)return new M(g);for(t=new M(p),h=n=new M(p),r=c=new M(p),_=Qe(f),s=t.e=_.length-g.e-1,t.c[0]=Ye[(a=s%Ge)<0?Ge+a:a],e=!e||l.comparedTo(t)>0?s>0?t:h:l,a=y,y=1/0,l=new M(_),c.c[0]=0;d=i(l,t,0,1),1!=(o=n.plus(d.times(r))).comparedTo(e);)n=r,r=o,h=c.plus(d.times(o=h)),c=o,t=l.minus(d.times(o=t)),l=o;return o=i(e.minus(n),r,0,1),c=c.plus(o.times(h)),n=n.plus(o.times(r)),c.s=h.s=g.s,u=i(h,r,s*=2,m).minus(g).abs().comparedTo(i(c,n,s,m).minus(g).abs())<1?[h,r]:[c,n],y=a,u},u.toNumber=function(){return+z(this)},u.toPrecision=function(e,t){return null!=e&&tt(e,1,Ze),R(this,e,t,2)},u.toString=function(e){var t,i=this,r=i.s,o=i.e;return null===o?r?(t="Infinity",r<0&&(t="-"+t)):t="NaN":(null==e?t=o<=g||o>=f?nt(Qe(i.c),o):rt(Qe(i.c),o,"0"):10===e&&$?t=rt(Qe((i=D(new M(i),_+o+1,m)).c),i.e,"0"):(tt(e,2,S.length,"Base"),t=n(rt(Qe(i.c),o,"0"),10,e,r,!0)),r<0&&i.c[0]&&(t="-"+t)),t},u.valueOf=u.toJSON=function(){return z(this)},u._isBigNumber=!0,u[Symbol.toStringTag]="BigNumber",u[Symbol.for("nodejs.util.inspect.custom")]=u.valueOf,null!=t&&M.set(t),M}(),st=class{key;left=null;right=null;constructor(e){this.key=e}},at=class extends st{constructor(e){super(e)}},lt=class{size=0;modificationCount=0;splayCount=0;splay(e){const t=this.root;if(null==t)return this.compare(e,e),-1;let i=null,n=null,r=null,o=null,s=t;const a=this.compare;let l;for(;;)if(l=a(s.key,e),l>0){let t=s.left;if(null==t)break;if(l=a(t.key,e),l>0&&(s.left=t.right,t.right=s,s=t,t=s.left,null==t))break;null==i?n=s:i.left=s,i=s,s=t}else{if(!(l<0))break;{let t=s.right;if(null==t)break;if(l=a(t.key,e),l<0&&(s.right=t.left,t.left=s,s=t,t=s.right,null==t))break;null==r?o=s:r.right=s,r=s,s=t}}return null!=r&&(r.right=s.left,s.left=o),null!=i&&(i.left=s.right,s.right=n),this.root!==s&&(this.root=s,this.splayCount++),l}splayMin(e){let t=e,i=t.left;for(;null!=i;){const e=i;t.left=e.right,e.right=t,t=e,i=t.left}return t}splayMax(e){let t=e,i=t.right;for(;null!=i;){const e=i;t.right=e.left,e.left=t,t=e,i=t.right}return t}_delete(e){if(null==this.root)return null;if(0!=this.splay(e))return null;let t=this.root;const i=t,n=t.left;if(this.size--,null==n)this.root=t.right;else{const e=t.right;t=this.splayMax(n),t.right=e,this.root=t}return this.modificationCount++,i}addNewRoot(e,t){this.size++,this.modificationCount++;const i=this.root;null!=i?(t<0?(e.left=i,e.right=i.right,i.right=null):(e.right=i,e.left=i.left,i.left=null),this.root=e):this.root=e}_first(){const e=this.root;return null==e?null:(this.root=this.splayMin(e),this.root)}_last(){const e=this.root;return null==e?null:(this.root=this.splayMax(e),this.root)}clear(){this.root=null,this.size=0,this.modificationCount++}has(e){return this.validKey(e)&&0==this.splay(e)}defaultCompare(){return(e,t)=>et?1:0}wrap(){return{getRoot:()=>this.root,setRoot:e=>{this.root=e},getSize:()=>this.size,getModificationCount:()=>this.modificationCount,getSplayCount:()=>this.splayCount,setSplayCount:e=>{this.splayCount=e},splay:e=>this.splay(e),has:e=>this.has(e)}}},ct=class e extends lt{root=null;compare;validKey;constructor(e,t){super(),this.compare=e??this.defaultCompare(),this.validKey=t??(e=>null!=e&&null!=e)}delete(e){return!!this.validKey(e)&&null!=this._delete(e)}deleteAll(e){for(const t of e)this.delete(t)}forEach(e){const t=this[Symbol.iterator]();let i;for(;i=t.next(),!i.done;)e(i.value,i.value,this)}add(e){const t=this.splay(e);return 0!=t&&this.addNewRoot(new at(e),t),this}addAndReturn(e){const t=this.splay(e);return 0!=t&&this.addNewRoot(new at(e),t),this.root.key}addAll(e){for(const t of e)this.add(t)}isEmpty(){return null==this.root}isNotEmpty(){return null!=this.root}single(){if(0==this.size)throw"Bad state: No element";if(this.size>1)throw"Bad state: Too many element";return this.root.key}first(){if(0==this.size)throw"Bad state: No element";return this._first().key}last(){if(0==this.size)throw"Bad state: No element";return this._last().key}lastBefore(e){if(null==e)throw"Invalid arguments(s)";if(null==this.root)return null;if(this.splay(e)<0)return this.root.key;let t=this.root.left;if(null==t)return null;let i=t.right;for(;null!=i;)t=i,i=t.right;return t.key}firstAfter(e){if(null==e)throw"Invalid arguments(s)";if(null==this.root)return null;if(this.splay(e)>0)return this.root.key;let t=this.root.right;if(null==t)return null;let i=t.left;for(;null!=i;)t=i,i=t.left;return t.key}retainAll(t){const i=new e(this.compare,this.validKey),n=this.modificationCount;for(const e of t){if(n!=this.modificationCount)throw"Concurrent modification during iteration.";this.validKey(e)&&0==this.splay(e)&&i.add(this.root.key)}i.size!=this.size&&(this.root=i.root,this.size=i.size,this.modificationCount++)}lookup(e){if(!this.validKey(e))return null;return 0!=this.splay(e)?null:this.root.key}intersection(t){const i=new e(this.compare,this.validKey);for(const e of this)t.has(e)&&i.add(e);return i}difference(t){const i=new e(this.compare,this.validKey);for(const e of this)t.has(e)||i.add(e);return i}union(e){const t=this.clone();return t.addAll(e),t}clone(){const t=new e(this.compare,this.validKey);return t.size=this.size,t.root=this.copyNode(this.root),t}copyNode(e){if(null==e)return null;const t=new at(e.key);return function e(t,i){let n,r;do{if(n=t.left,r=t.right,null!=n){const t=new at(n.key);i.left=t,e(n,t)}if(null!=r){const e=new at(r.key);i.right=e,t=r,i=e}}while(null!=r)}(e,t),t}toSet(){return this.clone()}entries(){return new ut(this.wrap())}keys(){return this[Symbol.iterator]()}values(){return this[Symbol.iterator]()}[Symbol.iterator](){return new dt(this.wrap())}[Symbol.toStringTag]="[object Set]"},ht=class{tree;path=new Array;modificationCount=null;splayCount;constructor(e){this.tree=e,this.splayCount=e.getSplayCount()}[Symbol.iterator](){return this}next(){return this.moveNext()?{done:!1,value:this.current()}:{done:!0,value:null}}current(){if(!this.path.length)return null;const e=this.path[this.path.length-1];return this.getValue(e)}rebuildPath(e){this.path.splice(0,this.path.length),this.tree.splay(e),this.path.push(this.tree.getRoot()),this.splayCount=this.tree.getSplayCount()}findLeftMostDescendent(e){for(;null!=e;)this.path.push(e),e=e.left}moveNext(){if(this.modificationCount!=this.tree.getModificationCount()){if(null==this.modificationCount){this.modificationCount=this.tree.getModificationCount();let e=this.tree.getRoot();for(;null!=e;)this.path.push(e),e=e.left;return this.path.length>0}throw"Concurrent modification during iteration."}if(!this.path.length)return!1;this.splayCount!=this.tree.getSplayCount()&&this.rebuildPath(this.path[this.path.length-1].key);let e=this.path[this.path.length-1],t=e.right;if(null!=t){for(;null!=t;)this.path.push(t),t=t.left;return!0}for(this.path.pop();this.path.length&&this.path[this.path.length-1].right===e;)e=this.path.pop();return this.path.length>0}},dt=class extends ht{getValue(e){return e.key}},ut=class extends ht{getValue(e){return[e.key,e.key]}},pt=e=>()=>e,_t=e=>{const t=e?(t,i)=>i.minus(t).abs().isLessThanOrEqualTo(e):pt(!1);return(e,i)=>t(e,i)?0:e.comparedTo(i)};function mt(e){const t=e?(t,i,n,r,o)=>t.exponentiatedBy(2).isLessThanOrEqualTo(r.minus(i).exponentiatedBy(2).plus(o.minus(n).exponentiatedBy(2)).times(e)):pt(!1);return(e,i,n)=>{const r=e.x,o=e.y,s=n.x,a=n.y,l=o.minus(a).times(i.x.minus(s)).minus(r.minus(s).times(i.y.minus(a)));return t(l,r,o,s,a)?0:l.comparedTo(0)}}var gt=e=>e,ft=e=>{if(e){const t=new ct(_t(e)),i=new ct(_t(e)),n=(e,t)=>t.addAndReturn(e),r=e=>({x:n(e.x,t),y:n(e.y,i)});return r({x:new ot(0),y:new ot(0)}),r}return gt},vt=e=>({set:e=>{yt=vt(e)},reset:()=>vt(e),compare:_t(e),snap:ft(e),orient:mt(e)}),yt=vt(),bt=(e,t)=>e.ll.x.isLessThanOrEqualTo(t.x)&&t.x.isLessThanOrEqualTo(e.ur.x)&&e.ll.y.isLessThanOrEqualTo(t.y)&&t.y.isLessThanOrEqualTo(e.ur.y),wt=(e,t)=>{if(t.ur.x.isLessThan(e.ll.x)||e.ur.x.isLessThan(t.ll.x)||t.ur.y.isLessThan(e.ll.y)||e.ur.y.isLessThan(t.ll.y))return null;const i=e.ll.x.isLessThan(t.ll.x)?t.ll.x:e.ll.x,n=e.ur.x.isLessThan(t.ur.x)?e.ur.x:t.ur.x;return{ll:{x:i,y:e.ll.y.isLessThan(t.ll.y)?t.ll.y:e.ll.y},ur:{x:n,y:e.ur.y.isLessThan(t.ur.y)?e.ur.y:t.ur.y}}},kt=(e,t)=>e.x.times(t.y).minus(e.y.times(t.x)),xt=(e,t)=>e.x.times(t.x).plus(e.y.times(t.y)),St=e=>xt(e,e).sqrt(),$t=(e,t,i)=>{const n={x:t.x.minus(e.x),y:t.y.minus(e.y)},r={x:i.x.minus(e.x),y:i.y.minus(e.y)};return kt(r,n).div(St(r)).div(St(n))},Mt=(e,t,i)=>{const n={x:t.x.minus(e.x),y:t.y.minus(e.y)},r={x:i.x.minus(e.x),y:i.y.minus(e.y)};return xt(r,n).div(St(r)).div(St(n))},Rt=(e,t,i)=>t.y.isZero()?null:{x:e.x.plus(t.x.div(t.y).times(i.minus(e.y))),y:i},Ct=(e,t,i)=>t.x.isZero()?null:{x:i,y:e.y.plus(t.y.div(t.x).times(i.minus(e.x)))},Tt=class e{point;isLeft;segment;otherSE;consumedBy;static compare(t,i){const n=e.comparePoints(t.point,i.point);return 0!==n?n:(t.point!==i.point&&t.link(i),t.isLeft!==i.isLeft?t.isLeft?1:-1:Et.compare(t.segment,i.segment))}static comparePoints(e,t){return e.x.isLessThan(t.x)?-1:e.x.isGreaterThan(t.x)?1:e.y.isLessThan(t.y)?-1:e.y.isGreaterThan(t.y)?1:0}constructor(e,t){void 0===e.events?e.events=[this]:e.events.push(this),this.point=e,this.isLeft=t}link(e){if(e.point===this.point)throw new Error("Tried to link already linked events");const t=e.point.events;for(let e=0,i=t.length;e{const n=i.otherSE;t.set(i,{sine:$t(this.point,e.point,n.point),cosine:Mt(this.point,e.point,n.point)})};return(e,n)=>{t.has(e)||i(e),t.has(n)||i(n);const{sine:r,cosine:o}=t.get(e),{sine:s,cosine:a}=t.get(n);return r.isGreaterThanOrEqualTo(0)&&s.isGreaterThanOrEqualTo(0)?o.isLessThan(a)?1:o.isGreaterThan(a)?-1:0:r.isLessThan(0)&&s.isLessThan(0)?o.isLessThan(a)?-1:o.isGreaterThan(a)?1:0:s.isLessThan(r)?-1:s.isGreaterThan(r)?1:0}}},Dt=class e{events;poly;_isExteriorRing;_enclosingRing;static factory(t){const i=[];for(let n=0,r=t.length;n0&&(e=i)}let t=e.segment.prevInResult(),i=t?t.prevInResult():null;for(;;){if(!t)return null;if(!i)return t.ringOut;if(i.ringOut!==t.ringOut)return i.ringOut?.enclosingRing()!==t.ringOut?t.ringOut:t.ringOut?.enclosingRing();t=i.prevInResult(),i=t?t.prevInResult():null}}},zt=class{exteriorRing;interiorRings;constructor(e){this.exteriorRing=e,e.poly=this,this.interiorRings=[]}addInterior(e){this.interiorRings.push(e),e.poly=this}getGeom(){const e=this.exteriorRing.getGeom();if(null===e)return null;const t=[e];for(let e=0,i=this.interiorRings.length;e0?(this.tree.delete(t),i.push(e)):(this.segments.push(t),t.prev=n)}else{if(n&&r){const e=n.getIntersection(r);if(null!==e){if(!n.isAnEndpoint(e)){const t=this._splitSafely(n,e);for(let e=0,n=t.length;e0)return-1;const n=t.comparePoint(e.rightSE.point);return 0!==n?n:-1}if(i.isGreaterThan(n)){if(s.isLessThan(a)&&s.isLessThan(c))return-1;if(s.isGreaterThan(a)&&s.isGreaterThan(c))return 1;const i=t.comparePoint(e.leftSE.point);if(0!==i)return i;const n=e.comparePoint(t.rightSE.point);return n<0?1:n>0?-1:1}if(s.isLessThan(a))return-1;if(s.isGreaterThan(a))return 1;if(r.isLessThan(o)){const i=t.comparePoint(e.rightSE.point);if(0!==i)return i}if(r.isGreaterThan(o)){const i=e.comparePoint(t.rightSE.point);if(i<0)return 1;if(i>0)return-1}if(!r.eq(o)){const e=l.minus(s),t=r.minus(i),h=c.minus(a),d=o.minus(n);if(e.isGreaterThan(t)&&h.isLessThan(d))return 1;if(e.isLessThan(t)&&h.isGreaterThan(d))return-1}return r.isGreaterThan(o)?1:r.isLessThan(o)||l.isLessThan(c)?-1:l.isGreaterThan(c)?1:e.idt.id?1:0}constructor(e,t,i,n){this.id=++Ot,this.leftSE=e,e.segment=this,e.otherSE=t,this.rightSE=t,t.segment=this,t.otherSE=e,this.rings=i,this.windings=n}static fromRing(t,i,n){let r,o,s;const a=Tt.comparePoints(t,i);if(a<0)r=t,o=i,s=1;else{if(!(a>0))throw new Error(`Tried to create degenerate segment at [${t.x}, ${t.y}]`);r=i,o=t,s=-1}const l=new Tt(r,!0),c=new Tt(o,!1);return new e(l,c,[n],[s])}replaceRightSE(e){this.rightSE=e,this.rightSE.segment=this,this.rightSE.otherSE=this.leftSE,this.leftSE.otherSE=this.rightSE}bbox(){const e=this.leftSE.point.y,t=this.rightSE.point.y;return{ll:{x:this.leftSE.point.x,y:e.isLessThan(t)?e:t},ur:{x:this.rightSE.point.x,y:e.isGreaterThan(t)?e:t}}}vector(){return{x:this.rightSE.point.x.minus(this.leftSE.point.x),y:this.rightSE.point.y.minus(this.leftSE.point.y)}}isAnEndpoint(e){return e.x.eq(this.leftSE.point.x)&&e.y.eq(this.leftSE.point.y)||e.x.eq(this.rightSE.point.x)&&e.y.eq(this.rightSE.point.y)}comparePoint(e){return yt.orient(this.leftSE.point,e,this.rightSE.point)}getIntersection(e){const t=this.bbox(),i=e.bbox(),n=wt(t,i);if(null===n)return null;const r=this.leftSE.point,o=this.rightSE.point,s=e.leftSE.point,a=e.rightSE.point,l=bt(t,s)&&0===this.comparePoint(s),c=bt(i,r)&&0===e.comparePoint(r),h=bt(t,a)&&0===this.comparePoint(a),d=bt(i,o)&&0===e.comparePoint(o);if(c&&l)return d&&!h?o:!d&&h?a:null;if(c)return h&&r.x.eq(a.x)&&r.y.eq(a.y)?null:r;if(l)return d&&o.x.eq(s.x)&&o.y.eq(s.y)?null:s;if(d&&h)return null;if(d)return o;if(h)return a;const u=((e,t,i,n)=>{if(t.x.isZero())return Ct(i,n,e.x);if(n.x.isZero())return Ct(e,t,i.x);if(t.y.isZero())return Rt(i,n,e.y);if(n.y.isZero())return Rt(e,t,i.y);const r=kt(t,n);if(r.isZero())return null;const o={x:i.x.minus(e.x),y:i.y.minus(e.y)},s=kt(o,t).div(r),a=kt(o,n).div(r),l=e.x.plus(a.times(t.x)),c=i.x.plus(s.times(n.x)),h=e.y.plus(a.times(t.y)),d=i.y.plus(s.times(n.y));return{x:l.plus(c).div(2),y:h.plus(d).div(2)}})(r,this.vector(),s,e.vector());return null===u?null:bt(n,u)?yt.snap(u):null}split(t){const i=[],n=void 0!==t.events,r=new Tt(t,!0),o=new Tt(t,!1),s=this.rightSE;this.replaceRightSE(o),i.push(o),i.push(r);const a=new e(r,s,this.rings.slice(),this.windings.slice());return Tt.comparePoints(a.leftSE.point,a.rightSE.point)>0&&a.swapEvents(),Tt.comparePoints(this.leftSE.point,this.rightSE.point)>0&&this.swapEvents(),n&&(r.checkForConsuming(),o.checkForConsuming()),i}swapEvents(){const e=this.rightSE;this.rightSE=this.leftSE,this.leftSE=e,this.leftSE.isLeft=!0,this.rightSE.isLeft=!1;for(let e=0,t=this.windings.length;e0){const e=i;i=n,n=e}if(i.prev===n){const e=i;i=n,n=e}for(let e=0,t=n.rings.length;e1===e.length&&e[0].isSubject;this._isInResult=i(e)!==i(t);break}}return this._isInResult}},Ht=class{poly;isExterior;segments;bbox;constructor(e,t,i){if(!Array.isArray(e)||0===e.length)throw new Error("Input geometry is not a valid Polygon or MultiPolygon");if(this.poly=t,this.isExterior=i,this.segments=[],"number"!=typeof e[0][0]||"number"!=typeof e[0][1])throw new Error("Input geometry is not a valid Polygon or MultiPolygon");const n=yt.snap({x:new ot(e[0][0]),y:new ot(e[0][1])});this.bbox={ll:{x:n.x,y:n.y},ur:{x:n.x,y:n.y}};let r=n;for(let t=1,i=e.length;tIt.run("union",e,t),qt=(e,...t)=>It.run("intersection",e,t),Wt=(e,...t)=>It.run("difference",e,t);yt.set;const jt=/^#[0-9a-fA-F]{6}$/;function Ut(e,t){return"string"==typeof e&&jt.test(e)?e:t}const Vt="(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])",Gt=new RegExp(`^rgb\\(${Vt}, ${Vt}, ${Vt}\\)$`);function Kt(e){if(!Array.isArray(e)||e.length<3)return null;const t=e.slice(0,3);if(!t.every(e=>"number"==typeof e&&Number.isFinite(e)))return null;const[i,n,r]=t.map(e=>Math.round(Math.min(255,Math.max(0,e))));return`rgb(${i}, ${n}, ${r})`}function Yt(e){const t=Math.max(0,Math.min(120,(e-40)/140*120));return`hsl(${Math.round(t)}, 85%, 55%)`}function Xt(e,t){if(!(Number.isFinite(e)&&t>0))return e;const i=Math.round(e/t)*t;return Math.abs(i-e)<=1e-9*t?e:i}function Zt(e,t,i,n=1/0){if(!(i>0&&e?.every(Number.isFinite)&&t?.every(Number.isFinite)))return[t[0],t[1]];const r=t[0]-e[0],o=t[1]-e[1];if(Math.abs(r)+Math.abs(o)<=1e-12)return[e[0],e[1]];const s=Math.PI/4;let a=Math.atan2(o,r);a<0&&(a+=2*Math.PI);const l=Math.floor(a/s+.5)%8,[c,h]=[[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]][l],d=c*c+h*h;let u=Math.max(0,Math.round((r*c+o*h)/(i*d)));if(Number.isFinite(n)&&n>=0){const t=(e,t)=>{if(!t)return 1/0;const r=t>0?n-e:e+n;return Math.max(0,Math.floor((r+1e-9*i)/i))};u=Math.min(u,t(e[0],c),t(e[1],h))}return[e[0]+c*u*i,e[1]+h*u*i]}function Jt(e,t){if(t){const t=e/2.54;let i=Math.floor(t/12),n=Math.round(t-12*i);return 12===n&&(i+=1,n=0),`${i}′ ${n}″`}return`${(e/100).toFixed(2)} m`}function Qt(e,t,i=1){const n=e[0].toFixed(i),r=e[1].toFixed(i),o=t[0].toFixed(i),s=t[1].toFixed(i),a=n=3?e.poly:e&&null!=e.x&&null!=e.y&&null!=e.w&&null!=e.h?[[e.x,e.y],[e.x+e.w,e.y],[e.x+e.w,e.y+e.h],[e.x,e.y+e.h]]:null}function ti(e){const t=[];for(const i of e||[])i?.poly?.length>=3?t.push({poly:i.poly.map(e=>e.join(",")).join(" ")}):i&&null!=i.x&&null!=i.y&&null!=i.w&&null!=i.h&&t.push({rect:{x:i.x,y:i.y,w:i.w,h:i.h,rx:.03*Math.min(i.w,i.h)}});return t}function ii(e){const t=[],i=new Set;for(const n of e||[]){const e=ei(n);if(e)for(let n=0;n=90?e-=180:e<-90&&(e+=180),n.step&&n.step>0){const i=Math.sqrt(d),o=Math.min(Math.max(n.length||0,0)/2,i/2);let a=Math.round(u*i/n.step)*n.step;Math.abs(u*i-i/2)<=n.step/2&&(a=i/2),a=Math.max(o,Math.min(i-o,a));const l=a/i;r={x:t+l*c,y:s+l*h,angle:e}}else r={x:p[0],y:p[1],angle:e}}}return r}function ri(e,t,i){let n=null,r=1/0;for(let o=0;o=r)continue;r=_;const m=Math.sqrt(u),g=(i>0?Math.max(0,Math.min(m,Math.round(p*m/i)*i)):p*m)/m;n=[s+g*h,a+g*d]}return n}function oi(e,t,i,n,r,o=1){const s=t*Math.PI/180,a=[Math.cos(s),Math.sin(s)];let l=null,c=o;for(const t of ii(n)){const i=[[t[0],t[1]],[t[2],t[3]]],n=t=>Math.abs(a[0]*(t[1]-e[1])-a[1]*(t[0]-e[0]));if(n(i[0])>o||n(i[1])>o)continue;const r=(i[0][0]-e[0])*a[0]+(i[0][1]-e[1])*a[1],s=(i[1][0]-e[0])*a[0]+(i[1][1]-e[1])*a[1],h=Math.min(r,s),d=Math.max(r,s),u=h>0?h:d<0?-d:0;u[e[0]+a[0]*t,e[1]+a[1]*t],g=(h+d)/2;return{wallA:m(h),wallB:m(d),sideA:p,sideB:_,midA:m((h-u)/2),midB:m((u+d)/2),wallCenter:m(g),centered:Math.abs(g)<=r}}function si(e,t,i=!1,n){if("passage"===e)return 1;if(null==t||"unavailable"===t||"unknown"===t)return"window"===e?0:1;const r="string"==typeof n?n.trim()?Number(n):NaN:Number(n),o=null!=n&&Number.isFinite(r)?Math.max(0,Math.min(1,r/100)):function(e){return["on","open","home","detected","playing","cleaning"].includes(String(e))}(t)?1:0;return i?1-o:o}function ai(e){const t=Number.isFinite(e)?Math.max(0,Math.min(1,e)):0;return Math.min(1,Math.max(0,.05*Math.round(t/.05)))}function li(e,t){return(Number.isFinite(e)&&e>0?e:0)*(Number.isFinite(t)?Math.max(0,Math.min(1,t)):0)}function ci(e){return"passage"===e.type?[]:[e.contact,e.lock].filter(e=>"string"==typeof e&&e.length>0)}function hi(e,t,i=200){const n=t.trim().toLowerCase();return(n?e.filter(e=>e.label.toLowerCase().includes(n)||e.value.toLowerCase().includes(n)):e).slice(0,Math.max(0,i))}function di(e,t,i=.001){return Math.abs(e[0]-t[0])e[1]!=l>e[1]&&e[0]<(a-o)*(e[1]-s)/(l-s)+o&&(i=!i)}return i}function pi(e,t,i){const n=i[0]-t[0],r=i[1]-t[1],o=n*n+r*r;let s=o?((e[0]-t[0])*n+(e[1]-t[1])*r)/o:0;return s=Math.max(0,Math.min(1,s)),Math.hypot(e[0]-(t[0]+s*n),e[1]-(t[1]+s*r))}function _i(e,t){if(!t||t.length<2)return null;let i=null,n=1/0;for(let r=0;rr&&s<-r||o<-r&&s>r)&&(a>r&&l<-r||a<-r&&l>r)}function yi(e,t=24){const i=e.map(e=>e[0]),n=e.map(e=>e[1]),r=Math.min(...i),o=Math.max(...i),s=Math.min(...n),a=Math.max(...n),l=Math.max(o-r,a-s)||1;let c=0,h=0,d=0;for(let t=0;t1e-9?[h/(3*c),d/(3*c)]:[(r+o)/2,(s+a)/2],p=(t,i)=>{const n=((t,i)=>{if(!ui([t,i],e))return-1/0;let n=1/0;for(let r=0;rm&&(m=c,_=[n,l])}if(_){const[e,i]=_,n=(o-r)/t,l=(a-s)/t;for(let t=-4;t<=4;t++)for(let r=-4;r<=4;r++){const o=e+n*t/4,s=i+l*r/4,a=p(o,s);a>m&&(m=a,_=[o,s])}}return _||bi(e)||e[0]}function bi(e,t=1e-6){if(!e||e.length<3)return null;const i=e.length,n=[e.reduce((e,t)=>e+t[0],0)/i,e.reduce((e,t)=>e+t[1],0)/i];if(gi(n,e,t))return n;for(let n=0;nki(e,t,i));return n.filter(e=>!n.some(t=>t!==e&&ki(t,e,i)))}function $i(e){if(!e||e.length<3)return 0;let t=0;for(let i=0;i[e[0],e[1]]),[e[0][0],e[0][1]]]]}function Ri(e,t){if(!e||!t||e.length<3||t.length<3)return null;const i=Bt(Mi(e),Mi(t));if(1!==i.length)return null;if(1!==i[0].length)return null;const n=i[0][0].slice(0,-1).map(e=>[e[0],e[1]]);return n.length>=3?n:null}function Ci(e,t,i){for(let n=0;n1&&di(i[0],i[i.length-1],t)&&i.pop(),i}function Di(e,t,i=1e-6){if(!e||e.length<3||!t||t.length<2)return null;const n=t[0],r=t[t.length-1];if(di(n,r,i))return null;const o=Ci(e,n,i),s=Ci(e,r,i);if(o<0||s<0)return null;const a=t.slice(1,-1);for(const t of a)if(!gi(t,e,i))return null;for(let i=0;i{const s=[t];let a=(n+1)%e.length;for(let t=0;t<=e.length&&(s.push(e[a]),a!==o);t++)a=(a+1)%e.length;return s.push(r),Ti(s,i)};let c,h;if(o===s){const s=Ti([...t],i);if(s.length<3||$i(s)<=i)return null;const a=[];for(let i=0;i=0?t:[...t].reverse();for(const e of i)a.push(e)}c=Ti(a,i),h=s}else c=Ti([...l(n,o,r,s),...[...a].reverse()],i),h=Ti([...l(r,s,n,o),...a],i);return c.length<3||h.length<3||$i(c)<=i||$i(h)<=i||Math.abs($i(c)+$i(h)-$i(e))>Math.max(i,1e-6*$i(e))?null:[c,h]}function zi(e,t,i){const[n,r]=e.split(":");return"device"===n?r:"entity"===n?"lg_"+r:t&&t.startsWith("v_")?t:i()}function Ai(e){return e.length?Math.round(e.reduce((e,t)=>e+t,0)/e.length):null}function Pi(e,t){if(t>e[2]/e[3]){const i=e[3],n=e[3]*t;return{x:e[0]-(n-e[2])/2,y:e[1],w:n,h:i}}const i=e[2],n=e[2]/t;return{x:e[0],y:e[1]-(n-e[3])/2,w:i,h:n}}function Fi(e,t,i,n){if(e.length<2)return;const r=t.x+n,o=t.x+t.w-n,s=t.y+n,a=t.y+t.h-n;for(let t=0;t<60;t++){let t=!1;for(let n=0;n=0)i=t.slice(0,r).trim(),n=t.slice(r+1).trim();else{const e=t.split(".");e.length>2&&(i=e.slice(0,2).join("."),n=e.slice(2).join("."))}return/^[a-z0-9_]+\.[a-z0-9_]+$/.test(i)?r>=0&&!n||n&&!/^[a-zA-Z0-9_.-]+$/.test(n)?null:n?{entity:i,attr:n}:{entity:i}:null}function Vi(e,t){const i=String(e??"").trim(),n=String(t??"").trim(),r=Ui(n?`${i}:${n}`:i);return r?`{${r.entity}${r.attr?`:${r.attr}`:""}}`:""}function Gi(e,t,i){const n=String(t??"").trim();if(!n)return null;const r=e?.states?.[n];if(!r)return null;const o=String(i??"").trim(),s=e=>e.slice(0,60);if(o){const t=function(e){if(null==e)return null;if(Array.isArray(e)){const t=e.map(e=>null==e?"":String(e)).join(", ");return t?t.slice(0,60):null}if("object"==typeof e)return null;const t=String(e);return""===t?null:t.slice(0,60)}(r.attributes?.[o]);if(null===t)return null;const i=e?.formatEntityAttributeValue;if("function"==typeof i)try{const t=i.call(e,r,o);if("string"==typeof t&&""!==t)return{text:s(t),formatted:!0}}catch{}return{text:t,formatted:!1}}const a=r.state;if(null==a||""===a)return null;const l=e?.formatEntityState;if("function"==typeof l)try{const t=l.call(e,r);if("string"==typeof t&&""!==t)return{text:s(t),formatted:!0}}catch{}return{text:s(String(a)),formatted:!1}}function Ki(e,t,i){const n=String(t??"").trim(),r=String(i??"").trim()||n;if(!r)return e.text;const o=e.formatted&&n?function(e,t){if(!t)return e;const i=e.replace(/\s+$/,"");return i.endsWith(t)?i.slice(0,i.length-t.length).replace(/\s+$/,""):e}(e.text,n):e.text;return`${o} ${r}`}function Yi(e,t){const i=(t?.entity||"").trim();if(!i)return"";const n=e?.states?.[i],r=n?.state;if(!n||null==r||""===r||"unavailable"===r||"unknown"===r)return Wi;const o=(t?.attr||"").trim(),s=Gi(e,i,o||null);if(null===s)return Wi;return Ki(s,o?"":String(n.attributes?.unit_of_measurement??"").trim(),t?.unit)}function Xi(e,t,i,n=()=>!0){const r=e??"";let o=!1;const s=r.replace(/\{([^{}\r\n]+)\}/g,(e,t)=>{const r=Ui(t);return r?(o=!0,n(r.entity||"")?Yi(i,r):Wi):e});if(o)return s;const a=(t?.entity||"").trim();if(!a)return r;if(!n(a)){const e=r.indexOf(ji);return e>=0?r.slice(0,e)+Wi+r.slice(e+2):r?`${r} ${Wi}`:Wi}const l=Yi(i,t),c=r.indexOf(ji);return c>=0?r.slice(0,c)+l+r.slice(c+2):r?`${r} ${l}`:l}const Zi=20;function Ji(e){const t=Number(e?.scale);if(Number.isFinite(t)&&t>0)return Math.min(20,Math.max(.15,t));return{s:.7,m:1,l:1.5}[String(e?.size??"")]??1}function Qi(e,t){if(!t)return e;let i=e;for(const[e,n]of Object.entries(t))i=i.split("{"+e+"}").join(String(n));return i}const en="#55606c",tn=.55,nn=20,rn=25,on={c:"#607d8b",a:.18};function sn(e,t=on){const i=e&&"object"==typeof e?e:null,n=i?.a;return{c:Ut(i?.c,t.c),a:"number"==typeof n&&Number.isFinite(n)?Math.min(1,Math.max(0,n)):t.a}}function an(e,t){const i=sn(e),n=t?.settings?.custom_fill;return n&&"object"==typeof n?sn(n,i):i}function ln(e){const t=e?.settings||{},i=!e?.plan_url,n="glow"===t.fill_mode;return{showBorders:t.show_borders??i,showNames:t.show_names??i,color:Ut(t.room_color,en),opacity:"number"==typeof t.room_opacity?Math.min(1,Math.max(0,t.room_opacity)):.55,fill:["lqi","light","temp","custom"].includes(t.fill_mode)?t.fill_mode:"none",customFill:sn(t.custom_fill),glow:"boolean"==typeof t.glow_enabled?t.glow_enabled:n,tempMin:"number"==typeof t.temp_min?t.temp_min:20,tempMax:"number"==typeof t.temp_max?t.temp_max:25,showLqi:"boolean"==typeof t.show_lqi?t.show_lqi:null,cardFontScale:"number"==typeof t.card_font_scale&&t.card_font_scale>0?Math.min(3,Math.max(.5,t.card_font_scale)):1,labelTemp:!0===t.label_temp,labelHum:!0===t.label_hum,labelLqi:!0===t.label_lqi,labelLight:!0===t.label_light,bgColor:Ut(t.bg_color,null),hideDecor:!0===t.hide_decor,hideOpenings:!0===t.hide_openings}}function cn(e,t){if(t.bgColor)return t.bgColor;const i=e?.bg_color;return Ut(i,"")}function hn(e){return!1!==e?.show_room_tooltip}const dn={light_on:{c:"#ffd45c",a:.18},light_off:{c:"#9aa0a6",a:.14},light_none:{c:"#6b7480",a:0},temp_cold:{c:"#4fc3f7",a:.18},temp_ok:{c:"#66d17a",a:.18},temp_hot:{c:"#ffd45c",a:.18},lqi_low:{c:"#f25a4a",a:.18},lqi_high:{c:"#4bd28f",a:.18},glow_base:{c:"#0d1b2a",a:.5},glow_light:{c:"#ffd9a0",a:.85},wall_fill:{c:"#ffffff",a:1}};function un(e){const t={},i=e?.fill_colors||{};for(const e of Object.keys(dn)){const n=dn[e],r=i[e];t[e]={c:Ut(r?.c,n.c),a:r&&"number"==typeof r.a?Math.min(1,Math.max(0,r.a)):n.a}}return t}function pn(e,t,i){const n=Math.min(1,Math.max(0,i)),r=[1,3,5].map(t=>parseInt(e.slice(t,t+2),16)),o=[1,3,5].map(e=>parseInt(t.slice(e,e+2),16)),s=r.map((e,t)=>Math.round(e+(o[t]-e)*n));return"#"+s.map(e=>e.toString(16).padStart(2,"0")).join("")}function _n(e,t,i,n,r,o,s,a=on){const l=function(e,t,i,n,r,o,s,a=on){if("custom"===e)return sn(a);if("lqi"===e){if(null==t)return null;const e=(t-40)/140;return{c:pn(s.lqi_low.c,s.lqi_high.c,e),a:s.lqi_low.a+(s.lqi_high.a-s.lqi_low.a)*Math.min(1,Math.max(0,e))}}if("light"===e)return"none"===i?s.light_none.a>0?s.light_none:null:"on"===i?s.light_on:s.light_off;if("temp"===e){if(null==n)return null;const e=Math.min(r,o),t=Math.max(r,o);return nt?s.temp_hot:s.temp_ok}return null}(e,t,i,n,r,o,s,a);return l?{color:l.c,opacity:l.a,mode:e}:null}const mn={blind:["mdi:blinds","mdi:blinds-open"],shade:["mdi:blinds","mdi:blinds-open"],shutter:["mdi:window-shutter","mdi:window-shutter-open"],curtain:["mdi:curtains-closed","mdi:curtains"],window:["mdi:window-closed","mdi:window-open"],awning:["mdi:awning-outline","mdi:awning"],door:["mdi:door-closed","mdi:door-open"],garage:["mdi:garage","mdi:garage-open"],gate:["mdi:gate","mdi:gate-open"],damper:["mdi:circle-slice-8","mdi:circle-outline"]},gn=[["mdi:roller-shade-closed","mdi:roller-shade"],["mdi:blinds-horizontal-closed","mdi:blinds-horizontal"],["mdi:garage-variant","mdi:garage-open-variant"],["mdi:door","mdi:door-open"]];function fn(e){for(const t of[...Object.values(mn),...gn])if(e===t[0]||e===t[1])return t;return null}function vn(e,t,i,n,r){if(!n||"unavailable"===n||"unknown"===n)return e;if(r){const i="cover"===t?fn(e):null;return i?"closed"===n?i[0]:i[1]:e}if("binary_sensor"===t){if("door"===i)return"on"===n?"mdi:door-open":"mdi:door-closed";if("window"===i)return"on"===n?"mdi:window-open":"mdi:window-closed";if("garage_door"===i)return"on"===n?"mdi:garage-open-variant":"mdi:garage-variant"}if("cover"===t){const t=mn[String(i||"")];if(t)return"closed"===n?t[0]:t[1];const r=fn(e);return r?"closed"===n?r[0]:r[1]:e}return"lock"===t?"locked"===n?"mdi:lock":"mdi:lock-open-variant":"light"===t&&"mdi:lightbulb"===e&&"on"===n?"mdi:lightbulb-on":e}function yn(e){const t=Math.min(4e4,Math.max(1e3,e))/100,i=t<=66?255:329.698727446*Math.pow(t-60,-.1332047592),n=t<=66?99.4708025861*Math.log(t)-161.1195681661:288.1221695283*Math.pow(t-60,-.0755148492),r=t>=66?255:t<=19?0:138.5177312231*Math.log(t-10)-305.0447927307,o=e=>Math.round(Math.min(255,Math.max(0,e)));return[o(i),o(n),o(r)]}const bn=1/2.2;function wn(e){const t=/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/.exec(e);return t?"#"+t.slice(1).map(e=>Math.min(255,Number(e)).toString(16).padStart(2,"0")).join(""):null}function kn(e){if(!e||"object"!=typeof e||Array.isArray(e))return null;const t=e;if(Object.keys(t).some(e=>"c"!==e&&"bri"!==e))return null;const i=Ut(t.c,null);return i?void 0===t.bri||null===t.bri?{c:i}:"number"!=typeof t.bri||!Number.isFinite(t.bri)||t.bri<.01||t.bri>1?null:{c:i,bri:t.bri}:null}function xn(e,t,i){const n=kn(t),r=e?.attributes||{},o=n?.bri??function(e){const t=e?.attributes?.brightness,i="number"==typeof t?t:"string"==typeof t&&""!==t.trim()?Number(t):Number.NaN;return Number.isFinite(i)?Math.max(0,Math.min(1,i/255)):1}(e);if(n)return{c:n.c,bri:o};const s=Kt(r.rgb_color);if(s)return{c:wn(s)||Ut(i,"#ffd9a0"),bri:o};const a=Number(r.color_temp_kelvin)||(Number(r.color_temp)>0?1e6/Number(r.color_temp):NaN);return Number.isFinite(a)&&a>0?{c:(l=yn(a),"#"+l.slice(0,3).map(e=>Math.min(255,Math.max(0,Math.round(Number(e)||0))).toString(16).padStart(2,"0")).join("")),bri:o}:{c:Ut(i,"#ffd9a0"),bri:o};var l}function Sn(e,t,i){return"on"===e?.state?xn(e,t,i):null}function $n(e,t=1){const i=Math.max(0,Math.min(1,Number.isFinite(e)?e:1)),n=.7*Math.max(0,Math.min(1,Number.isFinite(t)?t:1))*(.4+.6*Math.pow(i,bn));return Math.max(0,Math.min(1,n))}function Mn(e){return e.startsWith("light.")||e.startsWith("switch.")}function Rn(e,t,i=1e-6){const n=[];if(!e||!t||e.length<3||t.length<3)return n;for(let r=0;ru||l>u)continue;const p=(r[0]-o[0])*h+(r[1]-o[1])*d,_=(s[0]-o[0])*h+(s[1]-o[1])*d,m=Math.max(0,Math.min(p,_)),g=Math.min(c,Math.max(p,_));g-m>i&&n.push([o[0]+h*m,o[1]+d*m,o[0]+h*g,o[1]+d*g])}}return n}function Cn(e,t,i=1e-6){const n=[];for(const r of e){const e=[r[0],r[1]],o=[r[2],r[3]],s=o[0]-e[0],a=o[1]-e[1],l=Math.hypot(s,a);if(lo||r>o)continue;const s=(n[0]-e[0])*c+(n[1]-e[1])*h,a=(n[2]-e[0])*c+(n[3]-e[1])*h,u=Math.max(0,Math.min(s,a)),p=Math.min(l,Math.max(s,a));p-u>i&&d.push([u,p])}if(!d.length){n.push([e[0],e[1],o[0],o[1]]);continue}d.sort((e,t)=>e[0]-t[0]);let u=0;for(const[t,r]of d)t-u>i&&n.push([e[0]+c*u,e[1]+h*u,e[0]+c*t,e[1]+h*t]),u=Math.max(u,r);l-u>i&&n.push([e[0]+c*u,e[1]+h*u,o[0],o[1]])}return n}function Tn(e,t,i=1e-6){const n=[];for(let t=0;t{if("string"!=typeof e||!e)return;const i=Pn(e);i.startsWith("/api/houseplan/content/")&&t.add(i)};for(const t of e?.spaces||[]){i(t?.plan_url);for(const e of t?.markers||[])for(const t of e?.pdfs||[])i(t?.url)}for(const t of e?.markers||[])for(const e of t?.pdfs||[])i(e?.url);return t}function Pn(e){return e?e.startsWith("/houseplan_files/plans/")?"/api/houseplan/content/plans/_/"+e.slice(23):e.startsWith("/houseplan_files/files/")?"/api/houseplan/content/files/"+e.slice(23):e:""}function Fn(e,t){const i=t?.settings?.fill_mode;return"none"===i||"lqi"===i||"light"===i||"temp"===i||"custom"===i?i:e}function In(e,t){const i=t?.settings;return"boolean"==typeof i?.glow?i.glow:"glow"===i?.fill_mode||e}function On(e,t,i,n){if(!t||!i||t===i)return e;const r="/files/"+t+"/",o="/files/"+i+"/";return e.map(e=>{if(!e.url.includes(r))return e;const t=e.url.split(r)[1]||"",[i,s]=[t.split("?")[0],t.includes("?")?"?"+t.split("?")[1]:""];if(n){const t=n[decodeURIComponent(i)]??n[i];return t?{...e,url:e.url.split(r+i)[0]+o+encodeURIComponent(t)+s}:e}return{...e,url:e.url.split(r).join(o)}})}function En(e,t=1){const i=Number(e);return Number.isFinite(i)&&i>0?Math.min(3,Math.max(.5,i)):t}function Hn(e,t,i){let n=null,r=null;for(const o of t){if(!(Math.abs(o[0]-e[0])<1e-6&&Math.abs(o[1]-e[1])<1e-6)){if(Math.abs(o[0]-e[0])<=i){const t=Math.abs(o[1]-e[1]);t>1e-6&&(!n||t1e-6&&(!r||t"number"==typeof e&&Number.isFinite(e),Zn=(e,t,i)=>Math.min(i,Math.max(t,e));function Jn(e){return e.elevation<=-6?"night":e.elevation>=6?"day":e.rising?"dawn":"dusk"}function Qn(e){const t=(Math.floor(Number(e)||0)%1440+1440)%1440;return t>=300&&t<480?"dawn":t>=480&&t<1080?"day":t>=1080&&t<1260?"dusk":"night"}function er(e){const t=Jn(e),i=e.azimuth*Math.PI/180;return{sunX:50-42*Math.sin(i),sunY:78-Zn(e.elevation,0,90)/90*64,sunOpacity:"night"===t?0:Zn((e.elevation+6)/12,0,1)}}function tr(e){const t=(Math.floor(Number(e)||0)%1440+1440)%1440;if(t<300||t>=1260)return{sunX:50,sunY:78,sunOpacity:0};const i=(t-300)/960,n=(t-300)/120,r=(1260-t)/120;return{sunX:8+84*i,sunY:78-64*Math.sin(i*Math.PI),sunOpacity:Math.max(.18,Math.min(n,r,1))}}function ir(e,t=new Date){const i=function(e){const t=e?.states?.["sun.sun"]?.attributes;return t&&Xn(t.azimuth)&&Xn(t.elevation)&&"boolean"==typeof t.rising?{azimuth:Gn(t.azimuth),elevation:t.elevation,rising:t.rising}:null}(e);if(i)return{phase:Jn(i),source:"sun",...er(i)};const n="number"==typeof t?t:function(e=new Date){return 60*e.getHours()+e.getMinutes()}(t);return{phase:Qn(n),source:"clock",...tr(n)}}function nr(e){return`${e.source}|${e.phase}|${e.sunX.toFixed(2)}|${e.sunY.toFixed(2)}|`+e.sunOpacity.toFixed(3)}const rr=[[-90,"#070c14"],[-12,"#070c14"],[-4,"#131a28"],[0,"#4a3527"],[10,"#e8ddcf"],[30,"#ffffff"],[90,"#ffffff"]],or=e=>Math.min(1,Math.max(0,e));function sr(e,t,i=6){const n=e.angle*Math.PI/180,r=[Math.sin(n),-Math.cos(n)],o=n=>{const o=[e.x+r[0]*i*n,e.y+r[1]*i*n];return t.find(e=>e.poly.length>=3&&ui(o,e.poly))||null},s=o(1),a=o(-1);return s&&a?null:s||a?s?{normal:[-r[0],-r[1]],roomId:s.id}:{normal:r,roomId:a.id}:null}function ar(e,t,i){return i>0&&e[0]*t[0]+e[1]*t[1]>.05}function lr(e,t,i,n){return[[e[0],e[1]],[t[0],t[1]],[t[0]+i[0]*n,t[1]+i[1]*n],[e[0]+i[0]*n,e[1]+i[1]*n]]}function cr(e,t){try{const i=qt([[...e.map(e=>[e[0],e[1]]),[e[0][0],e[0][1]]]],[[...t.map(e=>[e[0],e[1]]),[t[0][0],t[0][1]]]]),n=[];for(const e of i){const t=e?.[0];!Array.isArray(t)||t.length<4||n.push(t.slice(0,t.length-1).map(e=>[e[0],e[1]]))}return n}catch{return[]}}function hr(e,t,i,n,r,o,s){if(!(n>0))return[];const a=Kn(i,r),l=[-a[0],-a[1]],c=function(e){const t=Math.min(90,Math.max(0,e));return.7*(.8+1.7*Math.pow(1-t/90,1.6))}(n),h=[];for(const i of t){if(!(i.length>0))continue;const t=sr(i,e);if(!t||!ar(t.normal,a,n))continue;const r=e.find(e=>e.id===t.roomId);if(!r)continue;const d=o&&o[t.roomId]||r.poly,u=i.angle*Math.PI/180,p=i.length/2,_=[-t.normal[0],-t.normal[1]],m=Math.max(0,s?.[i.id]||0),g=i.x+_[0]*m/2,f=i.y+_[1]*m/2,v=Math.cos(u)*p,y=Math.sin(u)*p,b=[g-v,f-y],w=[g+v,f+y],k=c*i.length,x=cr(lr(b,w,l,k),d);if(!x.length)continue;const S=l[0]*_[0]+l[1]*_[1];h.push({openingId:i.id,roomId:t.roomId,polys:x,a:b,b:w,dir:l,len:k,normal:_,depth:k*S})}return h}const dr=e=>"number"==typeof e&&Number.isInteger(e)&&e>=0&&e<=359?e:null;function ur(e,t){const i=dr(t?.north_deg);return null!==i?i:dr(e?.north_deg)}function pr(e,t){const i=e=>"static"===e||"daynight"===e?e:null;return i(t?.bg_mode)??i(e?.bg_mode)??"static"}function _r(e,t){const i=t?.sun_rays;return"boolean"==typeof i?i:!0===e?.sun_rays}function mr(e){const t=e?.states?.["sun.sun"]?.attributes,i=Number(t?.azimuth),n=Number(t?.elevation);return Number.isFinite(i)&&Number.isFinite(n)?{azimuth:i,elevation:n}:null}const gr=["dawn","day","dusk","night"];function fr(e){if(!e)return"";const t=Yn[e.phase];return[`--hp-day-cycle-outline-near:${t.outlineNear}`,`--hp-day-cycle-outline-mid:${t.outlineMid}`,`--hp-day-cycle-outline-far:${t.outlineFar}`].join(";")}function vr(e,t=1){if(!e)return V;const i=[`--hp-day-cycle-sun-x:${e.sunX.toFixed(2)}%`,`--hp-day-cycle-sun-y:${e.sunY.toFixed(2)}%`,`--hp-day-cycle-sun-opacity:${e.sunOpacity.toFixed(3)}`,`opacity:${Math.min(1,Math.max(0,t)).toFixed(4)}`].join(";");return W` - ${this._canEdit&&!this._kiosk?W`
+ style=${z?`opacity:${z.toolbarContentOpacity}`:V}> ${this._editorRuntime?"plan"===D?this._renderMarkupBar():"devices"===D?this._renderDevicesBar():this._renderDecorBar():V}
`:V} -
this._markupClick(e)} @wheel=${e=>this._onWheel(e)} @pointerdown=${e=>{this._notePointer(e),this._stagePointerDown(e)}} @@ -5484,7 +5484,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
- ${d&&M?.structural?j` - ${Me(d&&M?.structural?j`
- ${this._wallDialog?W`
${this._renderWallThickDialog()}
`:V} + ${this._wallDialog?j`
${this._renderWallThickDialog()}
`:V}
${this._renderFarHint()} ${this._renderHomeArrow(this._baseVb(h,x))} ${this._renderEditorRuntimeLoading()} ${this._renderRecoveryOverlay()} - ${this._booting||this._bootFading?W` @@ -5627,7 +5627,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e ${this._deviceInbox&&this._editorRuntime?this._renderDeviceInbox():V} ${this._markerDialog&&this._editorRuntime?this._renderMarkerDialog():V} ${this._backdropGuard?this._editorRuntime?this._editorRuntime._renderBackdropGuard():this._onboardingRuntime?._renderBackdropGuard()??V:V} - ${this._vacCalConfirm&&this._editorRuntime?W`{this._vacCalConfirm?.busy||(this._vacCalConfirm=null)}}> @@ -5655,11 +5655,11 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e ${this._backupImportDialog&&this._editorRuntime?this._renderBackupImportDialog():V} ${this._importDialog&&this._onboardingRuntime?this._renderImportDialog():V} - ${this._kiosk&&!this._hasFixedFloor&&this._kioskDots&&this._model.length>1?W`
- ${this._model.map(e=>W``)} + ${this._kiosk&&!this._hasFixedFloor&&this._kioskDots&&this._model.length>1?j`
+ ${this._model.map(e=>j``)}
`:V} ${this._kioskDialog?this._renderKioskDialog():V} - ${this._vacFit?W`
+ ${this._vacFit?j`
${this._t("vac.fit_hint")} @@ -5670,12 +5670,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
`:V} - ${this._tapConfirm?W`this._tapConfirm=null}>
- ${"run"===this._tapConfirm.kind?W`

${this._tapConfirm.text}

`:this._tapConfirm.lines.map((e,t)=>W` + ${"run"===this._tapConfirm.kind?j`

${this._tapConfirm.text}

`:this._tapConfirm.lines.map((e,t)=>j`

${e}

`)}
@@ -5686,18 +5686,18 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
`:V} - ${this._toast?W``:V} + ${this._toast?j``:V} - `;var B}_vacCandidateStatus(e,t,i=this._planHass){const n=this._bindingStatus("entity:"+e);if("ha_disabled"===n.kind)return"disabled";if("orphaned"===n.kind)return"missing";if("unverified"===n.kind)return"unverified";const r=i?.states?.[e];return"unavailable"===r?.state?"unavailable":t?.hasPosition?"ok":"unsupported"}_vacOpenAllCameras(e){const t=this._haRegistry.entities||{},i=[];for(const[e,n]of Object.entries(this.hass?.states||{})){if(!e.startsWith("camera."))continue;const r=vc(e,n,t[e]);r&&i.push(r)}this._vacAllCameraCache={devId:e.id,candidates:i},this._vacAllCamerasFor=e.id}_vacSourceResolution(e,t=!1,i=this._planHass){const n=e.marker?.vacuum,r="string"==typeof n?.source&&!!n.source,o=new Set(e.entities||[]),s=new Set(o);r&&s.add(n.source);const a=i?.entities||{},l=[];for(const e of s){const t=i?.states?.[e],o=vc(e,t,a[e]);o?l.push(o):r&&e===n.source&&l.push({entityId:e,name:String(t?.attributes?.friendly_name||e),platform:a[e]?.platform?String(a[e].platform):null,category:e.startsWith("camera.")?"camera":"partial",hasPosition:!1,hasRooms:!1,hasPath:!1,hasMapId:!1,score:0})}if(t&&this._vacAllCameraCache?.devId===e.id){const e=new Set(l.map(e=>e.entityId));for(const t of this._vacAllCameraCache.candidates)e.has(t.entityId)||l.push(t)}const c={};for(const e of l)c[e.entityId]=this._vacCandidateStatus(e.entityId,e,i);return function(e,t,i,n){const r="string"==typeof e&&e.length>0,o=new Set(t),s=Array.from(i).sort((t,i)=>r&&t.entityId===e?-1:r&&i.entityId===e?1:i.score-t.score||t.entityId.localeCompare(i.entityId));if(r){const t=s.find(t=>t.entityId===e);return{entityId:e,status:n[e]||(t?.hasPosition?"ok":"unverified"),pinned:!0,candidates:s}}const a=s.find(e=>o.has(e.entityId)&&e.hasPosition&&"ok"===n[e.entityId]);return a?{entityId:a.entityId,status:"ok",pinned:!1,candidates:s}:{entityId:null,status:"none",pinned:!1,candidates:s}}(n?.source,o,l,c)}_vacSource(e,t=this._planHass){if(!1===e.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(e,!1,t);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(e){return e.primary?.startsWith("vacuum.")?e.primary:(e.entities||[]).find(e=>e.startsWith("vacuum."))||null}_isVacDev(e){return!!this._vacEntity(e)}_activitySourceKey(e){return this._activitySnapshot(e).sourceKey}_activitySnapshot(e,t=cd(this._planHass,this._devices,null,this._virtualLights)){const i=xp(this._planHass,e,this._devices,t,this._fullRegistryHass);return{samples:i.samples,sourceKey:Mp(this._planHass,e,i)}}_stampActivity(e,t,i){let n=this._activityRt.get(e);n||(n=vm(i||"",[]),this._activityRt.set(e,n)),null!=i&&(n.sources=i),bm(n,t,Date.now(),window.clearTimeout.bind(window),e=>window.setTimeout(()=>this.requestUpdate(),e))}_syncActivityRuntime(){const e=new Map;if(!this.hass)return e;if(!1===this._config?.live_states){for(const e of this._activityRt.values())clearTimeout(e.timer);return this._activityRt.clear(),e}const t=new Set,i=cd(this._planHass,this._devices,null,this._virtualLights);for(const n of this._devices){if(n.hidden)continue;if("icon_ripple"!==Ei(n.marker?.display))continue;t.add(n.id);const r=this._activitySnapshot(n,i);e.set(n.id,r);const{samples:o,sourceKey:s}=r;let a=this._activityRt.get(n.id);a?a.sources!==s&&ym(a,s,o,window.clearTimeout.bind(window)):(a=vm(s,o),this._activityRt.set(n.id,a))}for(const[e,i]of this._activityRt)t.has(e)||(clearTimeout(i.timer),this._activityRt.delete(e));return e}_activityTick(){if(!this.hass)return;const e=this._syncActivityRuntime();for(const t of this._devices){if(t.hidden)continue;if("icon_ripple"!==Ei(t.marker?.display))continue;const i=e.get(t.id)||this._activitySnapshot(t),{samples:n,sourceKey:r}=i,o=this._activityRt.get(t.id);if(!o||o.sources!==r)continue;const s=wm(o,n,window.clearTimeout.bind(window));s&&this._stampActivity(t.id,s,r)}}_vacTick(){if(this.hass)for(const e of this._devices){if(e.hidden||!this._isVacDev(e))continue;if("static_icon"===Ei(e.marker?.display)){this._vacRt.delete(e.id);continue}const t=this._vacSource(e);if(!t)continue;const i=this._vacEntity(e),n=xc(this.hass.states[i||""]?.state),r=mc(this.hass.states[t]?.attributes);let o=this._vacRt.get(e.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(e.id,o)),n&&!o.moving&&(o.trail=[],o.lastPos=null);const s="never"!==Tc(e.marker?.vacuum)&&!r?.path.length;!n&&o.moving&&(o.endedTs=Date.now(),s&&o.lastPos&&(o.trail=kc(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=n;const a=r?.pos;if(n&&a){const e=a.x+":"+a.y;if(e!==o.lastKey){const t=Date.now();o.jump=o.lastTs>0&&t-o.lastTs>1e4,o.lastKey=e,o.lastTs=t,s&&o.lastPos&&(o.trail=kc(o.trail,o.lastPos,40)),o.lastPos=[a.x,a.y]}}}}_vacEnsureMarker(e){const t=this._serverCfg;if(!t)return null;t.markers=t.markers||[];const i=t.markers.find(t=>t.id===e.id);if(i)return i;if("device"!==e.bindingKind&&"entity"!==e.bindingKind||!e.bindingRef)return null;const n={id:e.id,binding:e.bindingKind+":"+e.bindingRef,space:e.space||null,area:e.area||null,hidden:!!e.hidden};return t.markers.push(n),n}_renderVacSection(e){return this._editorRuntimeOrThrow()._renderVacSection(e)}_vacMapId(e,t,i=this._planHass){const n=this._vacEntity(e),r=n?i?.states?.[n]?.attributes?.selected_map:null;return o=t.mapId,s=r,"default"!==o?o:null!=s?String(s):"default";var o,s}_vacObservedMapId(e,t,i=this._planHass){const n=mc(i?.states?.[t]?.attributes);return n?this._vacMapId(e,n,i):void 0}_vacSaveMatrix(e,t,i,n,r=""){return this._editorRuntimeOrThrow()._vacSaveMatrix(e,t,i,n,r)}_vacPlanRoomAnchors(e){return this._editorRuntimeOrThrow()._vacPlanRoomAnchors(e)}_vacAutoCalibrate(e){return this._editorRuntimeOrThrow()._vacAutoCalibrate(e)}_vacApplyCalibrationProposal(e){return this._editorRuntimeOrThrow()._vacApplyCalibrationProposal(e)}_vacStartFit(e){return this._editorRuntimeOrThrow()._vacStartFit(e)}_vacFitSave(){return this._editorRuntimeOrThrow()._vacFitSave()}_vacFitTurn(e){return this._editorRuntimeOrThrow()._vacFitTurn(e)}_vacGhostCentre(e){return this._editorRuntimeOrThrow()._vacGhostCentre(e)}_vacDelta(e,t,i){return this._editorRuntimeOrThrow()._vacDelta(e,t,i)}_vacFitPointer(e,t){return this._editorRuntimeOrThrow()._vacFitPointer(e,t)}_renderVacFit(e){return this._editorRuntime?this._editorRuntimeOrThrow()._renderVacFit(e):V}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const e=this.renderRoot,t=this._stageEl,i=this._vacLastView,n=e?.querySelectorAll?.(".vacpuck")||[];if(!t||!i||!n.length)return void(this._vacRaf=0);const r=t.getBoundingClientRect();for(const t of n){const n=t.getAttribute("data-mid"),o=t.getBoundingClientRect(),s=i.x+(o.left+o.width/2-r.left)/r.width*i.w,a=i.y+(o.top+o.height/2-r.top)/r.height*i.h;for(const t of e.querySelectorAll(`line.tip[data-mid="${n}"]`))t.setAttribute("x2",s.toFixed(1)),t.setAttribute("y2",a.toFixed(1))}this._vacRafLoop()})}_vacTrailPathD(e,t){const i=e.map(e=>e.map(([e,i])=>rc(t,e,i))),n=function(e,t,i=console.warn){if(!Number.isFinite(t)||t<=0)return[];const n=[];let r=0;for(const i of e){if(!i.every(pc)){r++;continue}const e=i.filter((e,t)=>0===t||!_c(e,i[t-1]));if(e.length<2)continue;const o=[{kind:"move",point:e[0]}];if(2!==e.length){for(let i=1;i0&&i(`[houseplan] vacuum trail: ${r} segment(s) dropped — non-finite point (check map calibration)`),n}(i,this._cmToUnits(17.5)),r=e=>{const t=this._scenePoint(e);return`${t[0].toFixed(1)} ${t[1].toFixed(1)}`};return n.map(e=>e.map(e=>"move"===e.kind?`M ${r(e.point)}`:"line"===e.kind?`L ${r(e.point)}`:`Q ${r(e.control)} ${r(e.point)}`).join(" ")).join(" ")}_renderVacuums(e,t,i){if(this._markup||"decor"===this._mode)return V;const n=this._space+"|"+t.x+"|"+t.y+"|"+t.w+"|"+t.h,r=this._vacJumpOnce||n!==this._vacViewKey;this._vacViewKey=n,this._vacJumpOnce=!1;const o=[],s=[];for(const n of e){if(n.hidden||!this._isVacDev(n))continue;if("static_icon"===Ei(n.marker?.display))continue;const e=this._renderDeviceSnapshot?.facts.get(`vacuum:${n.id}`),a=e?.source??this._vacSource(n,this._renderPlanHass);if(!a)continue;const l=e?.telemetry??mc(this._renderPlanHass?.states[a]?.attributes);if(!l)continue;const c=e?.routes??Pc(n.id,n.marker?.vacuum??null,n.space,a),h=e?.resolution??Ic({routes:c,observed:Oc(c,[a],e=>this._vacObservedMapId(n,e)),spaceIds:new Set(this._model.map(e=>e.id))}),d=e?.server??this._vacSrvTrails[n.id],u=Hc({resolution:h,routes:c,renderSpace:i,rootSource:n.marker?.vacuum?.source??null,serverCurrent:d?.current??null,serverPrevious:d?.previous??null,explicitRoutes:Array.isArray(n.marker?.vacuum?.map_routes)});if(!u.live&&!u.previous)continue;const p=u.live,_=e?.runtime??this._vacRt.get(n.id),m=_?.moving??!1,g=Tc(n.marker?.vacuum),f="always"===g||"cleaning"===g&&m,v=d,y=u.currentRunMatches&&Array.isArray(v?.current?.points)?v.current:null,b=u.previous&&Array.isArray(v?.previous?.points)?v.previous:null;if("always"===g&&b&&u.previous){const e=hc(b.points),t=this._vacTrailPathD(e,u.previous);t&&s.push(j``)}if(f&&p){const e=dc(l,y,_?.trail||[]),t=!m||"integration"!==e.source&&"server"!==e.source?e.path:uc(e.path);if(t.length){const e=this._vacTrailPathD(t,p);e&&s.push(j``);const i=t[t.length-1];if(m&&i?.length>=2){const e=i[i.length-1],[t,r]=rc(p,e[0],e[1]),o=this._scenePoint([t,r]),a=o[0].toFixed(1),l=o[1].toFixed(1);s.push(j``)}}}if(!m||!l.pos||!p)continue;const[w,k]=rc(p,l.pos.x,l.pos.y),x=this._scenePoint([w,k]),S=(x[0]-t.x)/t.w*100,$=(x[1]-t.y)/t.h*100,M=_&&_.lastTs>0&&Date.now()-_.lastTs>6e4,R=n.marker?.icon||n.icon||"mdi:robot-vacuum";o.push(W`
e.entityId));for(const t of this._vacAllCameraCache.candidates)e.has(t.entityId)||l.push(t)}const c={};for(const e of l)c[e.entityId]=this._vacCandidateStatus(e.entityId,e,i);return function(e,t,i,n){const r="string"==typeof e&&e.length>0,o=new Set(t),s=Array.from(i).sort((t,i)=>r&&t.entityId===e?-1:r&&i.entityId===e?1:i.score-t.score||t.entityId.localeCompare(i.entityId));if(r){const t=s.find(t=>t.entityId===e);return{entityId:e,status:n[e]||(t?.hasPosition?"ok":"unverified"),pinned:!0,candidates:s}}const a=s.find(e=>o.has(e.entityId)&&e.hasPosition&&"ok"===n[e.entityId]);return a?{entityId:a.entityId,status:"ok",pinned:!1,candidates:s}:{entityId:null,status:"none",pinned:!1,candidates:s}}(n?.source,o,l,c)}_vacSource(e,t=this._planHass){if(!1===e.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(e,!1,t);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(e){return e.primary?.startsWith("vacuum.")?e.primary:(e.entities||[]).find(e=>e.startsWith("vacuum."))||null}_isVacDev(e){return!!this._vacEntity(e)}_activitySourceKey(e){return this._activitySnapshot(e).sourceKey}_activitySnapshot(e,t=_d(this._planHass,this._devices,null,this._virtualLights)){const i=Cp(this._planHass,e,this._devices,t,this._fullRegistryHass);return{samples:i.samples,sourceKey:Ap(this._planHass,e,i)}}_stampActivity(e,t,i){let n=this._activityRt.get(e);n||(n=xm(i||"",[]),this._activityRt.set(e,n)),null!=i&&(n.sources=i),$m(n,t,Date.now(),window.clearTimeout.bind(window),e=>window.setTimeout(()=>this.requestUpdate(),e))}_syncActivityRuntime(){const e=new Map;if(!this.hass)return e;if(!1===this._config?.live_states){for(const e of this._activityRt.values())clearTimeout(e.timer);return this._activityRt.clear(),e}const t=new Set,i=_d(this._planHass,this._devices,null,this._virtualLights);for(const n of this._devices){if(n.hidden)continue;if("icon_ripple"!==Ei(n.marker?.display))continue;t.add(n.id);const r=this._activitySnapshot(n,i);e.set(n.id,r);const{samples:o,sourceKey:s}=r;let a=this._activityRt.get(n.id);a?a.sources!==s&&Sm(a,s,o,window.clearTimeout.bind(window)):(a=xm(s,o),this._activityRt.set(n.id,a))}for(const[e,i]of this._activityRt)t.has(e)||(clearTimeout(i.timer),this._activityRt.delete(e));return e}_activityTick(){if(!this.hass)return;const e=this._syncActivityRuntime();for(const t of this._devices){if(t.hidden)continue;if("icon_ripple"!==Ei(t.marker?.display))continue;const i=e.get(t.id)||this._activitySnapshot(t),{samples:n,sourceKey:r}=i,o=this._activityRt.get(t.id);if(!o||o.sources!==r)continue;const s=Mm(o,n,window.clearTimeout.bind(window));s&&this._stampActivity(t.id,s,r)}}_vacTick(){if(this.hass)for(const e of this._devices){if(e.hidden||!this._isVacDev(e))continue;if("static_icon"===Ei(e.marker?.display)){this._vacRt.delete(e.id);continue}const t=this._vacSource(e);if(!t)continue;const i=this._vacEntity(e),n=Cc(this.hass.states[i||""]?.state),r=bc(this.hass.states[t]?.attributes);let o=this._vacRt.get(e.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(e.id,o)),n&&!o.moving&&(o.trail=[],o.lastPos=null);const s="never"!==zc(e.marker?.vacuum)&&!r?.path.length;!n&&o.moving&&(o.endedTs=Date.now(),s&&o.lastPos&&(o.trail=Rc(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=n;const a=r?.pos;if(n&&a){const e=a.x+":"+a.y;if(e!==o.lastKey){const t=Date.now();o.jump=o.lastTs>0&&t-o.lastTs>1e4,o.lastKey=e,o.lastTs=t,s&&o.lastPos&&(o.trail=Rc(o.trail,o.lastPos,40)),o.lastPos=[a.x,a.y]}}}}_vacEnsureMarker(e){const t=this._serverCfg;if(!t)return null;t.markers=t.markers||[];const i=t.markers.find(t=>t.id===e.id);if(i)return i;if("device"!==e.bindingKind&&"entity"!==e.bindingKind||!e.bindingRef)return null;const n={id:e.id,binding:e.bindingKind+":"+e.bindingRef,space:e.space||null,area:e.area||null,hidden:!!e.hidden};return t.markers.push(n),n}_renderVacSection(e){return this._editorRuntimeOrThrow()._renderVacSection(e)}_vacMapId(e,t,i=this._planHass){const n=this._vacEntity(e),r=n?i?.states?.[n]?.attributes?.selected_map:null;return o=t.mapId,s=r,"default"!==o?o:null!=s?String(s):"default";var o,s}_vacObservedMapId(e,t,i=this._planHass){const n=bc(i?.states?.[t]?.attributes);return n?this._vacMapId(e,n,i):void 0}_vacSaveMatrix(e,t,i,n,r=""){return this._editorRuntimeOrThrow()._vacSaveMatrix(e,t,i,n,r)}_vacPlanRoomAnchors(e){return this._editorRuntimeOrThrow()._vacPlanRoomAnchors(e)}_vacAutoCalibrate(e){return this._editorRuntimeOrThrow()._vacAutoCalibrate(e)}_vacApplyCalibrationProposal(e){return this._editorRuntimeOrThrow()._vacApplyCalibrationProposal(e)}_vacStartFit(e){return this._editorRuntimeOrThrow()._vacStartFit(e)}_vacFitSave(){return this._editorRuntimeOrThrow()._vacFitSave()}_vacFitTurn(e){return this._editorRuntimeOrThrow()._vacFitTurn(e)}_vacGhostCentre(e){return this._editorRuntimeOrThrow()._vacGhostCentre(e)}_vacDelta(e,t,i){return this._editorRuntimeOrThrow()._vacDelta(e,t,i)}_vacFitPointer(e,t){return this._editorRuntimeOrThrow()._vacFitPointer(e,t)}_renderVacFit(e){return this._editorRuntime?this._editorRuntimeOrThrow()._renderVacFit(e):V}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const e=this.renderRoot,t=this._stageEl,i=this._vacLastView,n=e?.querySelectorAll?.(".vacpuck")||[];if(!t||!i||!n.length)return void(this._vacRaf=0);const r=t.getBoundingClientRect();for(const t of n){const n=t.getAttribute("data-mid"),o=t.getBoundingClientRect(),s=i.x+(o.left+o.width/2-r.left)/r.width*i.w,a=i.y+(o.top+o.height/2-r.top)/r.height*i.h;for(const t of e.querySelectorAll(`line.tip[data-mid="${n}"]`))t.setAttribute("x2",s.toFixed(1)),t.setAttribute("y2",a.toFixed(1))}this._vacRafLoop()})}_vacTrailPathD(e,t){const i=e.map(e=>e.map(([e,i])=>cc(t,e,i))),n=function(e,t,i=console.warn){if(!Number.isFinite(t)||t<=0)return[];const n=[];let r=0;for(const i of e){if(!i.every(vc)){r++;continue}const e=i.filter((e,t)=>0===t||!yc(e,i[t-1]));if(e.length<2)continue;const o=[{kind:"move",point:e[0]}];if(2!==e.length){for(let i=1;i0&&i(`[houseplan] vacuum trail: ${r} segment(s) dropped — non-finite point (check map calibration)`),n}(i,this._cmToUnits(17.5)),r=e=>{const t=this._scenePoint(e);return`${t[0].toFixed(1)} ${t[1].toFixed(1)}`};return n.map(e=>e.map(e=>"move"===e.kind?`M ${r(e.point)}`:"line"===e.kind?`L ${r(e.point)}`:`Q ${r(e.control)} ${r(e.point)}`).join(" ")).join(" ")}_renderVacuums(e,t,i){if(this._markup||"decor"===this._mode)return V;const n=this._space+"|"+t.x+"|"+t.y+"|"+t.w+"|"+t.h,r=this._vacJumpOnce||n!==this._vacViewKey;this._vacViewKey=n,this._vacJumpOnce=!1;const o=[],s=[];for(const n of e){if(n.hidden||!this._isVacDev(n))continue;if("static_icon"===Ei(n.marker?.display))continue;const e=this._renderDeviceSnapshot?.facts.get(`vacuum:${n.id}`),a=e?.source??this._vacSource(n,this._renderPlanHass);if(!a)continue;const l=e?.telemetry??bc(this._renderPlanHass?.states[a]?.attributes);if(!l)continue;const c=e?.routes??Nc(n.id,n.marker?.vacuum??null,n.space,a),h=e?.resolution??Lc({routes:c,observed:Bc(c,[a],e=>this._vacObservedMapId(n,e)),spaceIds:new Set(this._model.map(e=>e.id))}),d=e?.server??this._vacSrvTrails[n.id],u=jc({resolution:h,routes:c,renderSpace:i,rootSource:n.marker?.vacuum?.source??null,serverCurrent:d?.current??null,serverPrevious:d?.previous??null,explicitRoutes:Array.isArray(n.marker?.vacuum?.map_routes)});if(!u.live&&!u.previous)continue;const p=u.live,_=e?.runtime??this._vacRt.get(n.id),m=_?.moving??!1,g=zc(n.marker?.vacuum),f="always"===g||"cleaning"===g&&m,v=d,y=u.currentRunMatches&&Array.isArray(v?.current?.points)?v.current:null,b=u.previous&&Array.isArray(v?.previous?.points)?v.previous:null;if("always"===g&&b&&u.previous){const e=mc(b.points),t=this._vacTrailPathD(e,u.previous);t&&s.push(W``)}if(f&&p){const e=gc(l,y,_?.trail||[]),t=!m||"integration"!==e.source&&"server"!==e.source?e.path:fc(e.path);if(t.length){const e=this._vacTrailPathD(t,p);e&&s.push(W``);const i=t[t.length-1];if(m&&i?.length>=2){const e=i[i.length-1],[t,r]=cc(p,e[0],e[1]),o=this._scenePoint([t,r]),a=o[0].toFixed(1),l=o[1].toFixed(1);s.push(W``)}}}if(!m||!l.pos||!p)continue;const[w,k]=cc(p,l.pos.x,l.pos.y),x=this._scenePoint([w,k]),S=(x[0]-t.x)/t.w*100,$=(x[1]-t.y)/t.h*100,M=_&&_.lastTs>0&&Date.now()-_.lastTs>6e4,R=n.marker?.icon||n.icon||"mdi:robot-vacuum";o.push(j`
{e.stopPropagation();const t=this._vacEntity(n);t&&this._openMoreInfo(t)}}> -
`)}return this._vacLastView=t,o.length&&!this._vacRaf&&this._vacRafLoop(),o.length||s.length?W` - ${s.length?j`${s}`:V} - ${o}`:V}_renderDevice(e,t,i=!0,n){const r=this._pos(e),o=n?.visualScene??this._scenePoint([r.x,r.y]),s=(o[0]-t.x)/t.w*100,a=(o[1]-t.y)/t.h*100,l=this._devicePresentation(e,i),c=[`left:${s}%`,`top:${a}%`,...Ip(l)],h=l.disabledReason,d=l.haDisabled?this._t(`marker.ha_disabled_${h}`):e.userHidden?this._t("marker.hidden_ghost"):e.name,u=fp(l),p="view"===this._mode||"devices"===this._mode,_=[d,l.haDisabled?"":this._t(`marker.state_a11y_${u}`),"none"!==l.pulse.kind?this._t(`marker.pulse_a11y_${l.pulse.reason}`):"",l.valueFullText||l.valueText||"",Xu(l.valueBadge),null!=l.lqiText&&l.lqiBand?this._t(`marker.lqi_a11y_${l.lqiBand}`,{value:l.lqiText}):""].filter(Boolean).join(", "),m=[e.model,l.valueBadge?.fullText||"",null!=l.lqiText?"LQI "+l.lqiText:""].filter(Boolean).join(" · ");return W`
`)}return this._vacLastView=t,o.length&&!this._vacRaf&&this._vacRafLoop(),o.length||s.length?j` + ${s.length?W`${s}`:V} + ${o}`:V}_renderDevice(e,t,i=!0,n){const r=this._pos(e),o=n?.visualScene??this._scenePoint([r.x,r.y]),s=(o[0]-t.x)/t.w*100,a=(o[1]-t.y)/t.h*100,l=this._devicePresentation(e,i),c=[`left:${s}%`,`top:${a}%`,...Lp(l)],h=l.disabledReason,d=l.haDisabled?this._t(`marker.ha_disabled_${h}`):e.userHidden?this._t("marker.hidden_ghost"):e.name,u=kp(l),p="view"===this._mode||"devices"===this._mode,_=[d,l.haDisabled?"":this._t(`marker.state_a11y_${u}`),"none"!==l.pulse.kind?this._t(`marker.pulse_a11y_${l.pulse.reason}`):"",l.valueFullText||l.valueText||"",tp(l.valueBadge),null!=l.lqiText&&l.lqiBand?this._t(`marker.lqi_a11y_${l.lqiBand}`,{value:l.lqiText}):""].filter(Boolean).join(", "),m=[e.model,l.valueBadge?.fullText||"",null!=l.lqiText?"LQI "+l.lqiText:""].filter(Boolean).join(" · ");return j`
this._clickDevice(t,e)} @keydown=${t=>this._keyDevice(t,e)} @@ -5728,10 +5728,10 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e @pointercancel=${t=>this._pointerCancel(t,e)} @lostpointercapture=${t=>this._pointerCancel(t,e)} > - ${Ep(l,{newDevice:this._newIds.has(e.id),newDeviceTitle:this._t("device.new"),disabledTitle:l.haDisabled?d:""})} + ${qp(l,{newDevice:this._newIds.has(e.id),newDeviceTitle:this._t("device.new"),disabledTitle:l.haDisabled?d:""})} ${this._vacRouteBadge(e)} -
`}_vacRouteBadge(e){if(!this._isVacDev(e)||e.hidden)return V;if("static_icon"===Ei(e.marker?.display))return V;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${e.id}`),i=function(e,t){if(!t||!e)return null;switch(e.kind){case"unmapped":case"needs_calibration":case"ambiguous":case"missing_space":return e.kind;default:return null}}(t?.resolution,this._vacRt.get(e.id)?.moving??!1);if(!i)return V;const n=this._t(`vac.route_warn_${i}`);return W` - `}_roomArea(e){const t=ei(e);if(!t)return null;const i=this._spaceModel();if(!i)return null;const n=this._spaceWalls.length&&e.id&&this._innerRoomContour(i,e.id)||t,r=this._cleanFloor(e,n),o=this._cellCm/this._gridPitch;return Vn(r.area*o*o/1e4,"mi"===this._renderPlanHass?.config?.unit_system?.length)}_roomTemp(e){const t=e.settings?.temp_source;if(t)return Dd(this._renderPlanHass,t,"temp",this._markers);const i=Ad(this._spaceModel()?.id,e);return i?this._climate().get(i)?.temp??null:null}_roomHum(e){const t=e.settings?.hum_source;if(t)return Dd(this._renderPlanHass,t,"hum",this._markers);const i=Ad(this._spaceModel()?.id,e);return i?this._climate().get(i)?.hum??null:null}_climate(){const e=this._serverCfg?.markers,t=this._renderPlanHass,i=this._climateCache,n=this._settings.exclude_integrations;if(i&&i.h===t&&i.r===this._iconRules&&i.mk===e&&i.ex===n)return i.m;const r=Id(t,this._iconRules,e,this._excluded);return this._climateCache={h:t,r:this._iconRules,mk:e,ex:n,m:r},r}_resetRoomDialogFields(){return this._editorRuntimeOrThrow()._resetRoomDialogFields()}_openRoomEdit(e){return this._editorRuntimeOrThrow()._openRoomEdit(e)}_roomSettingsFromDialog(){return this._editorRuntimeOrThrow()._roomSettingsFromDialog()}_saveRoomEdit(){return this._editorRuntimeOrThrow()._saveRoomEdit()}_roomSrcCandidates(){return this._editorRuntimeOrThrow()._roomSrcCandidates()}_roomSrcLabel(e){return this._editorRuntimeOrThrow()._roomSrcLabel(e)}_labelPos(e,t){const i=this._layout["rl_"+(e.id||"")];if(i&&i.s===t)return{x:i.x*Sf,y:i.y*Sf};const n=this._roomCenter(e),r=this._gridPitch;return{x:Qa(Xt(n[0],r)),y:Qa(Xt(n[1],r))}}_labelDown(e,t,i){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelDown(e,t,i)}_labelMove(e,t,i){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelMove(e,t,i)}_labelUp(e){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelUp(e)}_labelScale(e){const t=this._layout["rl_"+(e.id||"")]?.k;return"number"==typeof t&&Number.isFinite(t)?Math.min(3,Math.max(.5,t)):1}_rlResizeDown(e,t,i){return this._editorRuntimeOrThrow()._rlResizeDown(e,t,i)}_rlResizeMove(e){return this._editorRuntimeOrThrow()._rlResizeMove(e)}_rlResizeUp(){return this._editorRuntimeOrThrow()._rlResizeUp()}_renderRoomGear(e,t,i){return this._editorRuntimeOrThrow()._renderRoomGear(e,t,i)}_renderRoomLabel(e,t,i,n,r){if(!e.name&&!this._markup)return V;const o=this._labelPos(e,t.id),s=r?.visualScene??this._scenePoint([o.x,o.y]),a=(s[0]-i.x)/i.w*100,l=(s[1]-i.y)/i.h*100,c=Math.min(1,n.opacity+.25),h=this._labelScale(e),d=[];if(n.labelTemp||n.labelHum||n.labelLqi&&e.area||n.labelLight){if(n.labelTemp){const t=this._roomTemp(e);null!=t&&d.push(W`${t}°`)}if(n.labelHum){const t=this._roomHum(e);null!=t&&d.push(W`${t}%`)}if(n.labelLqi&&e.area){const t=this._roomLqi(e.area);null!=t&&d.push(W`${t}`)}if(n.labelLight){const t=(u=cd(this._renderPlanHass,this._renderDevices,e,this._virtualLights)).length?{on:u.filter(e=>e.on).length,total:u.length}:null;if(t){const e=0===t.on?this._t("roomcard.light_off"):t.on===t.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:t.on,total:t.total});d.push(W`${e}`)}}}var u;const p=!!e.area,_=!this._markup;return W`
`}_vacRouteBadge(e){if(!this._isVacDev(e)||e.hidden)return V;if("static_icon"===Ei(e.marker?.display))return V;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${e.id}`),i=function(e,t){if(!t||!e)return null;switch(e.kind){case"unmapped":case"needs_calibration":case"ambiguous":case"missing_space":return e.kind;default:return null}}(t?.resolution,this._vacRt.get(e.id)?.moving??!1);if(!i)return V;const n=this._t(`vac.route_warn_${i}`);return j` + `}_roomArea(e){const t=ei(e);if(!t)return null;const i=this._spaceModel();if(!i)return null;const n=this._spaceWalls.length&&e.id&&this._innerRoomContour(i,e.id)||t,r=this._cleanFloor(e,n),o=this._cellCm/this._gridPitch;return Vn(r.area*o*o/1e4,"mi"===this._renderPlanHass?.config?.unit_system?.length)}_roomTemp(e){const t=e.settings?.temp_source;if(t)return Id(this._renderPlanHass,t,"temp",this._markers);const i=Ed(this._spaceModel()?.id,e);return i?this._climate().get(i)?.temp??null:null}_roomHum(e){const t=e.settings?.hum_source;if(t)return Id(this._renderPlanHass,t,"hum",this._markers);const i=Ed(this._spaceModel()?.id,e);return i?this._climate().get(i)?.hum??null:null}_climate(){const e=this._serverCfg?.markers,t=this._renderPlanHass,i=this._climateCache,n=this._settings.exclude_integrations;if(i&&i.h===t&&i.r===this._iconRules&&i.mk===e&&i.ex===n)return i.m;const r=Ld(t,this._iconRules,e,this._excluded);return this._climateCache={h:t,r:this._iconRules,mk:e,ex:n,m:r},r}_resetRoomDialogFields(){return this._editorRuntimeOrThrow()._resetRoomDialogFields()}_openRoomEdit(e){return this._editorRuntimeOrThrow()._openRoomEdit(e)}_roomSettingsFromDialog(){return this._editorRuntimeOrThrow()._roomSettingsFromDialog()}_saveRoomEdit(){return this._editorRuntimeOrThrow()._saveRoomEdit()}_roomSrcCandidates(){return this._editorRuntimeOrThrow()._roomSrcCandidates()}_roomSrcLabel(e){return this._editorRuntimeOrThrow()._roomSrcLabel(e)}_labelPos(e,t){const i=this._layout["rl_"+(e.id||"")];if(i&&i.s===t)return{x:i.x*Tf,y:i.y*Tf};const n=this._roomCenter(e),r=this._gridPitch;return{x:Qa(Xt(n[0],r)),y:Qa(Xt(n[1],r))}}_labelDown(e,t,i){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelDown(e,t,i)}_labelMove(e,t,i){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelMove(e,t,i)}_labelUp(e){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelUp(e)}_labelScale(e){const t=this._layout["rl_"+(e.id||"")]?.k;return"number"==typeof t&&Number.isFinite(t)?Math.min(3,Math.max(.5,t)):1}_rlResizeDown(e,t,i){return this._editorRuntimeOrThrow()._rlResizeDown(e,t,i)}_rlResizeMove(e){return this._editorRuntimeOrThrow()._rlResizeMove(e)}_rlResizeUp(){return this._editorRuntimeOrThrow()._rlResizeUp()}_renderRoomGear(e,t,i){return this._editorRuntimeOrThrow()._renderRoomGear(e,t,i)}_renderRoomLabel(e,t,i,n,r){if(!e.name&&!this._markup)return V;const o=this._labelPos(e,t.id),s=r?.visualScene??this._scenePoint([o.x,o.y]),a=(s[0]-i.x)/i.w*100,l=(s[1]-i.y)/i.h*100,c=Math.min(1,n.opacity+.25),h=this._labelScale(e),d=[];if(n.labelTemp||n.labelHum||n.labelLqi&&e.area||n.labelLight){if(n.labelTemp){const t=this._roomTemp(e);null!=t&&d.push(j`${t}°`)}if(n.labelHum){const t=this._roomHum(e);null!=t&&d.push(j`${t}%`)}if(n.labelLqi&&e.area){const t=this._roomLqi(e.area);null!=t&&d.push(j`${t}`)}if(n.labelLight){const t=(u=_d(this._renderPlanHass,this._renderDevices,e,this._virtualLights)).length?{on:u.filter(e=>e.on).length,total:u.length}:null;if(t){const e=0===t.on?this._t("roomcard.light_off"):t.on===t.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:t.on,total:t.total});d.push(j`${e}`)}}}var u;const p=!!e.area,_=!this._markup;return j`
${e.name||(this._markup?this._t("room.unnamed"):"")}${p?W`${e.name||(this._markup?this._t("room.unnamed"):"")}${p?j`{t.stopPropagation(),this._clickRoom(e)}:V} @pointerdown=${_?e=>e.stopPropagation():V}>`:V} - ${d.length?W`${d}`:V} - ${"plan"===this._mode?["tl","tr","bl","br"].map(i=>W`${d}`:V} + ${"plan"===this._mode?["tl","tr","bl","br"].map(i=>j`this._rlResizeDown(i,e,t.id)} @pointermove=${e=>this._rlResizeMove(e)} @pointerup=${()=>this._rlResizeUp()} @pointercancel=${()=>this._rlResizeUp()}>`):V} -
`}_renderLiveEditorMeasurements(e){const t=e,i=this._opMeasureView,n=this._decorMeasure,r=this._bdLive,o=this._editorRuntime?._furnLive()??null;return W` - ${this._measureAnchor?W`
${this._renderMeasureLabel(t)}
`:V} - ${this._resize?.liveLabels?W`
${this._resize.liveLabels.map(e=>W`
`}_renderLiveEditorMeasurements(e){const t=e,i=this._opMeasureView,n=this._decorMeasure,r=this._bdLive,o=this._editorRuntime?._furnLive()??null;return j` + ${this._measureAnchor?j`
${this._renderMeasureLabel(t)}
`:V} + ${this._resize?.liveLabels?j`
${this._resize.liveLabels.map(e=>j`
${e.text}
`)}
`:V} - ${i?W`
${i.labels.map(e=>W`
${i.labels.map(e=>j`
${e.text}
`)}
`:V} - ${n?W`
${n.text}
`:V} - ${o?W`
${o.map(e=>W`
${o.map(e=>j`
${e.text}
`)}
`:V} - ${r?W`
${r.text}
`:V} - `}get _measureAnchor(){return this._markup&&this._cursorPt?"draw"===this._tool&&this._path.length&&!this._contourClosed?this._path[this._path.length-1]:"split"===this._tool&&this._splitSel?.pts?.length?this._splitSel.pts[this._splitSel.pts.length-1]:null:null}_renderMeasureLabel(e){const t=this._measureAnchor,i=this._cursorPt,n=(i[0]-e.x)/e.w*100,r=(i[1]-e.y)/e.h*100,o=Nn(t,i),s=Math.round(10*o)/10,a=function(e,t,i=.001){if(e.length<2||t.length<2)return!1;const n=Math.abs(t[0]-e[0]),r=Math.abs(t[1]-e[1]);if(!Number.isFinite(n)||!Number.isFinite(r)||Math.hypot(n,r)<=i)return!1;const o=Math.max(n,r,1);return n<=i*o||r<=i*o||Math.abs(n-r)<=i*o}(t,i,2e-4*this._gridPitch);return W`
- ${this._fmtLen(t,i)} · ${s}°
`}get _decorMeasure(){const e=this._decorDraft;if(!e||"decor"!==this._mode)return null;const[t,i]=e.a,[n,r]=e.b;if(Math.abs(t-n)<1e-6&&Math.abs(i-r)<1e-6)return null;const o=(t+n)/2,s=(i+r)/2;if("line"===e.kind){const t=Nn(e.a,e.b);return{x:o,y:s,on45:Ln(t),text:`${this._fmtLen(e.a,e.b)} · ${Math.round(10*t)/10}°`}}const a=this._fmtLen([t,i],[n,i]),l=this._fmtLen([n,i],[n,r]);if("ellipse"===e.kind){const e=this._fmtLen([0,0],[Math.abs(n-t)/2,0]),a=this._fmtLen([0,0],[0,Math.abs(r-i)/2]);return{x:o,y:s,on45:!1,text:Math.abs(Math.abs(n-t)-Math.abs(r-i))<1e-6?`R ${e}`:`Rx ${e} × Ry ${a}`}}return{x:o,y:s,on45:!1,text:`${a} × ${l} · ${Vn($r(Math.abs(n-t),this._cellCm,this._gridPitch)*$r(Math.abs(r-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const e=this._drag.id.slice(3),t=this._spaceModel()?.rooms.find(t=>t.id===e);return t?(()=>{const e=this._labelPos(t,this._space);return[e.x,e.y]})():null}return null}if("devices"===this._mode&&this._deviceDrag?.moved){const e=this._devices.find(e=>e.id===this._deviceDrag.id);return e?(()=>{const t=this._pos(e);return[t.x,t.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const e=this._decorList.find(e=>e.id===this._decorMove.id);if(!e)return null;const t=Sf,i=this._decorH;return"line"===e.kind?[e.x1*t,e.y1*i]:[e.x*t,e.y*i]}return null}return null}_alignCandidates(){return this._editorRuntimeOrThrow()._alignCandidates()}_renderAlignGuides(){return this._editorRuntimeOrThrow()._renderAlignGuides()}_renderOpeningCenterTick(e){return this._editorRuntimeOrThrow()._renderOpeningCenterTick(e)}_renderOpeningDimensionGuides(e){return this._editorRuntimeOrThrow()._renderOpeningDimensionGuides(e)}_roomCenter(e){if(e.poly){const t=e.poly.length;return[e.poly.reduce((e,t)=>e+t[0],0)/t,e.poly.reduce((e,t)=>e+t[1],0)/t]}return[e.x+e.w/2,e.y+.1*Math.min(e.w,e.h)]}_openingAmt(e){const t=e.contact&&this._renderOpeningEntityAvailable(e.contact)?this._renderPlanHass.states[e.contact]:null;return si(e.type,t?.state,!!e.invert,t?.attributes?.current_position)}_planEntityAvailable(e){return!!e&&(!Sd(this._fullRegistryHass,e,xd(this._markers))&&"active"===this._bindingStatus("entity:"+e).kind)}_renderEntityAvailable(e){return!!e&&(!Sd(this._renderPlanHass,e,xd(this._markers))&&(!!this._renderPlanHass.entities?.[e]&&!!this._renderPlanHass.states?.[e]))}_openingEntityAvailable(e){return function(e,t,i=Th(e)){return!!t&&"active"===Eh(e,`entity:${t}`,i).kind}(this.hass,e,this._haRegistry)}_renderOpeningEntityAvailable(e){return t=this._renderPlanHass,!!(i=e)&&!!t?.states?.[i];var t,i}_renderOpeningPlacementPreview(){return this._editorRuntimeOrThrow()._renderOpeningPlacementPreview()}_renderOpenings(e,t){const i=t?this._openingsR.filter(e=>t.includes(e.id)):this._openingsR;if(!i.length)return j``;const n=this._spaceModel();if(!n)return j``;const r=e.color,o=this._spaceWalls,s=this._openCuts(),a=this._openingWallIndexFor(n,s).value;return j`${i.map(e=>{if(e.orphanReason)return j` + ${this._fmtLen(t,i)} · ${s}°
`}get _decorMeasure(){const e=this._decorDraft;if(!e||"decor"!==this._mode)return null;const[t,i]=e.a,[n,r]=e.b;if(Math.abs(t-n)<1e-6&&Math.abs(i-r)<1e-6)return null;const o=(t+n)/2,s=(i+r)/2;if("line"===e.kind){const t=Hn(e.a,e.b);return{x:o,y:s,on45:Ln(t),text:`${this._fmtLen(e.a,e.b)} · ${Math.round(10*t)/10}°`}}const a=this._fmtLen([t,i],[n,i]),l=this._fmtLen([n,i],[n,r]);if("ellipse"===e.kind){const e=this._fmtLen([0,0],[Math.abs(n-t)/2,0]),a=this._fmtLen([0,0],[0,Math.abs(r-i)/2]);return{x:o,y:s,on45:!1,text:Math.abs(Math.abs(n-t)-Math.abs(r-i))<1e-6?`R ${e}`:`Rx ${e} × Ry ${a}`}}return{x:o,y:s,on45:!1,text:`${a} × ${l} · ${Vn($r(Math.abs(n-t),this._cellCm,this._gridPitch)*$r(Math.abs(r-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const e=this._drag.id.slice(3),t=this._spaceModel()?.rooms.find(t=>t.id===e);return t?(()=>{const e=this._labelPos(t,this._space);return[e.x,e.y]})():null}return null}if("devices"===this._mode&&this._deviceDrag?.moved){const e=this._devices.find(e=>e.id===this._deviceDrag.id);return e?(()=>{const t=this._pos(e);return[t.x,t.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const e=this._decorList.find(e=>e.id===this._decorMove.id);if(!e)return null;const t=Tf,i=this._decorH;return"line"===e.kind?[e.x1*t,e.y1*i]:[e.x*t,e.y*i]}return null}return null}_alignCandidates(){return this._editorRuntimeOrThrow()._alignCandidates()}_renderAlignGuides(){return this._editorRuntimeOrThrow()._renderAlignGuides()}_renderOpeningCenterTick(e){return this._editorRuntimeOrThrow()._renderOpeningCenterTick(e)}_renderOpeningDimensionGuides(e){return this._editorRuntimeOrThrow()._renderOpeningDimensionGuides(e)}_roomCenter(e){if(e.poly){const t=e.poly.length;return[e.poly.reduce((e,t)=>e+t[0],0)/t,e.poly.reduce((e,t)=>e+t[1],0)/t]}return[e.x+e.w/2,e.y+.1*Math.min(e.w,e.h)]}_openingAmt(e){const t=e.contact&&this._renderOpeningEntityAvailable(e.contact)?this._renderPlanHass.states[e.contact]:null;return si(e.type,t?.state,!!e.invert,t?.attributes?.current_position)}_planEntityAvailable(e){return!!e&&(!Td(this._fullRegistryHass,e,Cd(this._markers))&&"active"===this._bindingStatus("entity:"+e).kind)}_renderEntityAvailable(e){return!!e&&(!Td(this._renderPlanHass,e,Cd(this._markers))&&(!!this._renderPlanHass.entities?.[e]&&!!this._renderPlanHass.states?.[e]))}_openingEntityAvailable(e){return function(e,t,i=zh(e)){return!!t&&"active"===qh(e,`entity:${t}`,i).kind}(this.hass,e,this._haRegistry)}_renderOpeningEntityAvailable(e){return t=this._renderPlanHass,!!(i=e)&&!!t?.states?.[i];var t,i}_renderOpeningPlacementPreview(){return this._editorRuntimeOrThrow()._renderOpeningPlacementPreview()}_renderOpenings(e,t){const i=t?this._openingsR.filter(e=>t.includes(e.id)):this._openingsR;if(!i.length)return W``;const n=this._spaceModel();if(!n)return W``;const r=e.color,o=this._spaceWalls,s=this._openCuts(),a=this._openingWallIndexFor(n,s).value;return W`${i.map(e=>{if(e.orphanReason)return W`{t.stopPropagation(),this._editOpening(e)}}> ! - `;const t=this._openingAmt(e),i=t>0&&!!e.contact&&this._renderOpeningEntityAvailable(e.contact)?"var(--hp-open)":r,n="gate"===e.type?!e.flip_v:e.flip_v,s=e.partitionHost||o.length||"gate"===e.type?this._openingFace(e,a,!!n):{ox:0,oy:0,cm:0,side:-1},l={type:e.type,length:e.rlen,angle:e.angle,amount:t,flipH:!!e.flip_h,flipV:!!e.flip_v,base:r,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s},{half:c,outlineHalf:h,hitHalf:d}=Wu(l),u=Ia(10,this._cellCm),p=Ia(12,this._cellCm);return j``;const t=this._openingAmt(e),i=t>0&&!!e.contact&&this._renderOpeningEntityAvailable(e.contact)?"var(--hp-open)":r,n="gate"===e.type?!e.flip_v:e.flip_v,s=e.partitionHost||o.length||"gate"===e.type?this._openingFace(e,a,!!n):{ox:0,oy:0,cm:0,side:-1},l={type:e.type,length:e.rlen,angle:e.angle,amount:t,flipH:!!e.flip_h,flipV:!!e.flip_v,base:r,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s},{half:c,outlineHalf:h,hitHalf:d}=Ku(l),u=Ia(10,this._cellCm),p=Ia(12,this._cellCm);return W` - ${Ku(l)} + ${Qu(l)} @@ -5794,7 +5794,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e @pointermove=${t=>this._opPointerMove(t,e)} @pointerup=${t=>this._opPointerUp(t,e)} @pointercancel=${t=>this._opPointerUp(t,e)}> - `})}`}_renderOpeningLocks(e,t){const i=this._openingsR.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&e.lock&&this._renderOpeningEntityAvailable(e.lock));if(!i.length)return W``;const n=this._spaceModel();if(!n)return W``;const r=this._openCuts(),o=this._openingWallIndexFor(n,r).value;return W`${i.map(i=>{const n=this._renderPlanHass.states[i.lock]?.state,r="locked"===n,s=r||["unlocked","open","opening","unlocking","locking"].includes(String(n)),a="gate"===i.type?this._openingFace(i,o,!i.flip_v):null,l=qu({x:i.rx,y:i.ry,angle:i.angle,flipV:!!i.flip_v,gateFace:a},this._cellCm)[0],c=t?.get(String(i.id)),h=c?.visualScene??this._scenePoint(l),d=(h[0]-e.x)/e.w*100,u=(h[1]-e.y)/e.h*100;return W`
`})}`}_renderOpeningLocks(e,t){const i=this._openingsR.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&e.lock&&this._renderOpeningEntityAvailable(e.lock));if(!i.length)return j``;const n=this._spaceModel();if(!n)return j``;const r=this._openCuts(),o=this._openingWallIndexFor(n,r).value;return j`${i.map(i=>{const n=this._renderPlanHass.states[i.lock]?.state,r="locked"===n,s=r||["unlocked","open","opening","unlocking","locking"].includes(String(n)),a="gate"===i.type?this._openingFace(i,o,!i.flip_v):null,l=Gu({x:i.rx,y:i.ry,angle:i.angle,flipV:!!i.flip_v,gateFace:a},this._cellCm)[0],c=t?.get(String(i.id)),h=c?.visualScene??this._scenePoint(l),d=(h[0]-e.x)/e.w*100,u=(h[1]-e.y)/e.h*100;return j`
-
`})}`}async _lockAction(e,t){if(this._openingEntityAvailable(e)){if("unlock"===t){const t=this.hass?.states?.[e]?.attributes?.friendly_name||e,i=await this._confirmDanger({key:"unlock",kind:"warning",title:this._t("confirm.unlock_title"),message:this._t("confirm.unlock_body"),objectName:t,confirmLabel:this._t("opening.unlock_action"),cancelLabel:this._t("btn.cancel")}),n=this._openingInfo;if(!i||!this._openingEntityAvailable(e)||!n||"door"!==n.type&&"gate"!==n.type||n.lock!==e||"locked"!==this.hass?.states?.[e]?.state)return}this.hass?.callService?.("lock",t,{entity_id:e})}}_renderOpeningInfoCard(){const e=this._openingInfo,t="passage"!==e.type&&e.contact&&this._openingEntityAvailable(e.contact)?e.contact:null,i=("door"===e.type||"gate"===e.type)&&e.lock&&this._openingEntityAvailable(e.lock)?e.lock:null,n=t?this.hass.states[t]?.state:null,r=this._openingAmt(e),o=i?this.hass.states[i]?.state:null,s="door"===e.type?"opening.door":"gate"===e.type?"opening.gate":"passage"===e.type?"opening.passage":"opening.window",a="door"===e.type?"mdi:door":"gate"===e.type?"mdi:gate":"passage"===e.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===e.type?r>0?"mdi:gate-open":"mdi:gate":r>0?"mdi:door-open":"mdi:door-closed",c=(e,t,i,n="")=>W`
${t}${i}
`;return W``})}`}async _lockAction(e,t){if(this._openingEntityAvailable(e)){if("unlock"===t){const t=this.hass?.states?.[e]?.attributes?.friendly_name||e,i=await this._confirmDanger({key:"unlock",kind:"warning",title:this._t("confirm.unlock_title"),message:this._t("confirm.unlock_body"),objectName:t,confirmLabel:this._t("opening.unlock_action"),cancelLabel:this._t("btn.cancel")}),n=this._openingInfo;if(!i||!this._openingEntityAvailable(e)||!n||"door"!==n.type&&"gate"!==n.type||n.lock!==e||"locked"!==this.hass?.states?.[e]?.state)return}this.hass?.callService?.("lock",t,{entity_id:e})}}_renderOpeningInfoCard(){const e=this._openingInfo,t="passage"!==e.type&&e.contact&&this._openingEntityAvailable(e.contact)?e.contact:null,i=("door"===e.type||"gate"===e.type)&&e.lock&&this._openingEntityAvailable(e.lock)?e.lock:null,n=t?this.hass.states[t]?.state:null,r=this._openingAmt(e),o=i?this.hass.states[i]?.state:null,s="door"===e.type?"opening.door":"gate"===e.type?"opening.gate":"passage"===e.type?"opening.passage":"opening.window",a="door"===e.type?"mdi:door":"gate"===e.type?"mdi:gate":"passage"===e.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===e.type?r>0?"mdi:gate-open":"mdi:gate":r>0?"mdi:door-open":"mdi:door-closed",c=(e,t,i,n="")=>j`
${t}${i}
`;return j`this._openingInfo=null}>
${t?c(l,this._t("opening.contact_label"),"unavailable"===n||null==n?this._t("opening.state_unknown"):this._t(r>0?"opening.open":"opening.closed"),r>0?"warn":"ok"):V} ${i?c("locked"===o?"mdi:lock":"mdi:lock-open-variant",this._t("opening.lock_label"),"locked"===o?this._t("opening.locked"):["unlocked","open"].includes(String(o))?this._t("opening.unlocked"):this._t("opening.state_unknown"),"locked"===o?"ok":"warn"):V} - ${i&&("locked"===o||["unlocked","open"].includes(String(o)))?W``:i&&["locking","unlocking"].includes(String(o))?W``:i&&["locking","unlocking"].includes(String(o))?j``:V} - ${t||i?V:W`

${this._t("opening.no_entities")}

`} + ${t||i?V:j`

${this._t("opening.no_entities")}

`}
-
`}_renderOpeningDialog(){return this._editorRuntimeOrThrow()._renderOpeningDialog()}_gridLevels(){return this._editorRuntimeOrThrow()._gridLevels()}_renderMarkupDefs(e){return this._editorRuntimeOrThrow()._renderMarkupDefs(e)}_renderPhysicalEditorLayer(){return this._editorRuntimeOrThrow()._renderPhysicalEditorLayer()}_renderHiddenWallDiagnosticOverlay(){return this._editorRuntimeOrThrow()._renderHiddenWallDiagnosticOverlay()}_renderPlanSnapOverlay(){return this._editorRuntimeOrThrow()._renderPlanSnapOverlay()}_syncPlanSnapActiveMarker(e){return this._editorRuntimeOrThrow()._syncPlanSnapActiveMarker(e)}_syncPlanSnapConflictMarkers(e){return this._editorRuntimeOrThrow()._syncPlanSnapConflictMarkers(e)}_planSnapPhysicalSegment(e){return this._editorRuntimeOrThrow()._planSnapPhysicalSegment(e)}_drawPreviewJoinPatchD(e,t){return this._editorRuntimeOrThrow()._drawPreviewJoinPatchD(e,t)}_renderMarkupLayer(e){return this._editorRuntimeOrThrow()._renderMarkupLayer(e)}_renderActiveChainInk(){return this._editorRuntimeOrThrow()._renderActiveChainInk()}_renderPartitionDeleteDialog(){return this._editorRuntimeOrThrow()._renderPartitionDeleteDialog()}_renderRoomDeleteDialog(){return this._editorRuntimeOrThrow()._renderRoomDeleteDialog()}_renderPhysicalDialog(){return this._editorRuntimeOrThrow()._renderPhysicalDialog()}_renderMarkupBar(){return this._editorRuntimeOrThrow()._renderMarkupBar()}_renderDevicesBar(){return this._editorRuntimeOrThrow()._renderDevicesBar()}_renderDeviceInbox(){return this._editorRuntimeOrThrow()._renderDeviceInbox()}_cardEntities(e){const t=this._planHass,i=[],n=new Set,r=e=>{if(!e||n.has(e)||!t.states[e])return;const r=t.entities[e];if("config"===r?.entity_category||"diagnostic"===r?.entity_category)return;n.add(e);const o=e.split(".")[0];["light","switch","fan","humidifier","siren","input_boolean"].includes(o)?i.push({eid:e,kind:"toggle"}):["cover","valve","lock","climate","media_player","vacuum","water_heater"].includes(o)?i.push({eid:e,kind:"open"}):["sensor","binary_sensor","number","select"].includes(o)&&i.push({eid:e,kind:"value"})};for(const i of cd(t,this._devices,null,this._virtualLights))if(i.device.id===e.id)for(const e of[...i.serviceEids,...i.stateEids])r(e);e.primary&&r(e.primary);for(const t of e.entities)r(t);return i.slice(0,12)}_cardToggle(e){const t=e.split(".")[0];"lock"!==t&&"alarm_control_panel"!==t&&this._planEntityAvailable(e)&&this.hass.callService("homeassistant","toggle",{entity_id:e}).catch(e=>this._showToast(this._t("toast.error",{err:this._errText(e)})))}_renderInfoCard(){const e=this._infoCard,t=e.primary?this.hass.states[e.primary]:void 0,i=t?Gi(this.hass,e.primary)?.text??t.state:null,n=(e.controls??e.marker?.controls??[]).filter(Mn).filter(e=>this._planEntityAvailable(e));return W``}_renderOpeningDialog(){return this._editorRuntimeOrThrow()._renderOpeningDialog()}_gridLevels(){return this._editorRuntimeOrThrow()._gridLevels()}_renderMarkupDefs(e){return this._editorRuntimeOrThrow()._renderMarkupDefs(e)}_renderPhysicalEditorLayer(){return this._editorRuntimeOrThrow()._renderPhysicalEditorLayer()}_renderHiddenWallDiagnosticOverlay(){return this._editorRuntimeOrThrow()._renderHiddenWallDiagnosticOverlay()}_renderPlanSnapOverlay(){return this._editorRuntimeOrThrow()._renderPlanSnapOverlay()}_syncPlanSnapActiveMarker(e){return this._editorRuntimeOrThrow()._syncPlanSnapActiveMarker(e)}_syncPlanSnapConflictMarkers(e){return this._editorRuntimeOrThrow()._syncPlanSnapConflictMarkers(e)}_planSnapPhysicalSegment(e){return this._editorRuntimeOrThrow()._planSnapPhysicalSegment(e)}_drawPreviewJoinPatchD(e,t){return this._editorRuntimeOrThrow()._drawPreviewJoinPatchD(e,t)}_renderMarkupLayer(e){return this._editorRuntimeOrThrow()._renderMarkupLayer(e)}_renderActiveChainInk(){return this._editorRuntimeOrThrow()._renderActiveChainInk()}_renderPartitionDeleteDialog(){return this._editorRuntimeOrThrow()._renderPartitionDeleteDialog()}_renderRoomDeleteDialog(){return this._editorRuntimeOrThrow()._renderRoomDeleteDialog()}_renderPhysicalDialog(){return this._editorRuntimeOrThrow()._renderPhysicalDialog()}_renderMarkupBar(){return this._editorRuntimeOrThrow()._renderMarkupBar()}_renderDevicesBar(){return this._editorRuntimeOrThrow()._renderDevicesBar()}_renderDeviceInbox(){return this._editorRuntimeOrThrow()._renderDeviceInbox()}_cardEntities(e){const t=this._planHass,i=[],n=new Set,r=e=>{if(!e||n.has(e)||!t.states[e])return;const r=t.entities[e];if("config"===r?.entity_category||"diagnostic"===r?.entity_category)return;n.add(e);const o=e.split(".")[0];["light","switch","fan","humidifier","siren","input_boolean"].includes(o)?i.push({eid:e,kind:"toggle"}):["cover","valve","lock","climate","media_player","vacuum","water_heater"].includes(o)?i.push({eid:e,kind:"open"}):["sensor","binary_sensor","number","select"].includes(o)&&i.push({eid:e,kind:"value"})};for(const i of _d(t,this._devices,null,this._virtualLights))if(i.device.id===e.id)for(const e of[...i.serviceEids,...i.stateEids])r(e);e.primary&&r(e.primary);for(const t of e.entities)r(t);return i.slice(0,12)}_cardToggle(e){const t=e.split(".")[0];"lock"!==t&&"alarm_control_panel"!==t&&this._planEntityAvailable(e)&&this.hass.callService("homeassistant","toggle",{entity_id:e}).catch(e=>this._showToast(this._t("toast.error",{err:this._errText(e)})))}_renderInfoCard(){const e=this._infoCard,t=e.primary?this.hass.states[e.primary]:void 0,i=t?Gi(this.hass,e.primary)?.text??t.state:null,n=(e.controls??e.marker?.controls??[]).filter(Mn).filter(e=>this._planEntityAvailable(e));return j`
- ${(()=>{const t=this._cardEntities(e);return t.length?W`
- ${t.map(({eid:e,kind:t})=>{const i=this.hass.states[e],n=this.hass.entities[e]?.name||i?.attributes?.friendly_name||e,r=i?Gi(this.hass,e)?.text??i.state:"",o="on"===i?.state||["open","unlocked","playing","cleaning"].includes(i?.state);return W`
- + ${(()=>{const t=this._cardEntities(e);return t.length?j`
+ ${t.map(({eid:e,kind:t})=>{const i=this.hass.states[e],n=this.hass.entities[e]?.name||i?.attributes?.friendly_name||e,r=i?Gi(this.hass,e)?.text??i.state:"",o="on"===i?.state||["open","unlocked","playing","cleaning"].includes(i?.state);return j`
+ ${n} - ${"toggle"===t?W``:"open"===t?W``:W`${r}`} + ${"toggle"===t?j``:"open"===t?j``:j`${r}`}
`})}
`:V})()} - ${e.model?W`
${this._t("info.model")}${e.model}
`:V} - ${i&&!this._cardEntities(e).length?W`
${this._t("info.state")}${i}
`:V} - ${Ii(e.link)?W`
${this._t("info.link")} + ${e.model?j`
${this._t("info.model")}${e.model}
`:V} + ${i&&!this._cardEntities(e).length?j`
${this._t("info.state")}${i}
`:V} + ${Ii(e.link)?j`
${this._t("info.link")} ${e.link}
`:V} - ${e.description?W`
${e.description}
`:V} - ${e.pdfs&&e.pdfs.length?W`
${this._t("info.manuals")} - ${e.pdfs.map(e=>W` + ${e.description?j`
${e.description}
`:V} + ${e.pdfs&&e.pdfs.length?j`
`:V} - ${n.length?W`
${this._t("info.controls")} + ${n.length?j`
${this._t("info.controls")} - ${n.map(e=>{const t=this.hass.states[e],i="on"===t?.state;return W` + ${n.map(e=>{const t=this.hass.states[e],i="on"===t?.state;return j` ${t?.attributes?.friendly_name||e}`})}
`:V} - ${e.model||i||e.link||e.description||e.pdfs&&e.pdfs.length||n.length?V:W`
${this._t("info.none")}
`} + ${e.model||i||e.link||e.description||e.pdfs&&e.pdfs.length||n.length?V:j`
${this._t("info.none")}
`}
- ${e.primary?W``:V}
- `}_markerValueBadgeFields(e){return this._editorRuntimeOrThrow()._markerValueBadgeFields(e)}_markerDraft(e){return this._editorRuntimeOrThrow()._markerDraft(e)}_markerPreviewDevice(e){return this._editorRuntimeOrThrow()._markerPreviewDevice(e)}_markerPreviewDevices(e){return this._editorRuntimeOrThrow()._markerPreviewDevices(e)}_toggleIntent(e,t=this._devices){return ou({hass:this._planHass,registryHass:this._fullRegistryHass,devices:t,device:e,virtualLights:this._virtualLights})}_toggleIntentForDialog(e){return this._editorRuntimeOrThrow()._toggleIntentForDialog(e)}_toggleStateText(e,t){const i=this._planHass?.states?.[e]||this.hass?.states?.[e];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):t}catch{return t}}_toggleConfirmationStateText(e){const t=String(e.state||"unknown"),i=e.entityId?this._toggleStateText(e.entityId,t):t;if(i.trim().toLocaleLowerCase()!==t.trim().toLocaleLowerCase())return i;const n={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[t];return n?this._t(n):t.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(e){const t={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(e,t){if(!au(e)||!e.nextEffect||!e.targets.length)return[];const i="group"===e.kind,n=i?e.targets.filter(e=>"on"===e.state).length:0,r=i?0===n?t.groupAllOff():t.groupCurrent(n,e.targets.length):t.state(e.targets[0]);let o;return o="toggle"===e.nextEffect?t.expectedByHa():i&&"turn-on"===e.nextEffect?t.groupAllOn():i&&"turn-off"===e.nextEffect?t.groupAllOff():t.effect(e.nextEffect),[t.current(r),t.expected(o),...e.skippedTargets.length?[t.unavailable(e.skippedTargets.length)]:[]]}(e,{state:e=>this._toggleConfirmationStateText(e),current:e=>this._t("confirm.current_state",{state:e}),expected:e=>this._t("confirm.expected_state",{state:e}),groupCurrent:(e,t)=>this._t("confirm.group_current",{on:e,total:t}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:e=>this._t("confirm.unavailable_targets",{count:e}),effect:e=>this._t(t[e]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(e){return this._editorRuntimeOrThrow()._toggleHintLines(e)}_effectiveStoredTapAction(e,t){return this._editorRuntimeOrThrow()._effectiveStoredTapAction(e,t)}_effectiveMarkerTapAction(e,t=this._markerPreviewDevice(e)){return this._editorRuntimeOrThrow()._effectiveMarkerTapAction(e,t)}_announceToggleDraft(e){return this._editorRuntimeOrThrow()._announceToggleDraft(e)}_valueBadgeForBinding(e,t){return this._editorRuntimeOrThrow()._valueBadgeForBinding(e,t)}_markerSpatialSource(e){return this._editorRuntimeOrThrow()._markerSpatialSource(e)}_markerAutoHasSpatialSource(e){return this._editorRuntimeOrThrow()._markerAutoHasSpatialSource(e)}_setMarkerLightRole(e){return this._editorRuntimeOrThrow()._setMarkerLightRole(e)}_controlRefInfo(e){return this._editorRuntimeOrThrow()._controlRefInfo(e)}_valueBadgeCandidateLabel(e){return this._editorRuntimeOrThrow()._valueBadgeCandidateLabel(e)}_controlCandidates(e){return this._editorRuntimeOrThrow()._controlCandidates(e)}_addControlRef(e,t){return this._editorRuntimeOrThrow()._addControlRef(e,t)}_setMarkerGlowMode(e){return this._editorRuntimeOrThrow()._setMarkerGlowMode(e)}_renderMarkerDialog(){return this._editorRuntimeOrThrow()._renderMarkerDialog()}_renderSpaceDialog(){return this._onboardingRuntime&&this._spaceDialog&&this._spaceDialogUsesOnboardingRuntime(this._spaceDialog.mode)?this._onboardingRuntime._renderSpaceDialog():this._editorRuntimeOrThrow()._renderSpaceDialog()}_renderMergeDialog(){return this._editorRuntimeOrThrow()._renderMergeDialog()}_renderCardPreview(e,t,i){const n=18*e;return W`
+ `}_markerValueBadgeFields(e){return this._editorRuntimeOrThrow()._markerValueBadgeFields(e)}_markerDraft(e){return this._editorRuntimeOrThrow()._markerDraft(e)}_markerPreviewDevice(e){return this._editorRuntimeOrThrow()._markerPreviewDevice(e)}_markerPreviewDevices(e){return this._editorRuntimeOrThrow()._markerPreviewDevices(e)}_toggleIntent(e,t=this._devices){return hu({hass:this._planHass,registryHass:this._fullRegistryHass,devices:t,device:e,virtualLights:this._virtualLights})}_toggleIntentForDialog(e){return this._editorRuntimeOrThrow()._toggleIntentForDialog(e)}_toggleStateText(e,t){const i=this._planHass?.states?.[e]||this.hass?.states?.[e];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):t}catch{return t}}_toggleConfirmationStateText(e){const t=String(e.state||"unknown"),i=e.entityId?this._toggleStateText(e.entityId,t):t;if(i.trim().toLocaleLowerCase()!==t.trim().toLocaleLowerCase())return i;const n={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[t];return n?this._t(n):t.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(e){const t={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(e,t){if(!uu(e)||!e.nextEffect||!e.targets.length)return[];const i="group"===e.kind,n=i?e.targets.filter(e=>"on"===e.state).length:0,r=i?0===n?t.groupAllOff():t.groupCurrent(n,e.targets.length):t.state(e.targets[0]);let o;return o="toggle"===e.nextEffect?t.expectedByHa():i&&"turn-on"===e.nextEffect?t.groupAllOn():i&&"turn-off"===e.nextEffect?t.groupAllOff():t.effect(e.nextEffect),[t.current(r),t.expected(o),...e.skippedTargets.length?[t.unavailable(e.skippedTargets.length)]:[]]}(e,{state:e=>this._toggleConfirmationStateText(e),current:e=>this._t("confirm.current_state",{state:e}),expected:e=>this._t("confirm.expected_state",{state:e}),groupCurrent:(e,t)=>this._t("confirm.group_current",{on:e,total:t}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:e=>this._t("confirm.unavailable_targets",{count:e}),effect:e=>this._t(t[e]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(e){return this._editorRuntimeOrThrow()._toggleHintLines(e)}_effectiveStoredTapAction(e,t){return this._editorRuntimeOrThrow()._effectiveStoredTapAction(e,t)}_effectiveMarkerTapAction(e,t=this._markerPreviewDevice(e)){return this._editorRuntimeOrThrow()._effectiveMarkerTapAction(e,t)}_announceToggleDraft(e){return this._editorRuntimeOrThrow()._announceToggleDraft(e)}_valueBadgeForBinding(e,t){return this._editorRuntimeOrThrow()._valueBadgeForBinding(e,t)}_markerSpatialSource(e){return this._editorRuntimeOrThrow()._markerSpatialSource(e)}_markerAutoHasSpatialSource(e){return this._editorRuntimeOrThrow()._markerAutoHasSpatialSource(e)}_setMarkerLightRole(e){return this._editorRuntimeOrThrow()._setMarkerLightRole(e)}_controlRefInfo(e){return this._editorRuntimeOrThrow()._controlRefInfo(e)}_valueBadgeCandidateLabel(e){return this._editorRuntimeOrThrow()._valueBadgeCandidateLabel(e)}_controlCandidates(e){return this._editorRuntimeOrThrow()._controlCandidates(e)}_addControlRef(e,t){return this._editorRuntimeOrThrow()._addControlRef(e,t)}_setMarkerGlowMode(e){return this._editorRuntimeOrThrow()._setMarkerGlowMode(e)}_renderMarkerDialog(){return this._editorRuntimeOrThrow()._renderMarkerDialog()}_renderSpaceDialog(){return this._onboardingRuntime&&this._spaceDialog&&this._spaceDialogUsesOnboardingRuntime(this._spaceDialog.mode)?this._onboardingRuntime._renderSpaceDialog():this._editorRuntimeOrThrow()._renderSpaceDialog()}_renderMergeDialog(){return this._editorRuntimeOrThrow()._renderMergeDialog()}_renderCardPreview(e,t,i){const n=18*e;return j`
${this._t("preview.room_name")} @@ -5872,4 +5872,4 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e 45% · ${this._t("roomcard.light_partial",{on:1,total:3})} -
`}_renderRoomSource(e){return this._editorRuntimeOrThrow()._renderRoomSource(e)}_renderRoomDialog(){return this._editorRuntimeOrThrow()._renderRoomDialog()}}zf.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_editorRuntimeLoadingVisible:{state:!0},_backdropGuard:{state:!0},_tapConfirm:{state:!0},_dangerConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_decorImagePalette:{state:!0},_decorAssetCatalog:{state:!0},_decorAssetBusy:{state:!0},_furnCategory:{state:!0},_furnPreviewInput:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_deviceInbox:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_supportDialog:{state:!0},_alignDialog:{state:!0},_preflightClipboardFallback:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0}},zf.ZOOM_MAX=8,zf.ZOOM_MIN=1/3,zf.styles=[xu,zm],customElements.get("houseplan-card")||customElements.define("houseplan-card",zf),window.customCards=window.customCards||[],window.customCards.find(e=>"houseplan-card"===e.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${df} `,"background:#3ea6ff;color:#04121f;font-weight:700","");export{Il as $,V as A,Ip as B,Xu as C,le as D,Ep as E,Vm as F,vi as G,Or as H,ki as I,xi as J,qt as K,$i as L,Xa as M,Na as N,di as O,vo as P,ei as Q,Po as R,Wp as S,jp as T,gs as U,Qr as V,Wo as W,Bo as X,n_ as Y,Hl as Z,el as _,Pm as a,Ro as a$,Al as a0,$s as a1,ls as a2,Ss as a3,Ks as a4,As as a5,ni as a6,Ka as a7,_u as a8,ku as a9,Cn as aA,Bn as aB,R_ as aC,Sr as aD,$_ as aE,Sl as aF,Dl as aG,jl as aH,Va as aI,Ul as aJ,ps as aK,Zs as aL,Zo as aM,la as aN,Aa as aO,t_ as aP,ha as aQ,Rs as aR,Gm as aS,hn as aT,_r as aU,pr as aV,ur as aW,cn as aX,Pe as aY,Lu as aZ,yg as a_,Ms as aa,yo as ab,bu as ac,uu as ad,Ko as ae,Cs as af,mu as ag,ea as ah,na as ai,_o as aj,go as ak,Yr as al,Qp as am,Uo as an,Ya as ao,qo as ap,Ba as aq,qa as ar,Zi as as,Ji as at,Ui as au,Vi as av,Ua as aw,xd as ax,Sd as ay,ii as az,W as b,mi as b$,Qa as b0,Xt as b1,Zt as b2,Er as b3,da as b4,ic as b5,e_ as b6,fo as b7,Am as b8,gi as b9,Nn as bA,br as bB,kr as bC,Bl as bD,zr as bE,ql as bF,Ol as bG,zl as bH,Wl as bI,Nl as bJ,Ll as bK,b_ as bL,Yo as bM,Wu as bN,yu as bO,af as bP,vu as bQ,ra as bR,tf as bS,lf as bT,Up as bU,oi as bV,gu as bW,wu as bX,Ri as bY,_i as bZ,ri as b_,ui as ba,Di as bb,Da as bc,fa as bd,ga as be,Vo as bf,Go as bg,Xs as bh,Jt as bi,vl as bj,Ra as bk,Ma as bl,Un as bm,Vn as bn,yi as bo,us as bp,ds as bq,o_ as br,s_ as bs,Dr as bt,Fr as bu,Pr as bv,$r as bw,wr as bx,xr as by,Cr as bz,Jl as c,cd as c$,Xo as c0,zi as c1,kn as c2,lp as c3,cp as c4,Yh as c5,tu as c6,Ei as c7,qi as c8,jn as c9,mc as cA,bc as cB,Tc as cC,lc as cD,wc as cE,gc as cF,fc as cG,Cc as cH,$c as cI,rc as cJ,En as cK,Hn as cL,si as cM,nf as cN,Ku as cO,ef as cP,bl as cQ,Ts as cR,ns as cS,rs as cT,Ae as cU,Fd as cV,hp as cW,dp as cX,Td as cY,hu as cZ,hd as c_,On as ca,bd as cb,__ as cc,mo as cd,kd as ce,yd as cf,ln as cg,sn as ch,on as ci,Ea as cj,Xp as ck,rn as cl,nn as cm,tn as cn,en as co,Oa as cp,h_ as cq,r_ as cr,Rr as cs,dn as ct,Km as cu,no as cv,mr as cw,Fe as cx,Ne as cy,Ie as cz,Fm as d,od as d0,Zh as d1,Mn as d2,Kh as d3,wd as d4,xn as d5,Cp as d6,Ju as d7,sd as d8,ad as d9,Si as dA,Fp as dB,Og as dC,Eg as dD,xg as dE,Op as dF,Fa as dG,pe as dH,_e as dI,U as dJ,Eu as dK,Ru as dL,Au as dM,Cu as dN,Yt as dO,zf as dP,Jh as da,Xd as db,Hi as dc,Oi as dd,Qu as de,Ii as df,Ha as dg,Ni as dh,Li as di,bo as dj,hi as dk,Md as dl,Cd as dm,Ga as dn,nc as dp,pg as dq,_g as dr,Bu as ds,gg as dt,fl as du,mg as dv,fg as dw,wa as dx,js as dy,qu as dz,Pc as e,Mc as f,Js as g,xo as h,Rc as i,$o as j,So as k,Hu as l,Ia as m,zc as n,Oc as o,Co as p,o as q,Ic as r,Qi as s,he as t,Ut as u,xu as v,j as w,Nu as x,pp as y,Pp as z}; +
`}_renderRoomSource(e){return this._editorRuntimeOrThrow()._renderRoomSource(e)}_renderRoomDialog(){return this._editorRuntimeOrThrow()._renderRoomDialog()}}Of.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_editorRuntimeLoadingVisible:{state:!0},_backdropGuard:{state:!0},_tapConfirm:{state:!0},_dangerConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_decorImagePalette:{state:!0},_decorAssetCatalog:{state:!0},_decorAssetBusy:{state:!0},_furnCategory:{state:!0},_furnPreviewInput:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_deviceInbox:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_supportDialog:{state:!0},_alignDialog:{state:!0},_preflightClipboardFallback:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0}},Of.ZOOM_MAX=8,Of.ZOOM_MIN=1/3,Of.styles=[Cu,Om],customElements.get("houseplan-card")||customElements.define("houseplan-card",Of),window.customCards=window.customCards||[],window.customCards.find(e=>"houseplan-card"===e.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${gf} `,"background:#3ea6ff;color:#04121f;font-weight:700","");export{Ll as $,V as A,Lp as B,tp as C,le as D,qp as E,Zm as F,vi as G,Or as H,ki as I,xi as J,qt as K,$i as L,Xa as M,Ha as N,di as O,vo as P,ei as Q,Fo as R,Kp as S,Yp as T,gs as U,Qr as V,jo as W,Bo as X,l_ as Y,Fl as Z,el as _,Nm as a,Sg as a$,El as a0,$s as a1,ls as a2,Ss as a3,Ks as a4,Ps as a5,ni as a6,Ka as a7,yu as a8,Ru as a9,Cn as aA,Bn as aB,P_ as aC,Sr as aD,D_ as aE,Cl as aF,Il as aG,Yl as aH,Va as aI,Xl as aJ,jl as aK,ps as aL,Zs as aM,Zo as aN,la as aO,Pa as aP,s_ as aQ,ha as aR,Rs as aS,Jm as aT,hn as aU,_r as aV,pr as aW,ur as aX,cn as aY,Fe as aZ,Uu as a_,Ms as aa,yo as ab,$u as ac,fu as ad,Ko as ae,Cs as af,bu as ag,ea as ah,na as ai,_o as aj,go as ak,Yr as al,r_ as am,Uo as an,Ya as ao,qo as ap,Ba as aq,qa as ar,Zi as as,Ji as at,Ui as au,Vi as av,Ua as aw,Cd as ax,Td as ay,ii as az,j as b,ri as b$,Ro as b0,Qa as b1,Xt as b2,Zt as b3,Er as b4,da as b5,ac as b6,o_ as b7,fo as b8,Em as b9,Cr as bA,Hn as bB,br as bC,kr as bD,Vl as bE,Ar as bF,Gl as bG,Bl as bH,Ol as bI,Kl as bJ,Wl as bK,Ul as bL,$_ as bM,Yo as bN,Ku as bO,Su as bP,uf as bQ,xu as bR,ra as bS,af as bT,pf as bU,Xp as bV,oi as bW,wu as bX,Mu as bY,Ri as bZ,_i as b_,gi as ba,ui as bb,Di as bc,Da as bd,fa as be,ga as bf,Vo as bg,Go as bh,Xs as bi,Jt as bj,vl as bk,Ra as bl,Ma as bm,Un as bn,Vn as bo,yi as bp,us as bq,ds as br,h_ as bs,d_ as bt,Dr as bu,zr as bv,Fr as bw,$r as bx,wr as by,xr as bz,nc as c,md as c$,mi as c0,Xo as c1,Ai as c2,kn as c3,pp as c4,_p as c5,ed as c6,su as c7,Ei as c8,qi as c9,Ie as cA,bc as cB,$c as cC,zc as cD,pc as cE,Mc as cF,wc as cG,kc as cH,Fc as cI,Dc as cJ,cc as cK,En as cL,Nn as cM,si as cN,lf as cO,Qu as cP,sf as cQ,bl as cR,Ts as cS,ns as cT,rs as cU,Pe as cV,Hd as cW,mp as cX,gp as cY,zd as cZ,mu as c_,Wn as ca,On as cb,$d as cc,y_ as cd,mo as ce,Rd as cf,Sd as cg,ln as ch,sn as ci,on as cj,Ea as ck,t_ as cl,rn as cm,nn as cn,tn as co,en as cp,Oa as cq,m_ as cr,c_ as cs,Rr as ct,dn as cu,Qm as cv,no as cw,mr as cx,ze as cy,He as cz,Hm as d,_d as d0,hd as d1,id as d2,Mn as d3,Qh as d4,Md as d5,xn as d6,Fp as d7,np as d8,dd as d9,Ws as dA,Gu as dB,Si as dC,Hp as dD,Bg as dE,qg as dF,Cg as dG,Bp as dH,za as dI,pe as dJ,_e as dK,U as dL,qu as dM,Pu as dN,Eu as dO,Fu as dP,Yt as dQ,Of as dR,ud as da,nd as db,tu as dc,Ni as dd,Oi as de,rp as df,Ii as dg,Na as dh,Hi as di,Li as dj,bo as dk,hi as dl,Ad as dm,Fd as dn,Ga as dp,Rl as dq,lc as dr,vg as ds,yg as dt,Vu as du,wg as dv,fl as dw,bg as dx,kg as dy,wa as dz,Nc as e,Ac as f,Js as g,xo as h,Pc as i,$o as j,So as k,ju as l,Ia as m,Oc as n,Bc as o,Co as p,o as q,Lc as r,Qi as s,he as t,Ut as u,Cu as v,W as w,Wu as x,vp as y,Np as z}; diff --git a/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js b/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js similarity index 79% rename from custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js rename to custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js index f9f0ed84..1be3800c 100644 --- a/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js +++ b/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{s as t,e,n as s,f as i,i as o,l as a,o as n,r,A as l,b as h,a as c,c as d,d as p,D as u,w as _,N as m,g,h as f,j as b,k as v,m as y,p as $,q as w,t as k,u as x,v as S,x as M,y as D,z as C,B as P,C as I,E as T,F as z,G as R,H as A,I as F,J as N,K as H,L,M as E,O,P as B,Q as W,R as G,S as j,T as q,U,V as K,W as V,X as J,Y,Z as X,_ as Z,$ as Q,a0 as tt,a1 as et,a2 as st,a3 as it,a4 as ot,a5 as at,a6 as nt,a7 as rt,a8 as lt,a9 as ht,aa as ct,ab as dt,ac as pt,ad as ut,ae as _t,af as mt,ag as gt,ah as ft,ai as bt,aj as vt,ak as yt,al as $t,am as wt,an as kt,ao as xt,ap as St,aq as Mt,ar as Dt,as as Ct,at as Pt,au as It,av as Tt,aw as zt,ax as Rt,ay as At,az as Ft,aA as Nt,aB as Ht,aC as Lt,aD as Et,aE as Ot,aF as Bt,aG as Wt,aH as Gt,aI as jt,aJ as qt,aK as Ut,aL as Kt,aM as Vt,aN as Jt,aO as Yt,aP as Xt,aQ as Zt,aR as Qt,aS as te,aT as ee,aU as se,aV as ie,aW as oe,aX as ae,aY as ne,aZ as re,a_ as le,a$ as he,b0 as ce,b1 as de,b2 as pe,b3 as ue,b4 as _e,b5 as me,b6 as ge,b7 as fe,b8 as be,b9 as ve,ba as ye,bb as $e,bc as we,bd as ke,be as xe,bf as Se,bg as Me,bh as De,bi as Ce,bj as Pe,bk as Ie,bl as Te,bm as ze,bn as Re,bo as Ae,bp as Fe,bq as Ne,br as He,bs as Le,bt as Ee,bu as Oe,bv as Be,bw as We,bx as Ge,by as je,bz as qe,bA as Ue,bB as Ke,bC as Ve,bD as Je,bE as Ye,bF as Xe,bG as Ze,bH as Qe,bI as ts,bJ as es,bK as ss,bL as is,bM as os,bN as as,bO as ns,bP as rs,bQ as ls,bR as hs,bS as cs,bT as ds,bU as ps,bV as us,bW as _s,bX as ms,bY as gs,bZ as fs,b_ as bs,b$ as vs,c0 as ys,c1 as $s,c2 as ws,c3 as ks,c4 as xs,c5 as Ss,c6 as Ms,c7 as Ds,c8 as Cs,c9 as Ps,ca as Is,cb as Ts,cc as zs,cd as Rs,ce as As,cf as Fs,cg as Ns,ch as Hs,ci as Ls,cj as Es,ck as Os,cl as Bs,cm as Ws,cn as Gs,co as js,cp as qs,cq as Us,cr as Ks,cs as Vs,ct as Js,cu as Ys,cv as Xs,cw as Zs,cx as Qs,cy as ti,cz as ei,cA as si,cB as ii,cC as oi,cD as ai,cE as ni,cF as ri,cG as li,cH as hi,cI as ci,cJ as di,cK as pi,cL as ui,cM as _i,cN as mi,cO as gi,cP as fi,cQ as bi,cR as vi,cS as yi,cT as $i,cU as wi,cV as ki,cW as xi,cX as Si,cY as Mi,cZ as Di,c_ as Ci,c$ as Pi,d0 as Ii,d1 as Ti,d2 as zi,d3 as Ri,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Hi,d8 as Li,d9 as Ei,da as Oi,db as Bi,dc as Wi,dd as Gi,de as ji,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji,dk as Yi,dl as Xi,dm as Zi,dn as Qi}from"./houseplan-card-CODdCIWj.js";import{i as to}from"./guard-BR4mAQsM.js";import{F as eo,f as so,p as io,c as oo,s as ao,i as no,e as ro,r as lo,a as ho,b as co,d as po,g as uo,t as _o}from"./backdrop-pick-BnsHKWaS.js";import{t as mo,h as go,m as fo,T as bo}from"./zigbee-topology-BUFPOnoy.js";var vo={"gs.hint":"Fill colors apply to every space; each color has its own opacity. Which fill mode a space uses is set in that space's dialog.","gs.show_room_tooltip":"Show the room information window on hover","support.about_group":"About the card","support.guide_group":"Documentation","support.guide":"User guide","support.form_group":"Send a report or suggestion","support.contact":"Contact details (email/tg/WhatsApp), optional.","support.message":"Message","support.attach":"Attach anonymized information from your plan","support.attach_hint":"Includes only allowed plan geometry, settings and bounded runtime facts. Excludes names, Home Assistant IDs, live states, URLs, files, and your message/contact.","support.geometry_warning":"The package contains no names or Home Assistant IDs, but it does contain the exact geometry and dimensions of your home.","support.close_busy_title":"Stop the current operation?","support.close_busy_body":"House Plan is preparing or sending the report. Closing now stops waiting for the result.","support.building":"Preparing anonymized data…","support.preview_summary":"Package v{version} · {spaces} spaces · {size} KiB","support.prepared":"Snapshot prepared {n} min ago","support.show_data":"Show data","support.download":"Download JSON","support.refresh":"Refresh snapshot","support.privacy":"When you send, your message, optional contact and, if selected, exact geometry leave your Home Assistant through the House Plan project relay and are visible to maintainers. The project node keeps the report for up to 30 days. Network infrastructure sees your HA server address, but House Plan does not retain it raw; rate-limit and idempotency metadata is kept for up to 24 hours.","support.error_title":"The report was not sent","support.manual_recovery":"You can keep the message and attachment and continue manually:","support.copy_message":"Copy message","support.success":"Report sent: {id}. Save this number when contacting support.","support.copy_id":"Copy ID","support.sending":"Sending…","support.retry":"Retry","support.send":"Send","support.update_required":"Update the House Plan card and integration to compatible versions to send reports.","support.message_copied":"Message copied","support.id_copied":"Report ID copied","support.copy_failed":"Could not access the clipboard. Select and copy the text manually.","support.validation.message_required":"Enter a message.","support.validation.message_too_long":"The message must contain no more than 10,000 characters.","support.validation.contact_too_long":"Contact details must contain no more than 320 characters.","support.validation.preview_missing":"Wait for the attachment preview or turn the attachment off.","support.validation.preview_expired":"The attachment preview expired. Refresh the snapshot.","support.error.support_invalid_message":"Check the message and try again.","support.error.support_preview_expired":"The attachment preview expired or is no longer available. Refresh the snapshot.","support.error.support_package_too_large":"The anonymized package exceeds the 8 MiB limit.","support.error.support_rate_limited":"Too many reports or previews were requested. Try again later.","support.error.support_unavailable":"The private support service is temporarily unavailable. Your draft remains here.","support.error.support_rejected":"The report did not pass the support service validation.","support.error.unauthorized":"You do not have permission to send this report.","vac.routes_section":"Maps and floors","vac.routes_current_map":"Current map","vac.routes_no_map":"no telemetry","vac.routes_status":"Routing","vac.routes_state_ready":"map assigned and calibrated","vac.routes_state_needs_calibration":"map assigned, calibration needed","vac.routes_state_unmapped":"current map is not assigned to a floor","vac.routes_state_ambiguous":"two maps are indistinguishable — no floor is chosen","vac.routes_state_missing_space":"the map's space was deleted","vac.routes_state_none":"no map data","vac.routes_empty":"No map is assigned to a floor yet.","vac.route_map_default":"no map id","vac.route_active":"Active","vac.route_space":"Space","vac.route_space_none":"not selected","vac.route_status_ready":"ready","vac.route_status_needs_calibration":"needs calibration","vac.route_status_ambiguous":"ambiguous","vac.route_status_missing_space":"space deleted","vac.route_missing_space_group":"Deleted space","vac.route_add_current":"Add current map","vac.route_delete":"Remove map","vac.route_delete_title":"Remove the map from its floor?","vac.route_delete_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_delete_confirm":"Remove","vac.route_space_title":"Move the map to another space?","vac.route_space_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_space_confirm":"Move","vac.route_missing_space_hint":"One of the maps points at a deleted space: pick a new one or remove the map. Until then the robot is not drawn for that map.","vac.route_default_hint":"The source reports no stable map id. Several floors cannot be told apart without another source or the robot's own selected map.","vac.route_target_hint":"The dock stays in the “{space}” space regardless of the current map.","vac.route_add_source":"Add a map source","vac.route_add_source_hint":"For integrations that give each map its own camera. The “All cameras” section above widens this list.","vac.route_source_no_map":"no map reported"};const yo={en:vo,ru:{"gs.hint":"Цвета заливок действуют на все пространства; у каждого цвета своя прозрачность. Какой режим заливки использует пространство — задаётся в его диалоге.","gs.show_room_tooltip":"Показывать окно с информацией при наведении на комнату","support.about_group":"О карточке","support.guide_group":"Документация","support.guide":"Руководство пользователя","support.form_group":"Отправить репорт или предложение","support.contact":"Контакт для связи (email/tg/WhatsApp), необязательно.","support.message":"Сообщение","support.attach":"Прикрепить обезличенную информацию из вашего плана","support.attach_hint":"В пакет входят только разрешённые геометрия, настройки и ограниченные сведения о среде. Не входят имена, HA id, текущие состояния, URL, файлы, сообщение и контакт.","support.geometry_warning":"Пакет не содержит имён и HA id, но содержит точную геометрию и размеры дома.","support.close_busy_title":"Прервать текущую операцию?","support.close_busy_body":"House Plan подготавливает или отправляет репорт. При закрытии ожидание результата прекратится.","support.building":"Подготавливаем обезличенные данные…","support.preview_summary":"Пакет v{version} · пространств: {spaces} · {size} КиБ","support.prepared":"Снимок подготовлен {n} мин назад","support.show_data":"Показать данные","support.download":"Скачать JSON","support.refresh":"Обновить снимок","support.privacy":"При отправке сообщение, необязательный контакт и, если выбран пакет, точная геометрия покидают ваш Home Assistant через relay проекта House Plan и доступны мейнтейнерам. Узел проекта хранит репорт до 30 дней. Сетевая инфраструктура видит адрес сервера HA, но House Plan не сохраняет его в исходном виде; метаданные лимитов и идемпотентности хранятся до 24 часов.","support.error_title":"Репорт не отправлен","support.manual_recovery":"Сообщение и вложение можно сохранить и продолжить вручную:","support.copy_message":"Копировать сообщение","support.success":"Репорт отправлен: {id}. Сохраните номер для связи с поддержкой.","support.copy_id":"Копировать ID","support.sending":"Отправляем…","support.retry":"Повторить","support.send":"Отправить","support.update_required":"Обновите карточку и интеграцию House Plan до совместимых версий, чтобы отправлять репорты.","support.message_copied":"Сообщение скопировано","support.id_copied":"ID репорта скопирован","support.copy_failed":"Не удалось получить доступ к буферу обмена. Выделите и скопируйте текст вручную.","support.validation.message_required":"Введите сообщение.","support.validation.message_too_long":"Сообщение должно содержать не более 10 000 символов.","support.validation.contact_too_long":"Контакт должен содержать не более 320 символов.","support.validation.preview_missing":"Дождитесь предпросмотра вложения или отключите его.","support.validation.preview_expired":"Предпросмотр вложения истёк. Обновите снимок.","support.error.support_invalid_message":"Проверьте сообщение и повторите попытку.","support.error.support_preview_expired":"Предпросмотр вложения истёк или больше недоступен. Обновите снимок.","support.error.support_package_too_large":"Обезличенный пакет превышает лимит 8 МиБ.","support.error.support_rate_limited":"Запрошено слишком много репортов или предпросмотров. Повторите позже.","support.error.support_unavailable":"Закрытая служба поддержки временно недоступна. Черновик сохранён в этом окне.","support.error.support_rejected":"Репорт не прошёл проверку службы поддержки.","support.error.unauthorized":"У вас нет прав на отправку этого репорта.","vac.routes_section":"Карты и этажи","vac.routes_current_map":"Текущая карта","vac.routes_no_map":"источник молчит","vac.routes_status":"Маршрутизация","vac.routes_state_ready":"карта сопоставлена и откалибрована","vac.routes_state_needs_calibration":"карта сопоставлена, нужна калибровка","vac.routes_state_unmapped":"текущая карта не сопоставлена этажу","vac.routes_state_ambiguous":"две карты неразличимы — этаж не выбирается","vac.routes_state_missing_space":"пространство карты удалено","vac.routes_state_none":"нет данных о карте","vac.routes_empty":"Ни одна карта ещё не сопоставлена этажу.","vac.route_map_default":"без идентификатора","vac.route_active":"Текущая","vac.route_space":"Пространство","vac.route_space_none":"не выбрано","vac.route_status_ready":"готова","vac.route_status_needs_calibration":"нужна калибровка","vac.route_status_ambiguous":"неоднозначна","vac.route_status_missing_space":"пространство удалено","vac.route_missing_space_group":"Пространство удалено","vac.route_add_current":"Добавить текущую карту","vac.route_delete":"Удалить карту","vac.route_delete_title":"Удалить карту с этажа?","vac.route_delete_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_delete_confirm":"Удалить","vac.route_space_title":"Перенести карту в другое пространство?","vac.route_space_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_space_confirm":"Перенести","vac.route_missing_space_hint":"Одна из карт ссылается на удалённое пространство: выберите новое или удалите карту. Пока ссылка не исправлена, робот на этой карте не рисуется.","vac.route_default_hint":"Источник не сообщает стабильный идентификатор карты. Несколько этажей нельзя различить без другого источника или собственной карты робота.","vac.route_target_hint":"Док остаётся в пространстве «{space}» независимо от текущей карты.","vac.route_add_source":"Добавить источник карты","vac.route_add_source_hint":"Для интеграций, где у каждой карты своя камера. Список расширяется разделом «Все камеры» выше.","vac.route_source_no_map":"карта не читается"},de:{"gs.hint":"Füllfarben gelten für jeden Bereich; jede Farbe hat ihre eigene Deckkraft. Der Füllmodus wird in den Einstellungen des jeweiligen Bereichs festgelegt.","gs.show_room_tooltip":"Rauminformationen beim Darüberfahren anzeigen","support.about_group":"Über die Karte","support.guide_group":"Dokumentation","support.guide":"Benutzerhandbuch","support.form_group":"Bericht oder Vorschlag senden","support.contact":"Kontakt (E-Mail/tg/WhatsApp), optional.","support.message":"Nachricht","support.attach":"Anonymisierte Informationen aus dem Plan anhängen","support.attach_hint":"Enthält nur erlaubte Plangeometrie, Einstellungen und begrenzte Laufzeitdaten. Namen, Home-Assistant-IDs, Live-Zustände, URLs, Dateien, Nachricht und Kontakt werden ausgeschlossen.","support.geometry_warning":"Das Paket enthält keine Namen oder Home-Assistant-IDs, aber die exakte Geometrie und die Maße Ihres Hauses.","support.close_busy_title":"Aktuellen Vorgang abbrechen?","support.close_busy_body":"House Plan bereitet den Bericht vor oder sendet ihn. Beim Schließen wird nicht weiter auf das Ergebnis gewartet.","support.building":"Anonymisierte Daten werden vorbereitet…","support.preview_summary":"Paket v{version} · {spaces} Bereiche · {size} KiB","support.prepared":"Schnappschuss vor {n} Min. erstellt","support.show_data":"Daten anzeigen","support.download":"JSON herunterladen","support.refresh":"Schnappschuss aktualisieren","support.privacy":"Beim Senden verlassen Ihre Nachricht, der optionale Kontakt und, falls ausgewählt, die exakte Geometrie Ihren Home Assistant über das House-Plan-Projektrelay und sind für die Maintainer sichtbar. Der Projektserver speichert den Bericht bis zu 30 Tage. Die Netzwerkinfrastruktur sieht die Adresse Ihres HA-Servers, House Plan speichert sie jedoch nicht im Rohformat; Limit- und Idempotenzdaten bleiben bis zu 24 Stunden erhalten.","support.error_title":"Der Bericht wurde nicht gesendet","support.manual_recovery":"Nachricht und Anhang können gespeichert und manuell weitergegeben werden:","support.copy_message":"Nachricht kopieren","support.success":"Bericht gesendet: {id}. Bewahren Sie diese Nummer für den Support auf.","support.copy_id":"ID kopieren","support.sending":"Wird gesendet…","support.retry":"Erneut versuchen","support.send":"Senden","support.update_required":"Aktualisieren Sie House-Plan-Karte und Integration auf kompatible Versionen, um Berichte zu senden.","support.message_copied":"Nachricht kopiert","support.id_copied":"Berichts-ID kopiert","support.copy_failed":"Kein Zugriff auf die Zwischenablage. Markieren und kopieren Sie den Text manuell.","support.validation.message_required":"Geben Sie eine Nachricht ein.","support.validation.message_too_long":"Die Nachricht darf höchstens 10.000 Zeichen enthalten.","support.validation.contact_too_long":"Der Kontakt darf höchstens 320 Zeichen enthalten.","support.validation.preview_missing":"Warten Sie auf die Vorschau oder deaktivieren Sie den Anhang.","support.validation.preview_expired":"Die Anhangsvorschau ist abgelaufen. Aktualisieren Sie den Schnappschuss.","support.error.support_invalid_message":"Prüfen Sie die Nachricht und versuchen Sie es erneut.","support.error.support_preview_expired":"Die Anhangsvorschau ist abgelaufen oder nicht mehr verfügbar. Aktualisieren Sie den Schnappschuss.","support.error.support_package_too_large":"Das anonymisierte Paket überschreitet das Limit von 8 MiB.","support.error.support_rate_limited":"Zu viele Berichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","support.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar. Der Entwurf bleibt in diesem Fenster erhalten.","support.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","support.error.unauthorized":"Sie dürfen diesen Bericht nicht senden.","vac.routes_section":"Karten und Etagen","vac.routes_current_map":"Aktuelle Karte","vac.routes_no_map":"keine Telemetrie","vac.routes_status":"Zuordnung","vac.routes_state_ready":"Karte zugeordnet und kalibriert","vac.routes_state_needs_calibration":"Karte zugeordnet, Kalibrierung nötig","vac.routes_state_unmapped":"aktuelle Karte keiner Etage zugeordnet","vac.routes_state_ambiguous":"zwei Karten nicht unterscheidbar — keine Etage gewählt","vac.routes_state_missing_space":"der Raum der Karte wurde gelöscht","vac.routes_state_none":"keine Kartendaten","vac.routes_empty":"Noch keine Karte einer Etage zugeordnet.","vac.route_map_default":"ohne Karten-ID","vac.route_active":"Aktiv","vac.route_space":"Raum","vac.route_space_none":"nicht gewählt","vac.route_status_ready":"bereit","vac.route_status_needs_calibration":"Kalibrierung nötig","vac.route_status_ambiguous":"mehrdeutig","vac.route_status_missing_space":"Raum gelöscht","vac.route_missing_space_group":"Gelöschter Bereich","vac.route_add_current":"Aktuelle Karte hinzufügen","vac.route_delete":"Karte entfernen","vac.route_delete_title":"Karte von der Etage entfernen?","vac.route_delete_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_delete_confirm":"Entfernen","vac.route_space_title":"Karte in einen anderen Raum verschieben?","vac.route_space_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_space_confirm":"Verschieben","vac.route_missing_space_hint":"Eine Karte verweist auf einen gelöschten Raum: neuen wählen oder Karte entfernen. Bis dahin wird der Roboter für diese Karte nicht gezeichnet.","vac.route_default_hint":"Die Quelle meldet keine stabile Karten-ID. Mehrere Etagen lassen sich ohne andere Quelle oder die vom Roboter gewählte Karte nicht unterscheiden.","vac.route_target_hint":"Die Station bleibt unabhängig von der aktuellen Karte im Raum „{space}“.","vac.route_add_source":"Kartenquelle hinzufügen","vac.route_add_source_hint":"Für Integrationen, die jeder Karte eine eigene Kamera geben. Der Abschnitt „Alle Kameras“ oben erweitert diese Liste.","vac.route_source_no_map":"keine Karte gemeldet"},fr:{"gs.hint":"Les couleurs de remplissage s’appliquent à tous les espaces ; chaque couleur possède sa propre opacité. Le mode de remplissage utilisé par un espace se règle dans la boîte de dialogue de cet espace.","gs.show_room_tooltip":"Afficher les informations de la pièce au survol","support.about_group":"À propos de la carte","support.guide_group":"Documentation d’aide","support.guide":"Guide utilisateur","support.form_group":"Envoyer un rapport ou une suggestion","support.contact":"Contact (e-mail/tg/WhatsApp), facultatif.","support.message":"Votre message","support.attach":"Joindre des informations anonymisées de votre plan","support.attach_hint":"Inclut uniquement la géométrie, les réglages autorisés et des données d’exécution limitées. Exclut les noms, identifiants Home Assistant, états en direct, URL, fichiers, message et contact.","support.geometry_warning":"Le paquet ne contient ni noms ni identifiants Home Assistant, mais il contient la géométrie et les dimensions exactes de votre logement.","support.close_busy_title":"Interrompre l’opération en cours ?","support.close_busy_body":"House Plan prépare ou envoie le rapport. Fermer maintenant arrête l’attente du résultat.","support.building":"Préparation des données anonymisées…","support.preview_summary":"Paquet v{version} · {spaces} espaces · {size} Kio","support.prepared":"Instantané préparé il y a {n} min","support.show_data":"Afficher les données","support.download":"Télécharger le JSON","support.refresh":"Actualiser l’instantané","support.privacy":"Lors de l’envoi, votre message, le contact facultatif et, si elle est sélectionnée, la géométrie exacte quittent votre Home Assistant via le relais du projet House Plan et sont visibles par les mainteneurs. Le serveur du projet conserve le rapport jusqu’à 30 jours. L’infrastructure réseau voit l’adresse de votre serveur HA, mais House Plan ne la conserve pas en clair ; les métadonnées de limitation et d’idempotence sont gardées jusqu’à 24 heures.","support.error_title":"Le rapport n’a pas été envoyé","support.manual_recovery":"Vous pouvez conserver le message et la pièce jointe puis continuer manuellement :","support.copy_message":"Copier le message","support.success":"Rapport envoyé : {id}. Conservez ce numéro pour contacter l’assistance.","support.copy_id":"Copier l’ID","support.sending":"Envoi…","support.retry":"Réessayer","support.send":"Envoyer","support.update_required":"Mettez à jour la carte et l’intégration House Plan vers des versions compatibles pour envoyer des rapports.","support.message_copied":"Message copié","support.id_copied":"ID du rapport copié","support.copy_failed":"Impossible d’accéder au presse-papiers. Sélectionnez et copiez le texte manuellement.","support.validation.message_required":"Saisissez un message.","support.validation.message_too_long":"Le message ne doit pas dépasser 10 000 caractères.","support.validation.contact_too_long":"Le contact ne doit pas dépasser 320 caractères.","support.validation.preview_missing":"Attendez l’aperçu de la pièce jointe ou désactivez-la.","support.validation.preview_expired":"L’aperçu de la pièce jointe a expiré. Actualisez l’instantané.","support.error.support_invalid_message":"Vérifiez le message et réessayez.","support.error.support_preview_expired":"L’aperçu de la pièce jointe a expiré ou n’est plus disponible. Actualisez l’instantané.","support.error.support_package_too_large":"Le paquet anonymisé dépasse la limite de 8 Mio.","support.error.support_rate_limited":"Trop de rapports ou d’aperçus ont été demandés. Réessayez plus tard.","support.error.support_unavailable":"Le service d’assistance privé est temporairement indisponible. Le brouillon reste dans cette fenêtre.","support.error.support_rejected":"Le rapport n’a pas passé la validation du service d’assistance.","support.error.unauthorized":"Vous n’êtes pas autorisé à envoyer ce rapport.","vac.routes_section":"Cartes et étages","vac.routes_current_map":"Carte actuelle","vac.routes_no_map":"aucune télémétrie","vac.routes_status":"Routage","vac.routes_state_ready":"carte assignée et calibrée","vac.routes_state_needs_calibration":"carte assignée, calibrage requis","vac.routes_state_unmapped":"carte actuelle non assignée à un étage","vac.routes_state_ambiguous":"deux cartes indiscernables — aucun étage choisi","vac.routes_state_missing_space":"l'espace de la carte a été supprimé","vac.routes_state_none":"aucune donnée de carte","vac.routes_empty":"Aucune carte n'est encore assignée à un étage.","vac.route_map_default":"sans identifiant","vac.route_active":"Active","vac.route_space":"Espace","vac.route_space_none":"non sélectionné","vac.route_status_ready":"prête","vac.route_status_needs_calibration":"calibrage requis","vac.route_status_ambiguous":"ambiguë","vac.route_status_missing_space":"espace supprimé","vac.route_missing_space_group":"Espace supprimé","vac.route_add_current":"Ajouter la carte actuelle","vac.route_delete":"Supprimer la carte","vac.route_delete_title":"Retirer la carte de son étage ?","vac.route_delete_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_delete_confirm":"Supprimer","vac.route_space_title":"Déplacer la carte vers un autre espace ?","vac.route_space_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_space_confirm":"Déplacer","vac.route_missing_space_hint":"Une carte pointe vers un espace supprimé : choisissez-en un autre ou supprimez la carte. D'ici là, le robot n'est pas dessiné pour cette carte.","vac.route_default_hint":"La source ne fournit pas d'identifiant de carte stable. Plusieurs étages ne peuvent pas être distingués sans une autre source ou la carte sélectionnée du robot.","vac.route_target_hint":"La station reste dans l'espace « {space} » quelle que soit la carte actuelle.","vac.route_add_source":"Ajouter une source de carte","vac.route_add_source_hint":"Pour les intégrations qui donnent à chaque carte sa propre caméra. La section « Toutes les caméras » ci-dessus élargit cette liste.","vac.route_source_no_map":"aucune carte signalée"}};function $o(e,s,i){return t(yo[e]?.[s]??vo[s]??s,i)}function wo(t,e,s,i,o){return{markerId:t,source:i,mapId:o,space:e.length?"":s}}function ko(t,e,s){return{...t,space:s.has(e)?e:""}}function xo(t,e=Math.random){const s=new Set(t);for(let t=0;t<64;t+=1){const t="vr_"+Math.floor(16777215*e()).toString(36).padStart(5,"0");if(!s.has(t))return t}return"vr_"+Date.now().toString(36)}function So(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const Mo=new WeakMap,Do=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function Co(t,i,o){const u=t.host,_=a(u.hass,u._config?.language),m=(t,e)=>$o(_,t,e),g=i.marker?.vacuum||{},f=Array.isArray(g.map_routes),b=u._vacSource(i)||"",v=e(i.id,g,i.space,b),y=(u._serverCfg?.spaces||[]).filter(t=>"string"==typeof t?.id&&!!t.id).map(t=>({id:t.id,name:String(t.name||t.id)})),$=new Set(y.map(t=>t.id)),w=n(v,[b],t=>u._vacObservedMapId(i,t)),k=r({routes:v,observed:w,spaceIds:$}),x="ready"===k.kind||"needs_calibration"===k.kind||"missing_space"===k.kind?k.route.id:"",S=b?w[b]:void 0,M=async e=>{let o=f?g.map_routes??null:null;if(!o&&(o=function(t,e,i,o){if(!i)return null;const a=t?.calibration;if(!a||"object"!=typeof a)return null;const n=new Set,r=[];for(const t of Object.keys(a)){const l=s(a[t]);if(!l)continue;const h=o(n);n.add(h),r.push({id:h,source:i,map_id:t,space:e,calibration:l})}return r.length?r:null}(g,i.space,b,t=>xo(t))??[],!b&&Object.keys(g.calibration||{}).length))return!1;const a=e(o);return!!a&&(async e=>{const s=u._serverCfg;if(!s)return!1;const o=JSON.parse(JSON.stringify(s));o.markers=o.markers||[];let a=o.markers.find(t=>t.id===i.id);if(!a){if("device"!==i.bindingKind&&"entity"!==i.bindingKind||!i.bindingRef)return!1;a={id:i.id,binding:`${i.bindingKind}:${i.bindingRef}`,space:i.space||null,area:i.area||null,hidden:!!i.hidden},o.markers.push(a)}a.vacuum={...a.vacuum||{},map_routes:e},delete a.vacuum.calibration;const n=c(s,o,u._cfgContentFingerprint,u._cfgRev,d);u._serverCfg=o,u._regSignature="",u._maybeRebuildDevices(),u.requestUpdate(),u._saveConfigDebounced.pending()&&u._saveConfigDebounced.cancel();try{return await t._saveConfigNow(),!0}catch(t){return p(u,n,d),u._regSignature="",u._maybeRebuildDevices(),u.requestUpdate(),u._showToast(u._t("toast.cfg_save_failed",{err:u._errText(t)})),!1}})(a)},D=o.candidates.filter(t=>t.entityId!==b&&!v.some(e=>e.source===t.entityId)),C=async(t,e)=>{if(!e||e===t.space)return;await u._confirmDanger({key:"vacuum_route_space",kind:"warning",title:m("vac.route_space_title"),message:m("vac.route_space_body"),objectName:t.map_id||m("vac.route_map_default"),confirmLabel:m("vac.route_space_confirm"),cancelLabel:u._t("btn.cancel")})&&await M(s=>function(t,e,s,i){return t.map(t=>t.id===e?{...t,id:i,space:s,calibration:null}:t)}(s,t.id,e,xo(new Set(v.map(t=>t.id)))))},P=new Map(y.map((t,e)=>[t.id,e])),I=(t,e)=>t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)||t.id.localeCompare(e.id),T=v.filter(t=>$.has(t.space)).sort((t,e)=>(P.get(t.space)??0)-(P.get(e.space)??0)||I(t,e)),z=v.filter(t=>!$.has(t.space)).sort(I),R=[...T,...z],A=!!b&&void 0!==S&&!v.some(t=>t.source===b&&t.map_id===S);let F=Mo.get(t);const N=F?.source||"",H=F?.mapId||"",L=!!F&&v.some(t=>t.source===N&&t.map_id===H);F&&(F.markerId!==i.id||u._vacObservedMapId(i,F.source)!==F.mapId||L&&!F.saving)&&(Mo.delete(t),F=void 0),F?.space&&!$.has(F.space)&&(F=ko(F,"",$),Mo.set(t,F));const E=e=>h` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{s as t,e,n as s,f as i,i as o,l as a,o as n,r,A as l,b as h,a as c,c as d,d as p,D as u,w as _,N as m,g,h as f,j as b,k as v,m as y,p as $,q as w,t as k,u as x,v as S,x as M,y as D,z as C,B as P,C as I,E as T,F as z,G as R,H as A,I as F,J as N,K as H,L,M as E,O,P as B,Q as W,R as G,S as j,T as q,U,V as K,W as V,X as J,Y,Z as X,_ as Z,$ as Q,a0 as tt,a1 as et,a2 as st,a3 as it,a4 as ot,a5 as at,a6 as nt,a7 as rt,a8 as lt,a9 as ht,aa as ct,ab as dt,ac as pt,ad as ut,ae as _t,af as mt,ag as gt,ah as ft,ai as bt,aj as vt,ak as yt,al as $t,am as wt,an as kt,ao as xt,ap as St,aq as Mt,ar as Dt,as as Ct,at as Pt,au as It,av as Tt,aw as zt,ax as Rt,ay as At,az as Ft,aA as Nt,aB as Ht,aC as Lt,aD as Et,aE as Ot,aF as Bt,aG as Wt,aH as Gt,aI as jt,aJ as qt,aK as Ut,aL as Kt,aM as Vt,aN as Jt,aO as Yt,aP as Xt,aQ as Zt,aR as Qt,aS as te,aT as ee,aU as se,aV as ie,aW as oe,aX as ae,aY as ne,aZ as re,a_ as le,a$ as he,b0 as ce,b1 as de,b2 as pe,b3 as ue,b4 as _e,b5 as me,b6 as ge,b7 as fe,b8 as be,b9 as ve,ba as ye,bb as $e,bc as we,bd as ke,be as xe,bf as Se,bg as Me,bh as De,bi as Ce,bj as Pe,bk as Ie,bl as Te,bm as ze,bn as Re,bo as Ae,bp as Fe,bq as Ne,br as He,bs as Le,bt as Ee,bu as Oe,bv as Be,bw as We,bx as Ge,by as je,bz as qe,bA as Ue,bB as Ke,bC as Ve,bD as Je,bE as Ye,bF as Xe,bG as Ze,bH as Qe,bI as ts,bJ as es,bK as ss,bL as is,bM as os,bN as as,bO as ns,bP as rs,bQ as ls,bR as hs,bS as cs,bT as ds,bU as ps,bV as us,bW as _s,bX as ms,bY as gs,bZ as fs,b_ as bs,b$ as vs,c0 as ys,c1 as $s,c2 as ws,c3 as ks,c4 as xs,c5 as Ss,c6 as Ms,c7 as Ds,c8 as Cs,c9 as Ps,ca as Is,cb as Ts,cc as zs,cd as Rs,ce as As,cf as Fs,cg as Ns,ch as Hs,ci as Ls,cj as Es,ck as Os,cl as Bs,cm as Ws,cn as Gs,co as js,cp as qs,cq as Us,cr as Ks,cs as Vs,ct as Js,cu as Ys,cv as Xs,cw as Zs,cx as Qs,cy as ti,cz as ei,cA as si,cB as ii,cC as oi,cD as ai,cE as ni,cF as ri,cG as li,cH as hi,cI as ci,cJ as di,cK as pi,cL as ui,cM as _i,cN as mi,cO as gi,cP as fi,cQ as bi,cR as vi,cS as yi,cT as $i,cU as wi,cV as ki,cW as xi,cX as Si,cY as Mi,cZ as Di,c_ as Ci,c$ as Pi,d0 as Ii,d1 as Ti,d2 as zi,d3 as Ri,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Hi,d8 as Li,d9 as Ei,da as Oi,db as Bi,dc as Wi,dd as Gi,de as ji,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji,dk as Yi,dl as Xi,dm as Zi,dn as Qi,dp as to,dq as eo}from"./houseplan-card-Bhpi71t0.js";import{i as so}from"./guard-BgTQLSGB.js";import{F as io,f as oo,p as ao,c as no,s as ro,i as lo,e as ho,r as co,a as po,b as uo,d as _o,g as mo,t as go}from"./backdrop-pick-CV_as5Xh.js";import{t as fo,h as bo,m as vo,T as yo}from"./zigbee-topology-B-C5QCCD.js";import{GENERATED_FURNITURE_ART as $o,FURNITURE_ART_FINGERPRINT as wo}from"./furniture-plan-art.generated-Bs3YknKY.js";var ko={"gs.hint":"Fill colors apply to every space; each color has its own opacity. Which fill mode a space uses is set in that space's dialog.","gs.show_room_tooltip":"Show the room information window on hover","support.about_group":"About the card","support.guide_group":"Documentation","support.guide":"User guide","support.form_group":"Send a report or suggestion","support.contact":"Contact details (email/tg/WhatsApp), optional.","support.message":"Message","support.attach":"Attach anonymized information from your plan","support.attach_hint":"Includes only allowed plan geometry, settings and bounded runtime facts. Excludes names, Home Assistant IDs, live states, URLs, files, and your message/contact.","support.geometry_warning":"The package contains no names or Home Assistant IDs, but it does contain the exact geometry and dimensions of your home.","support.close_busy_title":"Stop the current operation?","support.close_busy_body":"House Plan is preparing or sending the report. Closing now stops waiting for the result.","support.building":"Preparing anonymized data…","support.preview_summary":"Package v{version} · {spaces} spaces · {size} KiB","support.prepared":"Snapshot prepared {n} min ago","support.show_data":"Show data","support.download":"Download JSON","support.refresh":"Refresh snapshot","support.privacy":"When you send, your message, optional contact and, if selected, exact geometry leave your Home Assistant through the House Plan project relay and are visible to maintainers. The project node keeps the report for up to 30 days. Network infrastructure sees your HA server address, but House Plan does not retain it raw; rate-limit and idempotency metadata is kept for up to 24 hours.","support.error_title":"The report was not sent","support.manual_recovery":"You can keep the message and attachment and continue manually:","support.copy_message":"Copy message","support.success":"Report sent: {id}. Save this number when contacting support.","support.copy_id":"Copy ID","support.sending":"Sending…","support.retry":"Retry","support.send":"Send","support.update_required":"Update the House Plan card and integration to compatible versions to send reports.","support.message_copied":"Message copied","support.id_copied":"Report ID copied","support.copy_failed":"Could not access the clipboard. Select and copy the text manually.","support.validation.message_required":"Enter a message.","support.validation.message_too_long":"The message must contain no more than 10,000 characters.","support.validation.contact_too_long":"Contact details must contain no more than 320 characters.","support.validation.preview_missing":"Wait for the attachment preview or turn the attachment off.","support.validation.preview_expired":"The attachment preview expired. Refresh the snapshot.","support.error.support_invalid_message":"Check the message and try again.","support.error.support_preview_expired":"The attachment preview expired or is no longer available. Refresh the snapshot.","support.error.support_package_too_large":"The anonymized package exceeds the 8 MiB limit.","support.error.support_rate_limited":"Too many reports or previews were requested. Try again later.","support.error.support_unavailable":"The private support service is temporarily unavailable. Your draft remains here.","support.error.support_rejected":"The report did not pass the support service validation.","support.error.unauthorized":"You do not have permission to send this report.","vac.routes_section":"Maps and floors","vac.routes_current_map":"Current map","vac.routes_no_map":"no telemetry","vac.routes_status":"Routing","vac.routes_state_ready":"map assigned and calibrated","vac.routes_state_needs_calibration":"map assigned, calibration needed","vac.routes_state_unmapped":"current map is not assigned to a floor","vac.routes_state_ambiguous":"two maps are indistinguishable — no floor is chosen","vac.routes_state_missing_space":"the map's space was deleted","vac.routes_state_none":"no map data","vac.routes_empty":"No map is assigned to a floor yet.","vac.route_map_default":"no map id","vac.route_active":"Active","vac.route_space":"Space","vac.route_space_none":"not selected","vac.route_status_ready":"ready","vac.route_status_needs_calibration":"needs calibration","vac.route_status_ambiguous":"ambiguous","vac.route_status_missing_space":"space deleted","vac.route_missing_space_group":"Deleted space","vac.route_add_current":"Add current map","vac.route_delete":"Remove map","vac.route_delete_title":"Remove the map from its floor?","vac.route_delete_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_delete_confirm":"Remove","vac.route_space_title":"Move the map to another space?","vac.route_space_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_space_confirm":"Move","vac.route_missing_space_hint":"One of the maps points at a deleted space: pick a new one or remove the map. Until then the robot is not drawn for that map.","vac.route_default_hint":"The source reports no stable map id. Several floors cannot be told apart without another source or the robot's own selected map.","vac.route_target_hint":"The dock stays in the “{space}” space regardless of the current map.","vac.route_add_source":"Add a map source","vac.route_add_source_hint":"For integrations that give each map its own camera. The “All cameras” section above widens this list.","vac.route_source_no_map":"no map reported"};const xo={en:ko,ru:{"gs.hint":"Цвета заливок действуют на все пространства; у каждого цвета своя прозрачность. Какой режим заливки использует пространство — задаётся в его диалоге.","gs.show_room_tooltip":"Показывать окно с информацией при наведении на комнату","support.about_group":"О карточке","support.guide_group":"Документация","support.guide":"Руководство пользователя","support.form_group":"Отправить репорт или предложение","support.contact":"Контакт для связи (email/tg/WhatsApp), необязательно.","support.message":"Сообщение","support.attach":"Прикрепить обезличенную информацию из вашего плана","support.attach_hint":"В пакет входят только разрешённые геометрия, настройки и ограниченные сведения о среде. Не входят имена, HA id, текущие состояния, URL, файлы, сообщение и контакт.","support.geometry_warning":"Пакет не содержит имён и HA id, но содержит точную геометрию и размеры дома.","support.close_busy_title":"Прервать текущую операцию?","support.close_busy_body":"House Plan подготавливает или отправляет репорт. При закрытии ожидание результата прекратится.","support.building":"Подготавливаем обезличенные данные…","support.preview_summary":"Пакет v{version} · пространств: {spaces} · {size} КиБ","support.prepared":"Снимок подготовлен {n} мин назад","support.show_data":"Показать данные","support.download":"Скачать JSON","support.refresh":"Обновить снимок","support.privacy":"При отправке сообщение, необязательный контакт и, если выбран пакет, точная геометрия покидают ваш Home Assistant через relay проекта House Plan и доступны мейнтейнерам. Узел проекта хранит репорт до 30 дней. Сетевая инфраструктура видит адрес сервера HA, но House Plan не сохраняет его в исходном виде; метаданные лимитов и идемпотентности хранятся до 24 часов.","support.error_title":"Репорт не отправлен","support.manual_recovery":"Сообщение и вложение можно сохранить и продолжить вручную:","support.copy_message":"Копировать сообщение","support.success":"Репорт отправлен: {id}. Сохраните номер для связи с поддержкой.","support.copy_id":"Копировать ID","support.sending":"Отправляем…","support.retry":"Повторить","support.send":"Отправить","support.update_required":"Обновите карточку и интеграцию House Plan до совместимых версий, чтобы отправлять репорты.","support.message_copied":"Сообщение скопировано","support.id_copied":"ID репорта скопирован","support.copy_failed":"Не удалось получить доступ к буферу обмена. Выделите и скопируйте текст вручную.","support.validation.message_required":"Введите сообщение.","support.validation.message_too_long":"Сообщение должно содержать не более 10 000 символов.","support.validation.contact_too_long":"Контакт должен содержать не более 320 символов.","support.validation.preview_missing":"Дождитесь предпросмотра вложения или отключите его.","support.validation.preview_expired":"Предпросмотр вложения истёк. Обновите снимок.","support.error.support_invalid_message":"Проверьте сообщение и повторите попытку.","support.error.support_preview_expired":"Предпросмотр вложения истёк или больше недоступен. Обновите снимок.","support.error.support_package_too_large":"Обезличенный пакет превышает лимит 8 МиБ.","support.error.support_rate_limited":"Запрошено слишком много репортов или предпросмотров. Повторите позже.","support.error.support_unavailable":"Закрытая служба поддержки временно недоступна. Черновик сохранён в этом окне.","support.error.support_rejected":"Репорт не прошёл проверку службы поддержки.","support.error.unauthorized":"У вас нет прав на отправку этого репорта.","vac.routes_section":"Карты и этажи","vac.routes_current_map":"Текущая карта","vac.routes_no_map":"источник молчит","vac.routes_status":"Маршрутизация","vac.routes_state_ready":"карта сопоставлена и откалибрована","vac.routes_state_needs_calibration":"карта сопоставлена, нужна калибровка","vac.routes_state_unmapped":"текущая карта не сопоставлена этажу","vac.routes_state_ambiguous":"две карты неразличимы — этаж не выбирается","vac.routes_state_missing_space":"пространство карты удалено","vac.routes_state_none":"нет данных о карте","vac.routes_empty":"Ни одна карта ещё не сопоставлена этажу.","vac.route_map_default":"без идентификатора","vac.route_active":"Текущая","vac.route_space":"Пространство","vac.route_space_none":"не выбрано","vac.route_status_ready":"готова","vac.route_status_needs_calibration":"нужна калибровка","vac.route_status_ambiguous":"неоднозначна","vac.route_status_missing_space":"пространство удалено","vac.route_missing_space_group":"Пространство удалено","vac.route_add_current":"Добавить текущую карту","vac.route_delete":"Удалить карту","vac.route_delete_title":"Удалить карту с этажа?","vac.route_delete_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_delete_confirm":"Удалить","vac.route_space_title":"Перенести карту в другое пространство?","vac.route_space_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_space_confirm":"Перенести","vac.route_missing_space_hint":"Одна из карт ссылается на удалённое пространство: выберите новое или удалите карту. Пока ссылка не исправлена, робот на этой карте не рисуется.","vac.route_default_hint":"Источник не сообщает стабильный идентификатор карты. Несколько этажей нельзя различить без другого источника или собственной карты робота.","vac.route_target_hint":"Док остаётся в пространстве «{space}» независимо от текущей карты.","vac.route_add_source":"Добавить источник карты","vac.route_add_source_hint":"Для интеграций, где у каждой карты своя камера. Список расширяется разделом «Все камеры» выше.","vac.route_source_no_map":"карта не читается"},de:{"gs.hint":"Füllfarben gelten für jeden Bereich; jede Farbe hat ihre eigene Deckkraft. Der Füllmodus wird in den Einstellungen des jeweiligen Bereichs festgelegt.","gs.show_room_tooltip":"Rauminformationen beim Darüberfahren anzeigen","support.about_group":"Über die Karte","support.guide_group":"Dokumentation","support.guide":"Benutzerhandbuch","support.form_group":"Bericht oder Vorschlag senden","support.contact":"Kontakt (E-Mail/tg/WhatsApp), optional.","support.message":"Nachricht","support.attach":"Anonymisierte Informationen aus dem Plan anhängen","support.attach_hint":"Enthält nur erlaubte Plangeometrie, Einstellungen und begrenzte Laufzeitdaten. Namen, Home-Assistant-IDs, Live-Zustände, URLs, Dateien, Nachricht und Kontakt werden ausgeschlossen.","support.geometry_warning":"Das Paket enthält keine Namen oder Home-Assistant-IDs, aber die exakte Geometrie und die Maße Ihres Hauses.","support.close_busy_title":"Aktuellen Vorgang abbrechen?","support.close_busy_body":"House Plan bereitet den Bericht vor oder sendet ihn. Beim Schließen wird nicht weiter auf das Ergebnis gewartet.","support.building":"Anonymisierte Daten werden vorbereitet…","support.preview_summary":"Paket v{version} · {spaces} Bereiche · {size} KiB","support.prepared":"Schnappschuss vor {n} Min. erstellt","support.show_data":"Daten anzeigen","support.download":"JSON herunterladen","support.refresh":"Schnappschuss aktualisieren","support.privacy":"Beim Senden verlassen Ihre Nachricht, der optionale Kontakt und, falls ausgewählt, die exakte Geometrie Ihren Home Assistant über das House-Plan-Projektrelay und sind für die Maintainer sichtbar. Der Projektserver speichert den Bericht bis zu 30 Tage. Die Netzwerkinfrastruktur sieht die Adresse Ihres HA-Servers, House Plan speichert sie jedoch nicht im Rohformat; Limit- und Idempotenzdaten bleiben bis zu 24 Stunden erhalten.","support.error_title":"Der Bericht wurde nicht gesendet","support.manual_recovery":"Nachricht und Anhang können gespeichert und manuell weitergegeben werden:","support.copy_message":"Nachricht kopieren","support.success":"Bericht gesendet: {id}. Bewahren Sie diese Nummer für den Support auf.","support.copy_id":"ID kopieren","support.sending":"Wird gesendet…","support.retry":"Erneut versuchen","support.send":"Senden","support.update_required":"Aktualisieren Sie House-Plan-Karte und Integration auf kompatible Versionen, um Berichte zu senden.","support.message_copied":"Nachricht kopiert","support.id_copied":"Berichts-ID kopiert","support.copy_failed":"Kein Zugriff auf die Zwischenablage. Markieren und kopieren Sie den Text manuell.","support.validation.message_required":"Geben Sie eine Nachricht ein.","support.validation.message_too_long":"Die Nachricht darf höchstens 10.000 Zeichen enthalten.","support.validation.contact_too_long":"Der Kontakt darf höchstens 320 Zeichen enthalten.","support.validation.preview_missing":"Warten Sie auf die Vorschau oder deaktivieren Sie den Anhang.","support.validation.preview_expired":"Die Anhangsvorschau ist abgelaufen. Aktualisieren Sie den Schnappschuss.","support.error.support_invalid_message":"Prüfen Sie die Nachricht und versuchen Sie es erneut.","support.error.support_preview_expired":"Die Anhangsvorschau ist abgelaufen oder nicht mehr verfügbar. Aktualisieren Sie den Schnappschuss.","support.error.support_package_too_large":"Das anonymisierte Paket überschreitet das Limit von 8 MiB.","support.error.support_rate_limited":"Zu viele Berichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","support.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar. Der Entwurf bleibt in diesem Fenster erhalten.","support.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","support.error.unauthorized":"Sie dürfen diesen Bericht nicht senden.","vac.routes_section":"Karten und Etagen","vac.routes_current_map":"Aktuelle Karte","vac.routes_no_map":"keine Telemetrie","vac.routes_status":"Zuordnung","vac.routes_state_ready":"Karte zugeordnet und kalibriert","vac.routes_state_needs_calibration":"Karte zugeordnet, Kalibrierung nötig","vac.routes_state_unmapped":"aktuelle Karte keiner Etage zugeordnet","vac.routes_state_ambiguous":"zwei Karten nicht unterscheidbar — keine Etage gewählt","vac.routes_state_missing_space":"der Raum der Karte wurde gelöscht","vac.routes_state_none":"keine Kartendaten","vac.routes_empty":"Noch keine Karte einer Etage zugeordnet.","vac.route_map_default":"ohne Karten-ID","vac.route_active":"Aktiv","vac.route_space":"Raum","vac.route_space_none":"nicht gewählt","vac.route_status_ready":"bereit","vac.route_status_needs_calibration":"Kalibrierung nötig","vac.route_status_ambiguous":"mehrdeutig","vac.route_status_missing_space":"Raum gelöscht","vac.route_missing_space_group":"Gelöschter Bereich","vac.route_add_current":"Aktuelle Karte hinzufügen","vac.route_delete":"Karte entfernen","vac.route_delete_title":"Karte von der Etage entfernen?","vac.route_delete_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_delete_confirm":"Entfernen","vac.route_space_title":"Karte in einen anderen Raum verschieben?","vac.route_space_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_space_confirm":"Verschieben","vac.route_missing_space_hint":"Eine Karte verweist auf einen gelöschten Raum: neuen wählen oder Karte entfernen. Bis dahin wird der Roboter für diese Karte nicht gezeichnet.","vac.route_default_hint":"Die Quelle meldet keine stabile Karten-ID. Mehrere Etagen lassen sich ohne andere Quelle oder die vom Roboter gewählte Karte nicht unterscheiden.","vac.route_target_hint":"Die Station bleibt unabhängig von der aktuellen Karte im Raum „{space}“.","vac.route_add_source":"Kartenquelle hinzufügen","vac.route_add_source_hint":"Für Integrationen, die jeder Karte eine eigene Kamera geben. Der Abschnitt „Alle Kameras“ oben erweitert diese Liste.","vac.route_source_no_map":"keine Karte gemeldet"},fr:{"gs.hint":"Les couleurs de remplissage s’appliquent à tous les espaces ; chaque couleur possède sa propre opacité. Le mode de remplissage utilisé par un espace se règle dans la boîte de dialogue de cet espace.","gs.show_room_tooltip":"Afficher les informations de la pièce au survol","support.about_group":"À propos de la carte","support.guide_group":"Documentation d’aide","support.guide":"Guide utilisateur","support.form_group":"Envoyer un rapport ou une suggestion","support.contact":"Contact (e-mail/tg/WhatsApp), facultatif.","support.message":"Votre message","support.attach":"Joindre des informations anonymisées de votre plan","support.attach_hint":"Inclut uniquement la géométrie, les réglages autorisés et des données d’exécution limitées. Exclut les noms, identifiants Home Assistant, états en direct, URL, fichiers, message et contact.","support.geometry_warning":"Le paquet ne contient ni noms ni identifiants Home Assistant, mais il contient la géométrie et les dimensions exactes de votre logement.","support.close_busy_title":"Interrompre l’opération en cours ?","support.close_busy_body":"House Plan prépare ou envoie le rapport. Fermer maintenant arrête l’attente du résultat.","support.building":"Préparation des données anonymisées…","support.preview_summary":"Paquet v{version} · {spaces} espaces · {size} Kio","support.prepared":"Instantané préparé il y a {n} min","support.show_data":"Afficher les données","support.download":"Télécharger le JSON","support.refresh":"Actualiser l’instantané","support.privacy":"Lors de l’envoi, votre message, le contact facultatif et, si elle est sélectionnée, la géométrie exacte quittent votre Home Assistant via le relais du projet House Plan et sont visibles par les mainteneurs. Le serveur du projet conserve le rapport jusqu’à 30 jours. L’infrastructure réseau voit l’adresse de votre serveur HA, mais House Plan ne la conserve pas en clair ; les métadonnées de limitation et d’idempotence sont gardées jusqu’à 24 heures.","support.error_title":"Le rapport n’a pas été envoyé","support.manual_recovery":"Vous pouvez conserver le message et la pièce jointe puis continuer manuellement :","support.copy_message":"Copier le message","support.success":"Rapport envoyé : {id}. Conservez ce numéro pour contacter l’assistance.","support.copy_id":"Copier l’ID","support.sending":"Envoi…","support.retry":"Réessayer","support.send":"Envoyer","support.update_required":"Mettez à jour la carte et l’intégration House Plan vers des versions compatibles pour envoyer des rapports.","support.message_copied":"Message copié","support.id_copied":"ID du rapport copié","support.copy_failed":"Impossible d’accéder au presse-papiers. Sélectionnez et copiez le texte manuellement.","support.validation.message_required":"Saisissez un message.","support.validation.message_too_long":"Le message ne doit pas dépasser 10 000 caractères.","support.validation.contact_too_long":"Le contact ne doit pas dépasser 320 caractères.","support.validation.preview_missing":"Attendez l’aperçu de la pièce jointe ou désactivez-la.","support.validation.preview_expired":"L’aperçu de la pièce jointe a expiré. Actualisez l’instantané.","support.error.support_invalid_message":"Vérifiez le message et réessayez.","support.error.support_preview_expired":"L’aperçu de la pièce jointe a expiré ou n’est plus disponible. Actualisez l’instantané.","support.error.support_package_too_large":"Le paquet anonymisé dépasse la limite de 8 Mio.","support.error.support_rate_limited":"Trop de rapports ou d’aperçus ont été demandés. Réessayez plus tard.","support.error.support_unavailable":"Le service d’assistance privé est temporairement indisponible. Le brouillon reste dans cette fenêtre.","support.error.support_rejected":"Le rapport n’a pas passé la validation du service d’assistance.","support.error.unauthorized":"Vous n’êtes pas autorisé à envoyer ce rapport.","vac.routes_section":"Cartes et étages","vac.routes_current_map":"Carte actuelle","vac.routes_no_map":"aucune télémétrie","vac.routes_status":"Routage","vac.routes_state_ready":"carte assignée et calibrée","vac.routes_state_needs_calibration":"carte assignée, calibrage requis","vac.routes_state_unmapped":"carte actuelle non assignée à un étage","vac.routes_state_ambiguous":"deux cartes indiscernables — aucun étage choisi","vac.routes_state_missing_space":"l'espace de la carte a été supprimé","vac.routes_state_none":"aucune donnée de carte","vac.routes_empty":"Aucune carte n'est encore assignée à un étage.","vac.route_map_default":"sans identifiant","vac.route_active":"Active","vac.route_space":"Espace","vac.route_space_none":"non sélectionné","vac.route_status_ready":"prête","vac.route_status_needs_calibration":"calibrage requis","vac.route_status_ambiguous":"ambiguë","vac.route_status_missing_space":"espace supprimé","vac.route_missing_space_group":"Espace supprimé","vac.route_add_current":"Ajouter la carte actuelle","vac.route_delete":"Supprimer la carte","vac.route_delete_title":"Retirer la carte de son étage ?","vac.route_delete_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_delete_confirm":"Supprimer","vac.route_space_title":"Déplacer la carte vers un autre espace ?","vac.route_space_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_space_confirm":"Déplacer","vac.route_missing_space_hint":"Une carte pointe vers un espace supprimé : choisissez-en un autre ou supprimez la carte. D'ici là, le robot n'est pas dessiné pour cette carte.","vac.route_default_hint":"La source ne fournit pas d'identifiant de carte stable. Plusieurs étages ne peuvent pas être distingués sans une autre source ou la carte sélectionnée du robot.","vac.route_target_hint":"La station reste dans l'espace « {space} » quelle que soit la carte actuelle.","vac.route_add_source":"Ajouter une source de carte","vac.route_add_source_hint":"Pour les intégrations qui donnent à chaque carte sa propre caméra. La section « Toutes les caméras » ci-dessus élargit cette liste.","vac.route_source_no_map":"aucune carte signalée"}};function So(e,s,i){return t(xo[e]?.[s]??ko[s]??s,i)}function Mo(t,e,s,i,o){return{markerId:t,source:i,mapId:o,space:e.length?"":s}}function Do(t,e,s){return{...t,space:s.has(e)?e:""}}function Co(t,e=Math.random){const s=new Set(t);for(let t=0;t<64;t+=1){const t="vr_"+Math.floor(16777215*e()).toString(36).padStart(5,"0");if(!s.has(t))return t}return"vr_"+Date.now().toString(36)}function Po(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const Io=new WeakMap,To=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function zo(t,i,o){const u=t.host,_=a(u.hass,u._config?.language),m=(t,e)=>So(_,t,e),g=i.marker?.vacuum||{},f=Array.isArray(g.map_routes),b=u._vacSource(i)||"",v=e(i.id,g,i.space,b),y=(u._serverCfg?.spaces||[]).filter(t=>"string"==typeof t?.id&&!!t.id).map(t=>({id:t.id,name:String(t.name||t.id)})),$=new Set(y.map(t=>t.id)),w=n(v,[b],t=>u._vacObservedMapId(i,t)),k=r({routes:v,observed:w,spaceIds:$}),x="ready"===k.kind||"needs_calibration"===k.kind||"missing_space"===k.kind?k.route.id:"",S=b?w[b]:void 0,M=async e=>{let o=f?g.map_routes??null:null;if(!o&&(o=function(t,e,i,o){if(!i)return null;const a=t?.calibration;if(!a||"object"!=typeof a)return null;const n=new Set,r=[];for(const t of Object.keys(a)){const l=s(a[t]);if(!l)continue;const h=o(n);n.add(h),r.push({id:h,source:i,map_id:t,space:e,calibration:l})}return r.length?r:null}(g,i.space,b,t=>Co(t))??[],!b&&Object.keys(g.calibration||{}).length))return!1;const a=e(o);return!!a&&(async e=>{const s=u._serverCfg;if(!s)return!1;const o=JSON.parse(JSON.stringify(s));o.markers=o.markers||[];let a=o.markers.find(t=>t.id===i.id);if(!a){if("device"!==i.bindingKind&&"entity"!==i.bindingKind||!i.bindingRef)return!1;a={id:i.id,binding:`${i.bindingKind}:${i.bindingRef}`,space:i.space||null,area:i.area||null,hidden:!!i.hidden},o.markers.push(a)}a.vacuum={...a.vacuum||{},map_routes:e},delete a.vacuum.calibration;const n=c(s,o,u._cfgContentFingerprint,u._cfgRev,d);u._serverCfg=o,u._regSignature="",u._maybeRebuildDevices(),u.requestUpdate(),u._saveConfigDebounced.pending()&&u._saveConfigDebounced.cancel();try{return await t._saveConfigNow(),!0}catch(t){return p(u,n,d),u._regSignature="",u._maybeRebuildDevices(),u.requestUpdate(),u._showToast(u._t("toast.cfg_save_failed",{err:u._errText(t)})),!1}})(a)},D=o.candidates.filter(t=>t.entityId!==b&&!v.some(e=>e.source===t.entityId)),C=async(t,e)=>{if(!e||e===t.space)return;await u._confirmDanger({key:"vacuum_route_space",kind:"warning",title:m("vac.route_space_title"),message:m("vac.route_space_body"),objectName:t.map_id||m("vac.route_map_default"),confirmLabel:m("vac.route_space_confirm"),cancelLabel:u._t("btn.cancel")})&&await M(s=>function(t,e,s,i){return t.map(t=>t.id===e?{...t,id:i,space:s,calibration:null}:t)}(s,t.id,e,Co(new Set(v.map(t=>t.id)))))},P=new Map(y.map((t,e)=>[t.id,e])),I=(t,e)=>t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)||t.id.localeCompare(e.id),T=v.filter(t=>$.has(t.space)).sort((t,e)=>(P.get(t.space)??0)-(P.get(e.space)??0)||I(t,e)),z=v.filter(t=>!$.has(t.space)).sort(I),R=[...T,...z],A=!!b&&void 0!==S&&!v.some(t=>t.source===b&&t.map_id===S);let F=Io.get(t);const N=F?.source||"",H=F?.mapId||"",L=!!F&&v.some(t=>t.source===N&&t.map_id===H);F&&(F.markerId!==i.id||u._vacObservedMapId(i,F.source)!==F.mapId||L&&!F.saving)&&(Io.delete(t),F=void 0),F?.space&&!$.has(F.space)&&(F=Do(F,"",$),Io.set(t,F));const E=e=>h`
  • ${e.map_id||m("vac.route_map_default")} @@ -35,7 +35,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    - `}}const tc=(t,e)=>t[0]*e[1]-t[1]*e[0],ec=(t,e)=>t[0]*e[0]+t[1]*e[1],sc=(t,e)=>[t[0]-e[0],t[1]-e[1]],ic=(t,e,s)=>[t[0]+e[0]*s,t[1]+e[1]*s];function oc(t,e,s){return Math.abs(tc(t,e))<=s}function ac(t,e,s){return Math.abs(tc(sc(t,e),s))}function nc(t,e,s,i,o){const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(!(r>o&&s>0))return[];const l=[a/r,n/r];return function(t,e,s){const i=e.map(([e,s])=>[Math.max(0,Math.min(e,s)),Math.min(t,Math.max(e,s))]).filter(([t,e])=>e>t+s).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),o=[];for(const t of i){const e=o[o.length-1];!e||t[0]>e[1]+s?o.push([...t]):e[1]=Math.max(e[1],t[1])}const a=[];let n=0;for(const[t,e]of o)t>n+s&&a.push([n,t]),n=Math.max(n,e);return t>n+s&&a.push([n,t]),a}(r,i.flatMap(e=>{const i=e.b[0]-e.a[0],a=e.b[1]-e.a[1],n=Math.hypot(i,a);if(!(n>o&&oc(l,[i/n,a/n],1e-6)))return[];if(ac(e.a,t,l)>1.1*Math.max(s,o)||ac(e.b,t,l)>1.1*Math.max(s,o))return[];return[[ec(sc(e.a,t),l),ec(sc(e.b,t),l)]]}),o).flatMap(([e,i])=>{const o=Vt({a:ic(t,l,e),b:ic(t,l,i),halfDepth:s});return o?[o]:[]})}function rc(t){const e=t.coordScale??1,s=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),i=[];for(const s of t.rooms||[]){if(!s?.id)continue;const o=et(t.rooms,s.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!o||o.poly.length<3)continue;const a=Ut(o.poly,o.offsets);!a||a.length<3||i.push({roomId:s.id,profile:o,inner:a})}i.sort((t,e)=>t.roomId.localeCompare(e.roomId));const o=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,s=[Math.cos(e),Math.sin(e)],i=Math.max(0,t.length)/2;return{a:ic([t.x,t.y],s,-i),b:ic([t.x,t.y],s,i)}}),a=[];for(const i of Kt(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of nc(i.a,i.b,i.depthUnits/2,o,s))a.push({body:t});const n=new Map;for(const e of t.partitionCuts||[]){const t=n.get(e.hostId)||[];t.push(e),n.set(e.hostId,t)}for(const e of t.partitions||[]){const i=$(e.cm,t.cellCm,t.gridPitch)/2;for(const t of nc(e.a,e.b,i,n.get(e.id)||[],s))a.push({body:t,partitionId:e.id})}return{rooms:i,boundaries:a,epsilon:s}}function lc(t,e,s,i){const o=t.profile.offsets[e];if(!(o>0))return null;const a=function(t,e){const s=t[e],i=t[(e+1)%t.length],o=i[0]-s[0],a=i[1]-s[1],n=Math.hypot(o,a)||1;return function(t){let e=0;for(let s=0;s=0?[-a/n,o/n]:[a/n,-o/n]}(t.profile.poly,e),n=ic(s.center,a,o),r=[];for(let e=0;ei&&oc(s.axis,[l[0]/h,l[1]/h],1e-6)))continue;if(ac(o,n,s.axis)>i||ac(a,n,s.axis)>i)continue;const c=ec(sc(o,n),s.axis),d=ec(sc(a,n),s.axis);r.push([Math.min(c,d),Math.max(c,d)])}const l=function(t,e){t.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);const s=[];for(const i of t){const t=s[s.length-1];!t||i[0]>t[1]+e?s.push([...i]):t[1]=Math.max(t[1],i[1])}return s}(r,i).find(([t,e])=>t<=i&&e>=-i);if(!l)return null;const[h,c]=l,d=ic(n,s.axis,-s.half),p=ic(n,s.axis,s.half),u=Math.max(0,-s.half-h),_=Math.max(0,c-s.half),m=u>0?ic(n,s.axis,h):d,g=_>0?ic(n,s.axis,c):p,f=ec(a,s.normal)>=0?1:-1,b=(e,i,o)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:s.axis,labelNormal:a,distance:o,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:b(d,m,u),right:b(p,g,_)}}function hc(t){const e=ic(t.center,t.axis,-t.half),s=ic(t.center,t.axis,t.half),i=ic(t.center,t.axis,Math.min(-t.half,t.targetLo)),o=ic(t.center,t.axis,Math.max(t.half,t.targetHi)),a=(e,s)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(s[0]-e[0],s[1]-e[1]),source:"host-end"});return[a(e,i),a(s,o)]}function cc(t,e,s,i){const o=sc(s,e),a=ec(o,o);if(!(a>i*i))return Math.hypot(...sc(t,e))<=i;const n=ec(sc(t,e),o)/a;if(n<-i||n>1+i)return!1;const r=ic(e,o,Math.max(0,Math.min(1,n)));return Math.hypot(...sc(t,r))<=i}function dc(t,e,s){let i=!1;for(let o=0,a=e.length-1;ot[1]!=h>t[1]&&t[0]<(l-n)*(t[1]-r)/(h-r)+n&&(i=!i)}return i}function pc(t,e,s,i,o,a){const n=sc(i,s),r=tc(e,n);if(Math.abs(r)<=a)return null;const l=sc(s,t),h=tc(l,n)/r,c=tc(l,e)/r;return h<-a||h>o+a||c<-a||c>1+a?null:Math.max(0,Math.min(o,h))}function uc(t,e,s){const i=hc(s),o="partition"===t.host?.kind?t.host.id:void 0;return[{base:i[0],direction:[-s.axis[0],-s.axis[1]]},{base:i[1],direction:s.axis}].map(({base:t,direction:s})=>{const i=t.distance,a=function(t,e,s,i,o,a){let n=null;for(const r of i)if(!o||r.partitionId!==o){if(dc(t,r.body,a))return 0;for(let i=0;iec(sc(t,o),s));return{center:o,axis:s,normal:i,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...a),targetHi:Math.max(...a)}}(t),i=e.rooms.flatMap(t=>{const i=function(t,e,s){const{profile:i}=t;let o=null;for(let t=0;t0))continue;const a=i.poly[t],n=i.poly[(t+1)%i.poly.length],r=sc(n,a),l=Math.hypot(r[0],r[1]);if(!(l>s&&oc(e.axis,[r[0]/l,r[1]/l],1e-6)))continue;if(ac(a,e.center,e.axis)>s||ac(n,e.center,e.axis)>s)continue;const h=ec(sc(a,e.center),e.axis),c=ec(sc(n,e.center),e.axis),d=Math.min(h,c),p=Math.max(h,c);if(d>-e.half+s||p0?d:p<0?-p:0);(!o||u2)return hc(s);if(i.length){const t=i.map(({room:t,edge:i})=>lc(t,i,s,e.epsilon));if(t.some(t=>!t))return hc(s);const o=t;return[...o.map(t=>t.left),...o.map(t=>t.right)]}return uc(t,e,s)}const mc="1.73.0-beta.1",gc={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon"},fc={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon"},bc=2e3,vc=1e3,yc=(t,e,s,i)=>{for(t.delete(e),t.set(e,s);t.size>i;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},$c=1e3,wc=2e3,kc=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}},xc="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";class Sc{constructor(t){this.host=t,this._junctionBaselineCache=new WeakMap,this._resizePreviewNodes=null,this._resizeBaselineLimits=[],this._resizeBaseFrameStable=!0,this._supportPreviewGeneration=0,this._decorAssetGuardReplace=null,this._undoGeometry=()=>{if(this.host._physicalDrag||this.host._physicalRotate)return void this._cancelPhysicalGesture();if(this.host._decorDraft)return this.host._decorDraft=null,void this.host.requestUpdate();if(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)return void this._cancelDecorGesture();if(this.host._resize.dragging)return void this._rszCancelDrag();const t=this.host._geometryHistory.undo();t&&(this._applyGeometryState(t.before,!0)?this.host._showToast(this.host._t("history.undone",{name:t.name})):this.host._geometryHistory.clear())},this._redoGeometry=()=>{if(this.host._physicalDrag||this.host._physicalRotate)return void this._cancelPhysicalGesture();if(this.host._decorDraft)return this.host._decorDraft=null,void this.host.requestUpdate();if(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)return void this._cancelDecorGesture();if(this.host._resize.dragging)return void this._rszCancelDrag();const t=this.host._geometryHistory.redo();t&&(this._applyGeometryState(t.after,!0)?this.host._showToast(this.host._t("history.redone",{name:t.name})):this.host._geometryHistory.clear())},this._savePhysicalDialog=()=>{const t=this.host._physicalDialog,e=this.host._curSpaceCfg,s=this.host._spaceModel();if(!t||!e||!s)return;const i=ao(t.cm);if(null==i)return void this._showPhysicalRange("column"===t.kind?Jt:100,"column"===t.kind?1:0);const o=this.host._imperial?2.54*i:i,a="column"===t.kind?Jt:100,n="column"===t.kind?1:0;if(!Number.isFinite(o)||oa)return void this._showPhysicalRange(a,n);if("column"===t.kind){const e=s.wall_columns.find(e=>e.id===t.id);if(!e)return;const i=ao(t.angle||"0");if("circle"!==t.shape&&(null==i||i<0||i>=90))return void this.host._showToast(this.host._t("toast.physical_angle"));const a="circle"===t.shape?{id:t.id,shape:"circle",center:e.center,cm:o}:{id:t.id,shape:"square",center:e.center,cm:o,angle:i};if(s.wall_columns.some(e=>e.id!==t.id&&Yt(e,a,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"))}const r=this._geometrySnapshot();if("partition"===t.kind){const s=(e.partitions||[]).find(e=>e.id===t.id);if(s&&0===o&&Xt(e.openings,{kind:"partition",id:t.id}))return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"));s&&(s.cm=o)}else if("column"===t.kind){const s=(e.wall_columns||[]).find(e=>e.id===t.id);s&&(s.cm=Zt(o),s.shape="circle"===t.shape?"circle":"square","square"===s.shape?s.angle=ao(t.angle||"0"):delete s.angle)}else{const s=(e.room_drafts||[]).find(e=>e.id===t.id);s?.segments?.[t.segment||0]&&(s.segments[t.segment||0].cm=o)}const l=this._commitPhysicalGeometry(this.host._t("history.physical_edit"),r);this.host._physicalDialog=null,l||this.host.requestUpdate()},this._deletePhysicalSelection=async()=>{const t=this.host._physicalSel,e=this.host._curSpaceCfg;if(!t||!e)return;if("draft"===t.kind)return void await this._deleteDraftWhole();const s=this._geometrySnapshot();if("partition"===t.kind){const s=(e.openings||[]).filter(e=>"partition"===e.host?.kind&&e.host.id===t.id).sort((t,e)=>(t.host?.t||0)-(e.host?.t||0));if(s.length)return void(this.host._partitionDeleteDialog={id:t.id,openings:s.map(t=>JSON.parse(JSON.stringify(t)))})}const i="partition"===t.kind?"partitions":"column"===t.kind?"wall_columns":"room_drafts";e[i]=(e[i]||[]).filter(e=>e.id!==t.id),e[i].length||delete e[i],this.host._activeDraftId===t.id&&this._cancelPath(),this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),s)},this._confirmPartitionDelete=()=>{const t=this.host._partitionDeleteDialog,e=this.host._curSpaceCfg;if(!t||!e)return;const s=this._geometrySnapshot();e.partitions=(e.partitions||[]).filter(e=>e.id!==t.id),e.partitions.length||delete e.partitions,e.openings=(e.openings||[]).filter(e=>"partition"!==e.host?.kind||e.host.id!==t.id),e.openings.length||delete e.openings,this.host._partitionDeleteDialog=null,this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),s)},this._deleteDraftWhole=async()=>{const t="draft"===this.host._physicalDialog?.kind?this.host._physicalDialog.id:"draft"===this.host._physicalSel?.kind?this.host._physicalSel.id:null,e=this.host._space;if(!t||!this.host._curSpaceCfg)return;if(!await this.host._confirmDanger({key:"delete-draft",kind:"destructive",title:this.host._t("confirm.delete_draft_title"),message:this.host._t("confirm.delete_draft_body"),confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")})||this.host._space!==e)return;const s=this.host._curSpaceCfg;if(!s||!(s.room_drafts||[]).some(e=>e.id===t))return;const i=this._geometrySnapshot();s.room_drafts=(s.room_drafts||[]).filter(e=>e.id!==t),s.room_drafts.length||delete s.room_drafts,this.host._activeDraftId===t&&this._cancelPath(),this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),i)},this._deleteDraftSegment=async()=>{const t=this.host._physicalDialog,e=this.host._space;if(!t||"draft"!==t.kind||!this.host._curSpaceCfg)return;const s=t.id,i=t.segment||0,o=await this.host._confirmDanger({key:"delete-draft-segment",kind:"destructive",title:this.host._t("confirm.delete_draft_segment_title"),message:this.host._t("confirm.delete_draft_segment_body"),confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),a=this.host._physicalDialog;if(!o||this.host._space!==e||"draft"!==a?.kind||a.id!==s||(a.segment||0)!==i)return;const n=this.host._curSpaceCfg;if(!n)return;const r=(n.room_drafts||[]).findIndex(t=>t.id===s);if(r<0)return;const l=n.room_drafts[r];if(!Array.isArray(l.segments)||!Number.isInteger(i)||i<0||i>=l.segments.length)return;const h=i,c=[],d=l.points.slice(0,h+1),p=l.points.slice(h+1);if(d.length>=2&&c.push({id:l.id,points:d,segments:l.segments.slice(0,h)}),p.length>=2&&c.push({id:c.length?`${l.id}-${Date.now().toString(36)}`:l.id,points:p,segments:l.segments.slice(h+1)}),2===c.length&&n.room_drafts.length>=200)return void this.host._showToast(this.host._t("toast.physical_limit"));const u=this._geometrySnapshot();n.room_drafts.splice(r,1,...c),n.room_drafts.length||delete n.room_drafts,this.host._activeDraftId===l.id&&this._cancelPath(),this.host._physicalDialog=null,this.host._physicalSel=c.length?{kind:"draft",id:c[0].id}:null,this._commitPhysicalGeometry(this.host._t("history.draft_segment_delete"),u)},this._furnShiftListener=t=>{if("Shift"!==t.key)return;const e=this.host._furnPreviewInput;if(!e)return;const s="keydown"===t.type;e.free!==s&&(this.host._furnPreviewInput={...e,free:s},this.host.requestUpdate())},this._furnShiftAttached=!1,this._confirmRoomDelete=t=>{const e=this.host._roomDeleteDialog,s=this.host._curSpaceCfg,i=this.host._spaceModel();if(!e||!s||!i)return;const o=i.rooms.find(t=>t.id===e.roomId);if(!o)return void(this.host._roomDeleteDialog=null);const a=this.host._openCuts(),n=Ph(ct(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,$c).filter(t=>t.roomId===o.id),i.partitions,this.host._openingsR.map(t=>({...t,x:t.rx,y:t.ry})),.02*this.host._gridPitch),r=new Set(n.materialize.filter(t=>!t.reusePartitionId).map(t=>t.interval.key)).size;if(t&&(s.partitions||[]).length+r>wc)return void this.host._showToast(this.host._t("toast.physical_limit"));const l=this._geometrySnapshot(),h=Qt(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,$c);if(t){s.partitions||=[];const t=new Map,e=new Map,i=t=>{const e=(s.wall_segments||[]).find(e=>{const s=[Number(e.a?.[0])*$c,Number(e.a?.[1])*$c],i=[Number(e.b?.[0])*$c,Number(e.b?.[1])*$c];return this._samePt(t.a,s)&&this._samePt(t.b,i)||this._samePt(t.a,i)&&this._samePt(t.b,s)});return"string"==typeof e?.id&&e.id?e.id:null},o=Date.now().toString(36);for(const a of n.materialize){let n=a.reusePartitionId?s.partitions.find(t=>t.id===a.reusePartitionId):e.get(a.interval.key);n||(n={id:i(a.interval)||`partition-room-${o}-${e.size}`,a:[a.interval.a[0]/$c,a.interval.a[1]/$c],b:[a.interval.b[0]/$c,a.interval.b[1]/$c],cm:a.interval.cm},s.partitions.push(n),e.set(a.interval.key,n)),t.set(a.interval.key,n)}for(const e of s.openings||[]){const s=n.openingIntervals.get(e.id),i=s?t.get(s):null,o=this.host._openingsR.find(t=>t.id===e.id);if(!i||!o)continue;const a={a:[i.a[0]*$c,i.a[1]*$c],b:[i.b[0]*$c,i.b[1]*$c]};e.host={kind:"partition",id:i.id,t:Ih([o.rx,o.ry],a)}}}else if(n.removeOpeningIds.length){const t=new Set(n.removeOpeningIds);s.openings=(s.openings||[]).filter(e=>!t.has(e.id)),s.openings.length||delete s.openings}s.rooms=s.rooms.filter(t=>t.id!==o.id),this.host._cfgEpoch++;const c=this.host._normalizeWalls(h,this.host._openCuts());c.length?s.walls=c:delete s.walls,this.host._roomDeleteDialog=null,this._commitPhysicalGeometry(this.host._t(t?"history.delete_room_keep_walls":"history.delete_room_with_walls"),l),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate()},this._rebindPartitionOpening=()=>{const t=this.host._openingDialog;if(!t?.id)return;const e=t.id;this._activateMarkupTool("opening"),"opening"===this.host._tool&&(this.host._openingRebindId=e,this.host._openingPreset={type:t.type,lengthCm:t.lengthCm,flipH:t.flipH,flipV:t.flipV,revision:++this.host._openingPresetRevision},this.host._openingDialog=null,this.host._openingHoverCandidate=null)},this._deviceInboxTabKey=t=>{if("ArrowLeft"!==t.key&&"ArrowRight"!==t.key)return;const e=this.host._deviceInbox;if(!e)return;const s=["on_plan","available","hidden","readd"],i="ArrowRight"===t.key?1:-1,o=(s.indexOf(e.tab)+i+s.length)%s.length;this.host._deviceInbox={...e,tab:s[o],limit:100,onlyNew:!1},t.preventDefault()},this._keepClosedAsPartitions=()=>{if(this.host._wallFaceBatch)return void this._decideWallFace(!1);if(!this.host._contourClosed||this.host._pendingSplit||!this.host._curSpaceCfg)return;const t=this.host._curSpaceCfg,e=this.host._path.slice(0,-1);if((t.partitions||[]).length+e.length>wc)return void this.host._showToast(this.host._t("toast.physical_limit"));const s=this._geometrySnapshot(),i=sh(e.length,[...this.host._draftSegmentCms,this.host._closingWallCm??void 0],this.host._drawWallCm,dt);t.partitions||=[];const o=Date.now().toString(36),a=this.host._activeDraftId?(t.room_drafts||[]).find(t=>t.id===this.host._activeDraftId):null,n=this._draftSegmentsForPath(this.host._path,a,i);for(let s=0;st.id!==this.host._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._commitPhysicalGeometry(this.host._t("history.contour_to_partitions"),s),this.host._roomDialog=!1,this.host._path=[],delete this.host._resumeDraftBySpace[this.host._space],this.host._activeDraftId=null,this.host._draftSegmentCms=[],this.host._closingWallCm=null},this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,saved:t?.plans||[],savedBusy:!1})}catch(t){const e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}},this._openSettingsDialog=()=>{if(!this.host._norm)return;const t=this.host._glowRadiusCm,e=this.host._imperial?Math.round(t/30.48*10)/10:Math.round(t)/100;this.host._settingsDialog={colors:JSON.parse(JSON.stringify(this.host._fillColors)),glowRadius:e,bgColor:ae(this.host._settings,{bgColor:null})||null,northDeg:oe(this.host._settings,{}),bgMode:ie(this.host._settings,{}),sunRays:se(this.host._settings,{}),showRoomTooltip:ee(this.host._settings),zigbeeTopology:te(this.host._settings),busy:!1}},this._openSupportDialog=()=>{this.host._norm&&this.host._canEdit&&(clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this._supportPreviewGeneration+=1,this.host._supportDialog={draftId:qh("draft"),idempotencyKey:qh("report"),submissionFingerprint:"",contact:"",message:"",attach:!1,status:"idle",preview:null,rawOpen:!1,errorCode:"",reportId:""})},this._openAlignDialog=()=>this._previewAlignDialog(!1),this._toggleOptimizeLivePositions=()=>{const t=this.host._alignDialog;t&&!t.busy&&t.report.liveMissingPositions.length&&this._previewAlignDialog(!t.removeLiveMissingPositions)},this._openBackupExport=()=>{this.host._settingsDialog=null,this.host._backupExportDialog={kind:"full",planOnly:!1,busy:!1,error:""}},this._decorStylePersistTimer=null,this._openRulesDialog=()=>{if(!this.host._norm)return;const t=this.host._settings.icon_rules,e=(t&&t.length?t:ne).map(t=>({...t}));this.host._rulesDialog={rules:e,test:"",busy:!1}},this._discoveryPreviewMemo=null,this._decorImages=new Qh(t,{decorSnap:(t,e)=>this._decorSnap(t,e),geometrySnapshot:()=>this._geometrySnapshot(),clearFurniturePreview:()=>this._clearFurniturePreview(),recordGeometry:(t,e)=>this._recordGeometry(t,e),saveConfig:()=>this._saveConfig(),saveShape:()=>this._decorSaveShape(),setGuardReplace:t=>{this._decorAssetGuardReplace=t},furnShiftDetach:()=>this._furnShiftDetach(),furnPick:t=>this._furnPick(t),furnFieldValue:t=>this._furnFieldValue(t),furnFieldToCm:t=>this._furnFieldToCm(t)}),t._editorSecondary=new Eh({root:()=>t.renderRoot,requestUpdate:()=>t.requestUpdate(),updateComplete:()=>t.updateComplete,clearTip:()=>{t._tip=null}}),t._resize=new Ya}_routeLiveEditorUpdate(t,e){const s=Oo(this.host,t,e);return!s&&this.host._resize.preview&&(this._resizeBaseFrameStable=!1),s}_commitLiveEditor(){!function(t){const e=t,s=Ho(t);s.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(s.raf),s.raf=0,Go(s);const i=e.renderRoot?.querySelector("[data-hp-live-editor]");i&&u(l,i);const o=e.renderRoot?.querySelector("[data-hp-live-editor-html]");if(o){const t=e._viewOr(e._baseVb());u(e._renderLiveEditorMeasurements(t),o)}Lo(s,s.requestedRevision)}(this.host)}_disposeLiveEditor(){!function(t){zo(t);const e=Ro.get(t);e&&(e.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e.raf),Go(e),Lo(e,e.requestedRevision),Ro.delete(t))}(this.host)}async _whenLiveEditorSettled(){await this.host.updateComplete,await function(t){const e=Ro.get(t);if(!e||!e.raf||e.paintedRevision>=e.requestedRevision)return Promise.resolve();const s=e.requestedRevision;return new Promise(t=>e.waiters.push({revision:s,resolve:t}))}(this.host)}_queuePointerMove(t,e){Io(this.host,t,e)}_flushPointerMove(t){To(this.host,t)}_cancelPointerMove(t){zo(this.host,t)}_help(t){const e=`${t}.aria`,s=a(this.host.hass,this.host._config?.language);return re(s,t)&&re(s,e)?h``:l}_setMode(t,e=!0){t!==this.host._mode&&this.host._cancelDangerConfirm(),this.host._endTabDrag(),this._clearFurniturePreview(),this.host._pendingNavMode=null;const s=this.host._spaceModel();if(!s)return this.host._cancelModeTransition(!1),void(this.host._mode="view");if(this.host._kiosk&&"view"!==t)return;if(this.host._mode===t){if(!e&&"view"===t&&this.host._modeTransitionBusy){const e=this.host._currentModeVisual(t),s=this.host._modeTransitionTargetZoom,i=this.host._modeTransitionTargetCenterX,o=this.host._modeTransitionTargetCenterY;this.host._cancelModeTransition(!1),this.host._commitViewModeAtomic(e,s,i,o)}return}if("devices"===this.host._mode&&this.host._cancelDeviceDrag(),this.host._bootSoftCancel(),("plan"===t||"decor"===t)&&!this.host._norm)return void this.host._showToast(this.host._t("toast.markup_needs_server"));if(this.host._wallFaceBatch&&this._roomDialogCancel(),"plan"===this.host._mode&&"draw"===this.host._tool&&!this._finishWallChain())return;this.host._clearTransientHover(!0),this.host._cancelDevicePressFeedback();const i=this.host._mode,o=this.host._effectiveProjection(),a=this.host._currentModeVisual(i),n=this.host._modeTransitionBusy,r=a&&"view"!==i&&"view"!==t?{...a,toolbarContentOpacity:this.host._reducedMotion?1:.35}:a;this.host._cancelModeTransition(!1),this.host._editorSecondary.closeForNavigation(),(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)&&this._cancelDecorGesture();const l=!s.bg&&"view"===t!=("view"===i),h=n&&"view"===i&&"view"!==t?this.host._modeTransitionEditorCamera:null;let c=h?.zoom??(n?this.host._modeTransitionTargetZoom:this.host._zoom),d=h?h.centerX:n?this.host._modeTransitionTargetCenterX:r?.viewport.centerX,p=h?h.centerY:n?this.host._modeTransitionTargetCenterY:r?.viewport.centerY;if("view"===i&&"view"!==t&&!n){const e=this.host._view;if(this.host._viewModeSnap={space:this.host._space,zoom:this.host._zoom,cx:e?this.host._logicalViewCenter(o)?.x:void 0,cy:e?this.host._logicalViewCenter(o)?.y:void 0},"iso"===o){const e=this.host._logicalViewCenter("iso");d=e?.x,p=e?.y,this.host._view=null,this.host._mode=t,this.host._applyView(this.host._zoom,e?.x,e?.y)}l&&(c=1,d=void 0,p=void 0)}if("plan"===i&&this.host._activeDraftId&&(this.host._resumeDraftBySpace[this.host._space]=this.host._activeDraftId),this.host._mode=t,"devices"===i&&"devices"!==t&&(this.host._showHidden=!1,this.host._deviceInbox=null,this.host._deviceInboxReturn=null,this.host._deviceInboxMemo=null),this.host._editorChromeMode="view"===t?i:t,"view"===t){"view"===i||n||(this.host._modeTransitionEditorCamera={zoom:this.host._zoom,centerX:r?.viewport.centerX,centerY:r?.viewport.centerY});const t=this.host._viewModeSnap;if(t&&t.space===this.host._space){c=t.zoom;const e=this.host._labsIso&&"iso"===this.host._viewPreference[this.host._space]?"iso":"flat",s=null!=t.cx&&null!=t.cy&&"iso"===e?le([t.cx,t.cy],0):null;d=s?.[0]??t.cx,p=s?.[1]??t.cy}else t&&(c=this.host._zoomBySpace[this.host._space]||1,d=void 0,p=void 0)}else this.host._modeTransitionEditorCamera={zoom:c,centerX:d,centerY:p};this.host._modeTransitionTargetZoom=c,this.host._modeTransitionTargetCenterX=d,this.host._modeTransitionTargetCenterY=p,("iso"===o||"view"===t&&this.host._labsIso&&"iso"===this.host._viewPreference[this.host._space])&&(this.host._modeTransitionForceAtomic=!0);const u=++this.host._modeTransitionRequest;e?r?(this.host._modeTransitionPreparing=!0,this.host._modeTransitionVisual=r,this.host._prepareModeTransition(u,r,t,c,d,p)):(this.host._modeTransitionPreparing=!1,this.host._modeTransitionVisual=null,this.host._zoom=c,this.host._view=null,requestAnimationFrame(()=>{this.host.isConnected&&u===this.host._modeTransitionRequest&&this.host._mode===t&&(this.host._applyView(c,d,p),"view"===t&&(this.host._viewModeSnap=null,this.host._modeTransitionEditorCamera=null),this.host.requestUpdate())})):"view"===t&&this.host._commitViewModeAtomic(r,c,d,p),this.host._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this.host._tool="draw",this.host._mergeSel=null,this.host._mergeDialog=null,this.host._splitSel=null,this.host._pendingSplit=null,this.host._selId=null,this.host._physicalSel=null,this.host._physicalDialog=null,this.host._physicalDrag=null,this._rszResetController(),this.host._tip=null,this.host._hoverRoom=null,this.host._decorDraft=null,this.host._decorSel=null,this.host._decorMove=null,this.host._backdropDialog=null,this.host._decorTool="select",this.host._bdDrag=null,this.host._dtDrag=null,this.host._dtBox=null,"plan"===t&&(this._primeDrawWallField(),this._resumeLastDraft()),this.host._saveNav()}_primeDrawWallField(){null===this.host._drawWallField&&(this.host._drawWallField=he(dt,this.host._imperial))}_showPhysicalRange(t=this.host._drawWallMaxCm,e=0){this.host._showToast(this.host._t("toast.physical_range",{min:he(e,this.host._imperial),max:he(t,this.host._imperial),unit:this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_draftSegmentCount(t=this.host._curSpaceCfg){return(t?.room_drafts||[]).reduce((t,e)=>t+(Array.isArray(e.segments)?e.segments.length:0),0)}_mergeSpacePartitions(t,e){const s=t?.partitions||[];if(s.length<2)return 0;const i=jr(s,{pitch:E,seedIds:e,geometry:Ur(t,{excludeDraftId:this.host._activeDraftId})});return i.merged?(t.partitions=i.partitions,qr(t.openings,t.partitions,i.openingMoves,{coordScale:$c,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch}),i.merged):0}_finishWallChain(){if("draw"!==this.host._tool||this.host._wallFaceBatch||this.host._roomDialog)return!0;const t=this.host._curSpaceCfg;if(!t||this.host._path.length<2)return this.host._path=[],this.host._activeDraftId=null,this.host._draftSegmentCms=[],this.host._closingWallCm=null,this._clearPlanSnapHover(),!0;const e=ih(this.host._path,sh(this.host._path.length-1,this.host._draftSegmentCms,this.host._drawWallCm,dt)),s=e.length;if((t.partitions||[]).length+s>wc)return this.host._showToast(this.host._t("toast.physical_limit")),!1;const i=this._geometrySnapshot();t.partitions||=[];const o=Date.now().toString(36),a=[],n=this.host._activeDraftId?(t.room_drafts||[]).find(t=>t.id===this.host._activeDraftId):null,r=this._draftSegmentsForPath(this.host._path,n,e.map(t=>t.cm));for(let i=0;it.id!==this.host._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._commitPhysicalGeometry(this.host._t("history.wall_chain_finish"),i),delete this.host._resumeDraftBySpace[this.host._space],this.host._path=[],this.host._activeDraftId=null,this.host._draftSegmentCms=[],this.host._closingWallCm=null,this._clearPlanSnapHover(),!0}_activateMarkupTool(t){t!==this.host._tool&&(this.host._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this.host._tool||this._finishWallChain())&&(this._cancelPath(),"resize"===this.host._tool&&(this.host._resize.dragging?this._rszCancelDrag():this.host._resize.reset()),this.host._tool=t,"draw"===t&&this._resumeLastDraft(),"resize"===t&&this.host._resize.selectRoom(null),"wallthick"===t&&(this.host._wallDialog=null)))}_limitReached(t){const e=this.host._curSpaceCfg;if(!e)return!0;const s="draft"===t?(e.room_drafts||[]).length>=200:"partition"===t?(e.partitions||[]).length>=wc:(e.wall_columns||[]).length>=500;return s&&this.host._showToast(this.host._t("toast.physical_limit")),s}_svgPoint(t){const e=this.host.renderRoot.querySelector(".stage").getBoundingClientRect();return this.host._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this.host._gridPitch;return[ce(de(t[0],e)),ce(de(t[1],e))]}_snapDrawPoint(t,e=!1){const s=this.host._path[this.host._path.length-1],i=e&&s?pe(s,t,this.host._gridPitch,Qi):t;return this._snap(i)}_planSnapOpeningCuts(t,e){if(!this.host._openingsR.length)return[];const s=this.host._openingWallIndexFor(t,e).value,i=[];for(const e of this.host._roomWallOpeningInputs(this.host._openingsR,t)){const t=bt(s,e);if(!t.negative&&!t.positive)continue;const o=e.angle*Math.PI/180,a=Math.cos(o)*e.length/2,n=Math.sin(o)*e.length/2;i.push([e.x-a,e.y-n,e.x+a,e.y+n])}return i}_planSnapGeometrySnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this.host._space,this.host._cfgEpoch,this.host._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this.host._planSnapGeometryCache?.key===e)return this.host._planSnapGeometryCache;const s=this.host._openCuts(),i=Vl({space:t,activeDraftId:this.host._activeDraftId,roomCuts:this._planSnapOpeningCuts(t,s),partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this.host._gridPitch});return this.host._planSnapGeometryCache={key:e,value:i},this.host._planSnapGeometryCache}_hiddenWallDiagnosticSnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|hidden-empty`,value:{segments:[],endpoints:[]}};const e=["hidden",this.host._space,this.host._cfgEpoch,this.host._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this.host._hiddenWallDiagnosticCache?.key===e)return this.host._hiddenWallDiagnosticCache;const s=Kl({space:t,activeDraftId:this.host._activeDraftId,epsilon:2e-4*this.host._gridPitch});return this.host._hiddenWallDiagnosticCache={key:e,value:s},this.host._hiddenWallDiagnosticCache}_planStructuralGeometrySnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this.host._space,this.host._cfgEpoch,this.host._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this.host._planStructuralGeometryCache?.key===e)return this.host._planStructuralGeometryCache;const s=Vl({space:t,activeDraftId:this.host._activeDraftId,epsilon:2e-4*this.host._gridPitch});return this.host._planStructuralGeometryCache={key:e,value:s},this.host._planStructuralGeometryCache}_planSnapContextKey(t){const e=this.host._path[0],s=this.host._path[this.host._path.length-1];return[t,this.host._tool,this.host._path.length,e?`${e[0]},${e[1]}`:"",s?`${s[0]},${s[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const s=this._planSnapGeometrySnapshot(),i=this.host._path[this.host._path.length-1],o="draw"===this.host._tool&&this.host._path.length>=3?[{point:this.host._path[0],key:"closure:first-point"}]:[],a={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this.host._gridPitch,excludePoints:i?[i]:[],extraEndpoints:o,epsilon:2e-4*this.host._gridPitch},n=e&&i?th(s.value,t,{...a,anchor:i}):function(t,e,s){if(!(El(e)&&s.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const i=s.epsilon??Ll,o=s.excludePoints||[],a=Zl(Xl(t,e,s),s.distinguishTolerance||0);if(a)return a;let n=null;for(const a of t.segments){const t=[a.a[0],a.a[1],a.b[0],a.b[1]],r=Ht([e[0],e[1]],t);if(r>s.tolerance)continue;const l=Ql(a,e,s.gridStep);!Jl(l,o,i)&&Yl(r,a.key,n)&&(n={kind:"line",point:l,key:a.key,distance:r,segment:a})}return n?{kind:"resolved",candidate:n,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(s.value,t,a),r="resolved"===n.kind?n.candidate:null,l=r?[...r.point]:this._snapDrawPoint(t,e),h=i?ue(i,l):l;return{point:h,candidate:r&&O(h,r.point)?r:null,conflicts:"ambiguous"===n.kind?n.conflicts:[],ambiguous:"ambiguous"===n.kind,contextKey:this._planSnapContextKey(s.key)}}_clearPlanSnapHover(t=!0){this.host._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this.host._cursorPt=null)}_samePt(t,e){return O(t,e)}_dropLegacySegments(t=this.host._serverCfg){for(const e of t?.markers||[])"ripple"===e.display&&(e.display="icon_ripple");for(const e of t?.spaces||[]){delete e.segments;const t=new Set,s=e=>"string"==typeof e&&e.length>=1&&e.length<=64&&!t.has(e),i=e=>(t.add(e),!0),o=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=jt);if(Array.isArray(e.partitions)&&(e.partitions=e.partitions.filter(t=>t&&s(t.id)&&o(t.a)&&o(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&i(t.id)).map(t=>({...t,cm:Number.isFinite(Number(t.cm))?Math.max(0,Math.min(100,Number(t.cm))):15})),e.partitions.length||delete e.partitions),Array.isArray(e.wall_columns)&&(e.wall_columns=e.wall_columns.filter(t=>t&&s(t.id)&&o(t.center)&&i(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:Zt(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:_e(t.angle)}})),e.wall_columns.length||delete e.wall_columns),Array.isArray(e.room_drafts)&&(e.room_drafts=e.room_drafts.filter(t=>t&&s(t.id)&&Array.isArray(t.points)&&t.points.length>=2&&t.points.every(o)&&i(t.id)).map(t=>{const e=_n(t);return{id:t.id,...e}}).filter(t=>t.points.length>=2),e.room_drafts.length||delete e.room_drafts),Array.isArray(e.walls)){const t=me(zt({spaces:[e]}),e.id),s=t?ge(e,t,$c,.02*xt).contour.map(t=>t.map(t=>t/$c)):j(e.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);e.walls=St(e.walls,e.rooms||[],E,1,s),e.walls.length||delete e.walls}}}_rollbackRejectedPhysicalWrites(t){if(!this.host._serverCfg||!t.length)return!1;let e=!1;for(const[s]of t){const t=this.host._pendingPhysicalWrites.get(s);t&&(e=this._restoreGeometryStateInConfig(this.host._serverCfg,t.before)||e,this.host._pendingPhysicalWrites.delete(s))}return!!e&&(this._clearGeometryGesture(),this.host._geometryHistory.clear(),this.host._cfgEpoch++,this.host._modelCache=null,this.host._wallUnionCache=null,this.host._physicalBodiesCache=null,this.host._frame=null,this.host._regSignature="",this.host._cfgContentFingerprint=d(this.host._serverCfg),this.host._maybeRebuildDevices(),this.host.requestUpdate(),!0)}async _reloadRejectedPhysicalWrite(){const t=this.host._writeChain;await t.catch(()=>{}),await this.host._reloadConfigOnly(!0)}_prepareConfigCandidate(t){return this._dropLegacySegments(t),fe(t)}_writeConfig(t=null){this.host._writesPending++,this.host._writeChain=be(this.host._writeChain,async()=>{if(!this.host._serverCfg)return;const e=d(this.host._serverCfg),s=this._prepareConfigCandidate(this.host._serverCfg),i=d(s);t&&e===t.attemptedFingerprint&&Object.assign(t,{revision:this.host._cfgRev,attempted:s,attemptedFingerprint:i});const o=[...this.host._pendingPhysicalWrites.entries()];for(const[t,e]of o){const i=s.spaces.find(e=>e.id===t),o=Y(i);if(o===e.fingerprint)continue;let a=!1;try{a=this.host._checkSpacePhysicalGeometry(s,t).ok}catch{a=!1}if(!a)throw this._restoreGeometryStateLocal(e.before),this.host._pendingPhysicalWrites.delete(t),this.host._geometryHistory.clear(),this.host._showToast(this.host._t("toast.geometry_unsafe")),Object.assign(new Error("unsafe wall geometry"),{code:"geometry-unsafe"});e.fingerprint=o}i!==d(this.host._serverCfg)&&(this.host._serverCfg=s),this.host._cfgContentFingerprint=i;try{await this.host._sendConfigCandidate(s)}catch(t){if(!this._rollbackRejectedPhysicalWrites(o))throw t;const e=t&&"object"==typeof t?t:Object.assign(new Error(String(t)),{cause:t});throw e.physicalGeometryRolledBack=!0,e}for(const[t,e]of o)this.host._pendingPhysicalWrites.get(t)?.fingerprint===e.fingerprint&&this.host._pendingPhysicalWrites.delete(t)});return this.host._writeChain.finally(()=>{this.host._writesPending--})}_saveConfig(){this.host._cfgEpoch++,this.host._saveConfigDebounced()}_geometrySnapshotFromConfig(t,e){const s=t?.spaces?.find(t=>t.id===e);if(!s)return null;const i=t=>JSON.parse(JSON.stringify(t)),o={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==s[t]&&(o[t]=s[t]);return{spaceId:e,rooms:i(s.rooms||[]),...Array.isArray(s.openings)?{openings:i(s.openings)}:{},...Array.isArray(s.walls)?{walls:i(s.walls)}:{},...Array.isArray(s.wall_segments)?{wall_segments:i(s.wall_segments)}:{},...Array.isArray(s.open_spans)?{open_spans:i(s.open_spans)}:{},...Array.isArray(s.room_drafts)?{room_drafts:i(s.room_drafts)}:{},...Array.isArray(s.partitions)?{partitions:i(s.partitions)}:{},...Array.isArray(s.wall_columns)?{wall_columns:i(s.wall_columns)}:{},...Array.isArray(s.decor)?{decor:i(s.decor)}:{},plan_transform:o}}_geometrySnapshot(t=this.host._space){return this._geometrySnapshotFromConfig(this.host._serverCfg,t)}_recordGeometry(t,e){if(!e)return;const s=this._geometrySnapshot(e.spaceId);s&&JSON.stringify(e)!==JSON.stringify(s)&&(this.host._geometryHistory.push({name:t,before:e,after:s}),this.host.requestUpdate())}_restoreGeometryStateInConfig(t,e,s=!1){const i=t?.spaces?.find(t=>t.id===e.spaceId);if(!i)return!1;const o=t=>JSON.parse(JSON.stringify(t)),a=new Map((i.rooms||[]).map(t=>[t.id,t]));if(i.rooms=o(e.rooms),s)for(const t of i.rooms){const e=a.get(t.id);!Array.isArray(t.wall_ids)&&Array.isArray(e?.wall_ids)&&e.wall_ids.length===t.poly?.length&&(t.wall_ids=o(e.wall_ids))}const n=(t,e)=>{void 0!==e?i[t]=o(e):s&&"wall_segments"===t||delete i[t]},r=new Map((i.openings||[]).map(t=>[t.id,t])),l=new Map((i.room_drafts||[]).map(t=>[t.id,t]));if(n("openings",e.openings),n("walls",e.walls),n("wall_segments",e.wall_segments),n("open_spans",e.open_spans),n("room_drafts",e.room_drafts),n("partitions",e.partitions),n("wall_columns",e.wall_columns),n("decor",e.decor),s){for(const t of i.openings||[]){const e=r.get(t.id);t.host||"wall"!==e?.host?.kind||(t.host=o(e.host))}for(const t of i.room_drafts||[]){const e=l.get(t.id);for(let s=0;s<(t.segments||[]).length;s++)!t.segments[s]?.id&&e?.segments?.[s]?.id&&(t.segments[s].id=e.segments[s].id)}}for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete i[t];return Object.assign(i,o(e.plan_transform||{})),!0}_restoreGeometryStateLocal(t){return!!this._restoreGeometryStateInConfig(this.host._serverCfg,t)&&(this.host._cfgEpoch++,this.host._modelCache=null,this.host._wallUnionCache=null,this.host._physicalBodiesCache=null,this.host._frame=null,this.host.requestUpdate(),!0)}_wallModelBlockerLabel(t){const e=t instanceof nn?t.reason:"invalid-room";return this.host._t(`wall_model.reason.${e}`)}_hasLegacyZeroWallFields(t=this.host._serverCfg){return(t?.spaces||[]).some(t=>Array.isArray(t?.open_spans)&&t.open_spans.length>0||(t?.rooms||[]).some(t=>Array.isArray(t?.open_to)&&t.open_to.length>0))}_showWallModelMigrationBlocked(t){const e=this._hasLegacyZeroWallFields()?"toast.zero_wall_migration_blocked":"toast.wall_model_migration_blocked";this.host._showToast(this.host._t(e,{reason:this._wallModelBlockerLabel(t)}))}_limitSegmentsOf(t){const e=[];for(const s of t?.wall_segments||[])s?.a&&s?.b&&e.push({id:String(s.id||""),a:s.a,b:s.b,cm:Number(s.cm)});for(const s of t?.partitions||[])s?.a&&s?.b&&e.push({id:String(s.id||""),a:s.a,b:s.b,cm:Number(s.cm)});for(const s of t?.room_drafts||[]){const t=Array.isArray(s?.points)?s.points:[],i=Array.isArray(s?.segments)?s.segments:[];for(let o=0;o+1t?.id===e);return o?function(t,e,s,i,o){const a=(t?.spaces||[]).find(t=>t?.id===e);if(!a)return[];const n=Number(a.cell_cm)>0?Number(a.cell_cm):5,r=[...br(s),...kr(s,n,E),...Sr(s,n,E)];let l=i?.multiWallNodes||null;if(!l)try{l=it(a.rooms||[],a.walls||[],[],E,n,E,1)}catch{l=null}const h=i&&"lightweight"!==i.status?i:null;let c="ok"===h?.status||"degraded-extra"===h?.status?h.roomGeom:null;const d=null===i||"lightweight"===i?.status;if(!c&&!d&&l?.nodes.length)try{const t=ot(a.rooms||[],a.walls||[],[],[],E,n,E,1);c="ok"===t?.status||"degraded-extra"===t?.status?t.roomGeom:null}catch{c=null}for(const t of a.rooms||[]){const e=String(t?.id||"");if(!e||o&&!o.has(e))continue;let s=null;try{s=at(a.rooms||[],e,a.walls||[],[],E,n,E,1,d?null:c??void 0,l)}catch{s=null}r.push(...Mr(e,s,n,E))}return r}(t,e,this._limitSegmentsOf(o),s,i):[]}_junctionLimitLabel(t){const e=t=>String(Math.round(10*t)/10);return this.host._t(`junction.limit_${t.rule}`,{actual:e(t.actual),limit:e(t.limit)})}_junctionLimitsIntroduced(t,e,s,i,o){const a=o?.length?new Set(o):void 0;let n;const r=(e.spaces||[]).find(t=>t?.id===s);let l="";try{l=Y(r)}catch{l=""}const h=!a&&e&&"object"==typeof e?this._junctionBaselineCache.get(e):void 0;if(h&&l&&h.fingerprint===l&&h.spaceId===s&&(n=h.violations),!n){try{const t=Number(e?.model_version||0)>=9?e:Tn(e).config;n=this.host._junctionLimitViolations(t,s,a?null:void 0,a)}catch{return[]}!a&&e&&"object"==typeof e&&l&&this._junctionBaselineCache.set(e,{spaceId:s,fingerprint:l,violations:n})}let c=[],d=n;try{c=this.host._junctionLimitViolations(t,s,i,a),a&&(d=n.filter(t=>"clearance"!==t.rule||a.has(t.subject)))}catch{return[{rule:"check_failed",subject:s,actual:0,limit:0}]}return Dr(c,d)}_commitPhysicalGeometry(t,e,s=[]){if(!e||!this.host._serverCfg)return!1;const i=this.host._serverCfg,o=this._geometrySnapshotFromConfig(i,e.spaceId),a=i.spaces.find(t=>t.id===e.spaceId);if(!a||Y(e)===Y(a))return!1;let n,r=!1;try{r=this.host._checkSpacePhysicalGeometry(i,e.spaceId).ok}catch{r=!1}if(!r)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;let l=e;try{if(Number(i.model_version||0)<9){const t=JSON.parse(JSON.stringify(i));if(!this._restoreGeometryStateInConfig(t,e))throw new nn("invalid-room",e.spaceId);const s=Tn(t).config;l=this._geometrySnapshotFromConfig(s,e.spaceId)||e;const a=JSON.parse(JSON.stringify(s));if(!o||!this._restoreGeometryStateInConfig(a,o,!0))throw new nn("invalid-room",e.spaceId);const r=s.spaces.find(t=>t.id===e.spaceId),h=a.spaces.find(t=>t.id===e.spaceId);if(!Array.isArray(o.wall_segments)&&JSON.stringify(e.rooms)===JSON.stringify(o.rooms))for(const t of h?.wall_segments||[])t.cm=J(o.walls,t.a,t.b,E,1);const c=((t,e,s)=>{const i=new Map,o=new Map((t?.rooms||[]).map(t=>[t.id,t])),a=new Map((e||[]).map(t=>[t.id,t])),{rooms:n}=Mn(s,xn(t));for(const t of n){const e=a.get(t.id),n=o.get(t.id),r=W(e),l=(s.rooms||[]).find(e=>e.id===t.id),h=W(l),c=W(n);if(r&&h&&c&&r.length===h.length&&c.length===n?.wall_ids?.length&&t.poly.length===t.wall_ids.length)for(let e=0;e{const o=[];for(let a=0;aan||fn(r,s,i)>an)continue;const l=gn(n,s,i),h=gn(r,s,i);l<-1e-9||h>1+an||h<=l+an||o.push({start:l,id:e[a]})}return o.sort((t,e)=>t.start-e.start)},o=s(c,n.wall_ids,r[e],r[(e+1)%r.length]),a=s(t.poly,t.wall_ids,h[e],h[(e+1)%h.length]);if(o.length&&o.length===a.length)for(let t=0;tt.id===e.spaceId),i=this.host._path.length>=2?this.host._path.map(t=>[t[0]/$c,t[1]/$c]):[];i.push(...s.map(t=>[t[0],t[1]])),h=mn(t)<=mn(l,i)&&this.host._checkSpacePhysicalGeometry(n,e.spaceId).ok}catch{h=!1}if(!h)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;const c=JSON.parse(JSON.stringify(i));this._restoreGeometryStateInConfig(c,e);const d=this._junctionLimitsIntroduced(n,c,e.spaceId);if(d.length)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this._junctionLimitLabel(d[0])),!1;Rn(i,n),this._recordGeometry(t,l);const p=i.spaces.find(t=>t.id===e.spaceId),u=this.host._pendingPhysicalWrites.get(e.spaceId);return this.host._pendingPhysicalWrites.set(e.spaceId,{before:u?.before||l,fingerprint:Y(p)}),this._saveConfig(),!0}_clearGeometryGesture(){this._clearFurniturePreview(),this.host._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this.host._mergeSel=null,this.host._mergeDialog=null,this.host._splitSel=null,this.host._pendingSplit=null,this.host._wallFaceBatch=null,this.host._wallRepairDiagnostic=null,this.host._roomDeleteDialog=null,this.host._wallDialog=null,this.host._physicalDialog=null,this.host._physicalSel=null,this.host._physicalDrag=null,this.host._physicalRotate=null,this.host._activeDraftId=null,this.host._draftSegmentCms=[],this.host._closingWallCm=null,this.host._openingDialog=null,this._rszResetController(),this.host._decorDraft=null,this.host._decorMove=null,this.host._dtDrag=null,this.host._bdDrag=null}_stagePointerCancel(t){return clearTimeout(this.host._kioskHoldTimer),this.host._swipeStart?.id===t.pointerId&&(this.host._swipeStart=null),this.host._furnTouchPending?.pid===t.pointerId?(this._clearFurniturePreview(),this.host._pointers.delete(t.pointerId),void this.host.requestUpdate()):this.host._physicalDrag?.pid!==t.pointerId&&this.host._physicalRotate?.pid!==t.pointerId?this.host._decorDraft?.pid===t.pointerId?(this.host._decorDraft=null,void this.host.requestUpdate()):void(this.host._decorMove?.pid!==t.pointerId&&this.host._dtDrag?.pid!==t.pointerId&&this.host._bdDrag?.pid!==t.pointerId?("opening"===this.host._tool?(this.host._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this.host._tool&&this._clearPlanSnapHover(),this.host._pointers.delete(t.pointerId),this.host._pointers.size<2&&(this.host._pinchStart=null),0===this.host._pointers.size&&(this.host._panStart=null,this.host._panLock=null),this.host._viewportGestureDirty&&0===this.host._pointers.size&&(this.host._viewportGestureDirty=!1,this.host.requestUpdate())):this._cancelDecorGesture()):void this._cancelPhysicalGesture()}_applyGeometryState(t,e=!1){if(!this.host._canCommitSpace(t.spaceId))return!1;const s=this._geometrySnapshot(t.spaceId);if(!s||!this._restoreGeometryStateLocal(t))return!1;const i=this.host._serverCfg,o=Y(s)!==Y(t);if(o){let o=!1;try{const s=i?this.host._checkSpacePhysicalGeometry(i,t.spaceId):null;o=!!s?.ok||!(!e||"wall-degraded-extra"!==s?.reason)}catch{o=!1}if(!o)return this._restoreGeometryStateLocal(s),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1}let a;try{a=Tn(i).config}catch(t){return this._restoreGeometryStateLocal(s),this._showWallModelMigrationBlocked(t),!1}if(o){let o=!1;try{const s=a?this.host._checkSpacePhysicalGeometry(a,t.spaceId):null;o=!!s?.ok||!(!e||"wall-degraded-extra"!==s?.reason)}catch{o=!1}if(!o)return this._restoreGeometryStateLocal(s),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;Rn(i,a);const n=i?.spaces.find(e=>e.id===t.spaceId),r=this.host._pendingPhysicalWrites.get(t.spaceId);this.host._pendingPhysicalWrites.set(t.spaceId,{before:r?.before||s,fingerprint:Y(n)})}else Rn(i,a);return this._clearGeometryGesture(),this.host._space!==t.spaceId&&(this.host._commitSpace(t.spaceId),this.host._saveNav(),this.host._restoreZoom()),this.host._modelCache=null,this.host._frame=null,this.host._regSignature="",this.host._maybeRebuildDevices(),this._saveConfig(),this.host.requestUpdate(),!0}_roomAt(t){return this.host._spaceModel()?.rooms.find(e=>{const s=W(e);return!!s&&ve(t,s)})}_overlapRoom(t){return this.host._spaceModel()?.rooms.find(e=>{const s=W(e);return!!s&&N(t,s)})}_pointInRoom(t,e){return e.poly?ye(t,e.poly):null!=e.x&&t[0]>=e.x&&t[0]<=e.x+e.w&&t[1]>=e.y&&t[1]<=e.y+e.h}_contourSelfIntersects(t){if(!ka(t))return!0;const e=t.length,s=.001;for(let i=0;i=500)return this.host._showToast(this.host._t("toast.physical_limit")),!1;const t=this.host._curSpaceCfg;return!(!this.host._activeDraftId&&(t?.room_drafts||[]).length>=200||this._draftSegmentCount(t)>=2e3||(t?.partitions||[]).length+this.host._path.length>wc)||(this.host._showToast(this.host._t("toast.physical_limit")),!1)}_markupClick(t){if(this.host._vacFit)return;if(!this.host._markup)return;const e=this.host._spaceModel();if(!e)return void this._clearGeometryGesture();if(this.host._suppressClick)return;if(this.host._drag||this.host._rlResize)return;const s=t.composedPath?.()||[];if(s.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(s.some(t=>t?.classList?.contains?.("physical-hit")))return;const i=this._svgPoint(t);if("select"===this.host._tool)return void(this.host._physicalSel=null);if("resize"===this.host._tool){if(this.host._resize.dragging||s.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(i,t));return this.host._resize.selectRoom(t?.id||null),void this.host.requestUpdate()}if("delroom"===this.host._tool)return void this._deleteRoomClick(i);if("opening"===this.host._tool)return void this._openingClick(i);if("merge"===this.host._tool)return void this._mergeClick(i);if("wallthick"===this.host._tool)return void this._wallThickClick(i);if("split"===this.host._tool)return void this._splitClick(i);if("column"===this.host._tool)return void this._columnClick(i);this.host._wallRepairDiagnostic=null;const o=this._resolvePlanDrawPoint(i,t.shiftKey);if(o.ambiguous)return this.host._planSnapHover={contextKey:o.contextKey,candidate:null,conflicts:o.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(o.conflicts),void this.host._showToast(this.host._t("toast.plan_snap_ambiguous"));let a=o.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this.host._path.length<3)return;a=ue(this.host._path[this.host._path.length-1],this.host._path[0])}if(!this.host._path.length){if(!t.shiftKey&&!o.candidate&&this._offerExistingWallFace(i))return;const e=this._draftEndAt(a);return e?(this.host._activeDraftId=e.draft.id,this.host._resumeDraftBySpace[this.host._space]=e.draft.id,this.host._path=e.reverse?[...e.draft.points].reverse().map(t=>[...t]):e.draft.points.map(t=>[...t]),void(this.host._draftSegmentCms=this._adoptDraftCms(this.host._path,e.reverse?[...e.draft.segments].reverse().map(t=>t.cm):e.draft.segments.map(t=>t.cm),e.draft.id))):(this.host._activeDraftId=null,this.host._draftSegmentCms=[],void(this.host._path=[a]))}const n=this.host._path[this.host._path.length-1];if(this._samePt(a,n))return;const r=this._draftEndAt(a,this.host._activeDraftId||void 0);if(r)return void this._mergeDraftEndpoint(r);if(!this._canAppendRoomDraftPoint())return;const l=this.host._drawWallCm;if(null==l)return void this._showPhysicalRange(100);const h=this.host._path.map(t=>[...t]);this.host._path=[...this.host._path,a],this.host._draftSegmentCms=[...this.host._draftSegmentCms,l],this._persistActiveDraftSegment(),this._offerWallFaces(h)}_draftEndAt(t,e){const s=this.host._spaceModel();if(!s)return null;const i=this.host._viewOr(this.host._baseVb()),o=Math.max(.15*this.host._gridPitch,this.host._stageEl?.clientWidth?i.w/this.host._stageEl.clientWidth*12:0);for(const i of s.room_drafts||[]){if(i.id===e)continue;if(i.points.length<2)continue;const s=i.points[0],a=i.points[i.points.length-1];if(Math.hypot(t[0]-a[0],t[1]-a[1])<=o)return{draft:i,reverse:!1};if(Math.hypot(t[0]-s[0],t[1]-s[1])<=o)return{draft:i,reverse:!0}}return null}_mergeDraftEndpoint(t){const e=this.host._curSpaceCfg;if(!e||!this.host._path.length)return;const s=this.host._path.map(t=>[...t]),i=this._wallGraphSources(s),o=Array.isArray(e.room_drafts)?e.room_drafts:[],a=this.host._activeDraftId?o.find(t=>t.id===this.host._activeDraftId):null,n=o.find(e=>e.id===t.draft.id);if(!n)return;const r=t.reverse?t.draft.points.map(t=>[...t]):[...t.draft.points].reverse().map(t=>[...t]),l=t.reverse?(n.segments||[]).map(t=>({...t})):[...n.segments||[]].reverse().map(t=>({...t})),h=this.host._path[this.host._path.length-1],c=this._samePt(h,r[0]),d=c?null:this.host._drawWallCm;if(!c&&null==d)return void this._showPhysicalRange(100);const p=this._draftSegmentsForPath(this.host._path,a,this.host._draftSegmentCms),u=[...this.host._path.map(t=>[...t]),...c?r.slice(1):r],_=[...p,...null==d?[]:[{cm:d}],...l],m=u.length>=4&&this._samePt(u[0],u[u.length-1]),g=u,f=_;if(g.length>500)return void this.host._showToast(this.host._t("toast.physical_limit"));const b=(a?.segments?.length||0)+(n.segments?.length||0);if(this._draftSegmentCount(e)-b+f.length>2e3)return void this.host._showToast(this.host._t("toast.physical_limit"));if(m){const t=g.slice(0,-1);if(this._contourSelfIntersects(t)||L(t)<=1e-6)return void this.host._showToast(this.host._t("toast.contour_cannot_close"));const e=this._overlapRoom(t);if(e)return void this.host._showToast(this.host._t("toast.room_overlap",{name:e.name||""}))}const v=this._geometrySnapshot(),y=this.host._activeDraftId||t.draft.id,$={...a||n,id:y,points:g.map(t=>[t[0]/$c,t[1]/$c]),segments:f};e.room_drafts=o.filter(e=>e.id!==t.draft.id&&(!this.host._activeDraftId||e.id!==this.host._activeDraftId)),e.room_drafts.push($),this.host._activeDraftId=y,this.host._resumeDraftBySpace[this.host._space]=y,this.host._path=g,this.host._draftSegmentCms=this._adoptDraftCms(g,f.map(t=>Number(t.cm)),y),this.host._physicalSel=null,this._commitPhysicalGeometry(this.host._t("history.draft_merge"),v),null!=d&&this._offerWallFaces(s,s.length-1,i)}_adoptDraftCms(t,e,s){const i=Math.max(0,t.length-1),o=sh(i,e,this.host._drawWallCm,dt);return e.length!==i&&console.debug(`[houseplan] draft ${s??"?"}: восстановлено толщин ${i-e.length} (#234)`),o}_draftSegmentsForPath(t,e,s){const i=Array.isArray(e?.points)?e.points.map(t=>[Number(t?.[0])*$c,Number(t?.[1])*$c]):[],o=Array.isArray(e?.segments)?e.segments:[];return sh(Math.max(0,t.length-1),s,this.host._drawWallCm,dt).map((e,s)=>{const a=t[s],n=t[s+1],r=i.findIndex((t,e)=>{if(e+1>=i.length)return!1;const s=i[e+1];return this._samePt(a,t)&&this._samePt(n,s)||this._samePt(a,s)&&this._samePt(n,t)});return{...r>=0?o[r]:{},cm:e}})}_persistActiveDraftSegment(){if(this.host._path.length<2||!this.host._curSpaceCfg)return;const t=this._geometrySnapshot(),e=this.host._curSpaceCfg;e.room_drafts||=[],this.host._activeDraftId||(this.host._activeDraftId="draft-"+Date.now().toString(36)),this.host._resumeDraftBySpace[this.host._space]=this.host._activeDraftId;const s=e.room_drafts.findIndex(t=>t.id===this.host._activeDraftId),i={...s>=0?e.room_drafts[s]:{},id:this.host._activeDraftId,points:this.host._path.map(t=>[t[0]/$c,t[1]/$c]),segments:this._draftSegmentsForPath(this.host._path,s>=0?e.room_drafts[s]:null,this.host._draftSegmentCms)};s>=0?e.room_drafts[s]=i:e.room_drafts.push(i),Zn(this,this.host._t("history.draft_segment"),t)}_activeWallSourceKey(t){return`active:${this.host._activeDraftId||"session"}:${t}`}_wallGraphSources(t){const e=this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}));for(let s=0;s+1t.key===s);if(i>=0){const[t]=this.host._wallFaceGraphCache.splice(i,1);return this.host._wallFaceGraphCache.push(t),t.value}const o=Sh(t,e);return this.host._wallFaceGraphCache.push({key:s,value:o}),this.host._wallFaceGraphCache.length>4&&this.host._wallFaceGraphCache.shift(),o}_offerWallFaces(t,e=this.host._path.length-2,s){if(this.host._path.length<2||this.host._wallFaceBatch||this.host._roomDialog)return;const i=this.host._spaceModel();if(!i)return;const o=this._activeWallSourceKey(e),a=2e-4*this.host._gridPitch;let n,r;try{const e=s||this._wallGraphSources(t);r=this._wallGraphSources(this.host._path),n=function(t,e,s){const i=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!i.has(t.key)&&t.sourceKeys.includes(s))}(this._wallFaceGraph(e,a),this._wallFaceGraph(r,a),o)}catch{return}if(!n.length){const t=Hh(r,{requiredSourceKey:o,maxDistance:$(2,this.host._cellCm,this.host._gridPitch),gridStep:this.host._gridPitch,epsilon:a});return"ambiguous"===t.kind?(this.host._wallRepairDiagnostic=t.proposals[0]||null,void this.host._showToast(this.host._t(0===this.host._drawWallCm?"toast.zero_wall_ambiguous":"toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of i.rooms){const e=W(t);if(!t.id||!e)continue;const s=$e(e,this.host._path,.02*this.host._gridPitch);if(!s)continue;const[i,o]=s,a=L(i)>=L(o)?i:o,r=a===i?o:i,l=[...n].sort((t,e)=>Math.abs(t.area-L(r))-Math.abs(e.area-L(r))||t.key.localeCompare(e.key))[0];if(!l)return;return void this._beginWallFaceBatch([{...l,ring:r.map(t=>[t[0],t[1]]),split:{roomId:t.id,mainPoly:a,newPoly:r},consumeAllActive:!0}])}const l=n.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this.host._wallRepairDiagnostic=null,this.host._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this.host._path.map(t=>[...t]),activeCms:[...this.host._draftSegmentCms],activeDraftId:this.host._activeDraftId},this._clearPlanSnapHover(),this.host._nameSel="",this.host._areaSel="",this._resetRoomDialogFields(),this.host._roomDialog=!0}_offerExistingWallFace(t){if(this.host._path.length||this.host._wallFaceBatch||this.host._roomDialog)return!1;const e=2e-4*this.host._gridPitch;try{let s,i=Mh(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!i){const o=Hh(this._wallGraphSources([]),{point:t,maxDistance:$(2,this.host._cellCm,this.host._gridPitch),gridStep:this.host._gridPitch,epsilon:e});if("ambiguous"===o.kind)return this.host._wallRepairDiagnostic=o.proposals[0]||null,this.host._showToast(this.host._t(0===this.host._drawWallCm?"toast.zero_wall_ambiguous":"toast.wall_repair_ambiguous")),!0;if("repair"===o.kind)i=o.face,s=o.proposal;else if("none"===o.kind){const s=Hh(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this.host._gridPitch,epsilon:e});if("repair"===s.kind)return this.host._wallRepairDiagnostic=s.proposal,this.host._showToast(this.host._t("toast.wall_repair_too_large")),!0}}return!(!i||i.ring.length<3||this._contourSelfIntersects(i.ring)||this._overlapRoom(i.ring))&&(this._beginWallFaceBatch([{...i,existing:!s,repair:s}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),s=this.host._drawWallCm;if(null==s)return void this._showPhysicalRange(Jt,1);if(!this.host._curSpaceCfg||this._limitReached("column"))return;const i=this.host._spaceModel();if(!i)return;const o={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:Zt(s),angle:0},a=(i.wall_columns||[]).find(t=>Yt(t,o,.02*this.host._gridPitch));if(a)return clearTimeout(this.host._duplicateColumnTimer),this.host._duplicateColumnId=a.id,this.host._duplicateColumnTimer=window.setTimeout(()=>{this.host._duplicateColumnId=null},900),void this.host._showToast(this.host._t("toast.column_duplicate"));const n=this._geometrySnapshot(),r=this.host._curSpaceCfg;r.wall_columns||=[],r.wall_columns.push({...o,center:[e[0]/$c,e[1]/$c]}),this._commitPhysicalGeometry(this.host._t("history.column_add"),n)}_openPhysicalDialog(t,e,s){const i=this.host._spaceModel();if(i)if("partition"===t){const s=i.partitions.find(t=>t.id===e);s&&(this.host._physicalDialog={kind:t,id:e,cm:he(s.cm,this.host._imperial),length:this.host._fmtLen(s.a,s.b)})}else if("column"===t){const s=i.wall_columns.find(t=>t.id===e);s&&(this.host._physicalDialog={kind:t,id:e,cm:he(s.cm,this.host._imperial),shape:s.shape,angle:this.host._angleField("square"===s.shape?_e(s.angle):0)})}else{const o=i.room_drafts.find(t=>t.id===e),a=Math.max(0,Math.min(o?.segments.length?o.segments.length-1:0,s||0));o?.segments[a]&&(this.host._physicalDialog={kind:t,id:e,segment:a,cm:he(o.segments[a].cm,this.host._imperial),length:this.host._fmtLen(o.points[a],o.points[a+1])})}}_physicalDown(t,e,s){const i=this.host._spaceModel();if(!i)return;t.stopPropagation(),kc(t);const o=this._svgPoint(t),a=[];for(const t of[...i.wall_columns].reverse())we(o,ke(t,this.host._cellCm,this.host._gridPitch))&&a.push({kind:"column",id:t.id});for(const t of[...i.partitions].reverse()){const e=xe(t.a,t.b,t.cm,this.host._cellCm,this.host._gridPitch);e&&we(o,e)&&a.push({kind:"partition",id:t.id})}a.some(t=>t.kind===e&&t.id===s)||a.unshift({kind:e,id:s});const n=a.map(t=>`${t.kind}:${t.id}`).sort().join("|"),r=performance.now(),l=this.host._physicalPickCycle,h=a.length>1&&l?.signature===n&&r-l.at>380&&r-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%a.length:Math.max(0,a.findIndex(t=>t.kind===e&&t.id===s));this.host._physicalPickCycle={signature:n,index:h,x:t.clientX,y:t.clientY,at:r},e=a[h].kind,s=a[h].id;const c="partition"===e?i.partitions.find(t=>t.id===s):i.wall_columns.find(t=>t.id===s);c&&(this.host._physicalSel={kind:e,id:s},this.host._physicalDrag={pid:t.pointerId,kind:e,id:s,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(c)),delta:[0,0]})}_clampPhysicalDelta(t,e,s){const i="partition"===t?[e.a,e.b]:[e.center],o=i.map(t=>t[0]),a=i.map(t=>t[1]);return[Math.max(-jt*$c-Math.min(...o),Math.min(jt*$c-Math.max(...o),s[0])),Math.max(-jt*$c-Math.min(...a),Math.min(jt*$c-Math.max(...a),s[1]))]}_physicalMove(t){t.stopPropagation(),Io(this.host,"physical",()=>this._physicalMoveNow(t))}_physicalMoveNow(t){const e=this.host._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const s=this._svgPoint(t),i="partition"===e.kind?e.base.a:e.base.center,o=this._snap([i[0]+s[0]-e.start[0],i[1]+s[1]-e.start[1]]),a=this._clampPhysicalDelta(e.kind,e.base,[o[0]-i[0],o[1]-i[1]]);this.host._physicalDrag={...e,delta:a,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){To(this.host,"physical");const e=this.host._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this.host._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const s=this.host._spaceModel();if(!this.host._curSpaceCfg||!s)return;const i=this.host._curSpaceCfg;if("partition"===e.kind){const t=(i.partitions||[]).find(t=>t.id===e.id),s=e.base;if(t){const o={...s,a:[s.a[0]+e.delta[0],s.a[1]+e.delta[1]],b:[s.b[0]+e.delta[0],s.b[1]+e.delta[1]]};t.a=[o.a[0]/$c,o.a[1]/$c],t.b=[o.b[0]/$c,o.b[1]/$c];for(const t of i.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const s=lt(t,[o],$c,this.host._cellCm,this.host._gridPitch).resolved;s&&Object.assign(t,ht(t,s,$c))}}}else{const t=(i.wall_columns||[]).find(t=>t.id===e.id),o=e.base,a={...o,center:[o.center[0]+e.delta[0],o.center[1]+e.delta[1]]};if(s.wall_columns.some(t=>t.id!==e.id&&Yt(t,a,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"));t&&(t.center=[(o.center[0]+e.delta[0])/$c,(o.center[1]+e.delta[1])/$c])}this._commitPhysicalGeometry(this.host._t("history.physical_move"),e.before)}_registerPhysicalTap(t,e,s){const i=performance.now(),o=this.host._physicalLastTap?.kind===t&&this.host._physicalLastTap.id===e&&this.host._physicalLastTap.segment===s&&i-this.host._physicalLastTap.at<=360;this.host._physicalLastTap={kind:t,id:e,segment:s,at:i},o&&(this.host._physicalLastTap=null,this._openPhysicalDialog(t,e,s))}_cancelPhysicalGesture(){zo(this.host,"physical"),zo(this.host,"physical-rotate"),this.host._physicalDrag=null,this.host._physicalRotate=null,this.host.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this.host._spaceModel())return;t.preventDefault(),t.stopPropagation(),kc(t);const s=this._svgPoint(t);this.host._physicalSel={kind:"column",id:e.id},this.host._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(s[1]-e.center[1],s[0]-e.center[0])/Math.PI,baseAngle:_e(e.angle),angle:_e(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){t.preventDefault(),t.stopPropagation(),Io(this.host,"physical-rotate",()=>this._physicalRotateMoveNow(t))}_physicalRotateMoveNow(t){const e=this.host._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const s=this._svgPoint(t),i=180*Math.atan2(s[1]-e.center[1],s[0]-e.center[0])/Math.PI,o=e.baseAngle+i-e.startAngle,a=_e(t.shiftKey?o:5*Math.round(o/5));this.host._physicalRotate={...e,angle:a,moved:e.moved||Math.abs(o-e.baseAngle)>=.5}}_physicalRotateUp(t){To(this.host,"physical-rotate");const e=this.host._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this.host._physicalRotate=null;const s=this.host._spaceModel();if(!e.moved||!this.host._curSpaceCfg||!s)return;const i=s.wall_columns.find(t=>t.id===e.id);if(!i||"square"!==i.shape)return;const o={...i,angle:e.angle};if(s.wall_columns.some(t=>t.id!==e.id&&Yt(t,o,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"));const a=this.host._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);a&&(a.angle=e.angle,this._commitPhysicalGeometry(this.host._t("history.physical_edit"),e.before))}_rszRooms(){const t=[],e=this.host._spaceModel();if(!e)return t;for(const s of e.rooms){const e=s.id?W(s):null;e&&t.push({id:s.id,poly:e,wall_ids:Array.isArray(s.wall_ids)?[...s.wall_ids]:void 0})}return s=t,i=Math.max(1e-12,1e-12*this.host._gridPitch),s.map(t=>{if(!Array.isArray(t.wall_ids)||t.wall_ids.length!==t.poly.length)return{...t,poly:t.poly.map(t=>[...t])};const e=t.poly.map(t=>[...t]);let s=!0;for(;s&&e.length>3;){s=!1;for(let t=0;t0){e.splice(t,1),s=!0;break}}}return{...t,poly:e}});var s,i}_rszOpenings(){return this.host._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen,hosted:!!t.host,angle:t.angle,type:t.type}))}_rszObstacles(){const t=this.host._spaceModel();if(!t)return[];const e=[];for(const s of t.partitions||[])e.push({kind:"segment",a:[...s.a],b:[...s.b],half:$(s.cm,this.host._cellCm,this.host._gridPitch)/2});for(const s of t.room_drafts||[])for(let t=0;t+1Array.isArray(t.a)&&Array.isArray(t.b)&&t.a.length>=2&&t.b.length>=2).map(t=>({wall:t,a:[t.a[0]*$c,t.a[1]*this.host._spaceH],b:[t.b[0]*$c,t.b[1]*this.host._spaceH]})),o=Math.abs(t[0]-e[0])<=.05*this.host._gridPitch?"v":Math.abs(t[1]-e[1])<=.05*this.host._gridPitch?"h":null,a=i.filter(s=>!!o&&("h"===o?!(Math.abs(s.a[1]-t[1])>.05*this.host._gridPitch||Math.abs(s.b[1]-t[1])>.05*this.host._gridPitch)&&Math.min(Math.max(t[0],e[0]),Math.max(s.a[0],s.b[0]))-Math.max(Math.min(t[0],e[0]),Math.min(s.a[0],s.b[0]))>.05*this.host._gridPitch:!(Math.abs(s.a[0]-t[0])>.05*this.host._gridPitch||Math.abs(s.b[0]-t[0])>.05*this.host._gridPitch)&&Math.min(Math.max(t[1],e[1]),Math.max(s.a[1],s.b[1]))-Math.max(Math.min(t[1],e[1]),Math.min(s.a[1],s.b[1]))>.05*this.host._gridPitch)),n=new Set(a.map(t=>Number(t.wall.cm)).filter(t=>t>0));return{minDim:this.host._cmToUnits(30),eps:.05*this.host._gridPitch,step:this.host._gridPitch,movingHalf:s>0?$(s,this.host._cellCm,this.host._gridPitch)/2:0,obstacles:this._rszObstacles(),thicknessConflict:n.size>1}}_rszResolution(t,e,s){const i=this.host._resize.snapshotIdentity||s||this._rszSnapshot(),o=`${this.host._space}|${this.host._cellCm}|${this.host._gridPitch}|${i}`,a=`${t}:${e}`;return this.host._resize.resolve(o,a,()=>{const s=[...this.host._resize.rooms||this._rszRooms()],i=s.find(e=>e.id===t),o=i?.poly?.[e]||[0,0],a=i?.poly?.[(e+1)%(i?.poly?.length||1)]||[0,0];return function(t,e,s,i,o){const{eps:a}=o,n=t.find(t=>t.id===s);if(!n||i<0||i>=(n.poly?.length||0)||n.poly.length<4||!ka(n.poly))return{enabled:!1,reason:"invalid-geometry"};const r=n.poly[i],l=n.poly[(i+1)%n.poly.length],h=Da(r,l,a);if(!h)return{enabled:!1,reason:"diagonal"};if(!Ta(n.poly,i,h,a))return{enabled:!1,reason:"side-angle"};if(o.thicknessConflict)return{enabled:!1,reason:"thickness-conflict"};for(const t of o.obstacles||[])if(Aa(t,r,l,o))return{enabled:!1,reason:"duplicate-physical-wall"};const c=va(ga(l,r)),d=[],p=new Set;let u=!1,_=!1;for(const e of t)if(e.id!==s)for(let t=0;t1||d.length>1)return{enabled:!1,reason:"multiple-rooms"};const m={[s]:i},g=[s];if(1===d.length){const t=d[0];if(!ka(t.room.poly))return{enabled:!1,reason:"invalid-geometry"};if(!Ta(t.room.poly,t.edge,h,a))return{enabled:!1,reason:"side-angle"};g.push(t.room.id),m[t.room.id]=t.edge}const f=[];for(const t of e)if(!($a([t.x,t.y],r,l)>2*a)){if(t.hosted||t.length>c+2*a)return{enabled:!1,reason:"opening-conflict"};f.push(t.id)}const b=Object.fromEntries(g.map(e=>[e,t.find(t=>t.id===e).poly.length])),v=[];for(const e of g){const s=t.find(t=>t.id===e),i=m[e],o=(i-1+s.poly.length)%s.poly.length,n=(i+1)%s.poly.length,r=Ha(t,e,o,1,a),l=Ha(t,e,n,0,a);if(!r||!l)return{enabled:!1,reason:"partial-shared"};v.push(r,l)}const y={roomId:s,edge:i,a:[...r],b:[...l],n:wa(n.poly,i),roomIds:g,edgeByRoom:m,topology:b,movingOpeningIds:f,sideOwnership:v};if(!ja(t,e,y,0,o))return{enabled:!1,reason:"invalid-geometry"};const $=Math.abs(Number(o.step));if(Number.isFinite($)&&$>a){const s=[-$,$];if(!s.some(s=>ja(t,e,y,s,o))){if(!s.some(s=>Oa(Ba(t,e,y,s),y,a)))return{enabled:!1,reason:"partial-shared"};const i={...o,obstacles:[]};return s.some(s=>ja(t,e,y,s,i))?{enabled:!1,reason:"duplicate-physical-wall"}:e.length&&s.some(e=>ja(t,[],y,e,o))?{enabled:!1,reason:"opening-conflict"}:{enabled:!1,reason:"invalid-geometry"}}}return{enabled:!0,plan:y}}(s,[...this.host._resize.openings||this._rszOpenings()],t,e,this._rszOptsFor(o,a))})}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this.host._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszResetController(){const t=null!==this.host._resize.preview;this.host._resize.reset(),t&&this.host._cfgEpoch++}_rszProjectPreview(t,e,s,i,o){this.host._rszLimitViolation=null;const a=this.host._serverCfg?.spaces.find(t=>t.id===this.host._space);if(!a||!this.host._serverCfg)return{ok:!1,reason:"missing-context"};const n=JSON.parse(t),r={...a,rooms:n.rooms,openings:n.openings||[]};for(const t of["walls","wall_segments","open_spans","room_drafts","partitions","wall_columns","decor"])void 0!==n[t]?r[t]=n[t]:delete r[t];for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==n.plan_transform?.[t]?r[t]=n.plan_transform[t]:delete r[t];const l=this.host._spaceH;for(const[t,s]of Object.entries(e)){const e=r.rooms.find(e=>e.id===t);e&&(e.poly=s.map(t=>[t[0]/$c,t[1]/l]),delete e.x,delete e.y,delete e.w,delete e.h)}for(const[t,e]of Object.entries(s)){const s=(r.openings||[]).find(e=>e.id===t);s&&(s.x=e[0]/$c,s.y=e[1]/l)}const h=[],c=[];for(const t of i){const e=o.find(e=>e.id===t),s=r.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const i=s.poly.map(t=>[t[0]*$c,t[1]*l]);if(e.poly.length!==i.length)continue;const a=Array.isArray(e.wall_ids)?e.wall_ids:[];for(let t=0;tt.id===s):null;o&&(o.a=[i[t][0]/$c,i[t][1]/$c],o.b=[i[(t+1)%i.length][0]/$c,i[(t+1)%i.length][1]/$c])}}if(h.length&&Array.isArray(r.walls)&&r.walls.length){const t=Se(r.walls,h,c,this.host._wallKeyPitch,$c,"fixed-topology");if(t.rejected)return{ok:!1,reason:"wall-metadata"};r.walls=t.walls}const d=[];for(const t of r.rooms||[]){const e=W(t);if(e&&!(e.length<2))for(let t=0;tJSON.stringify([t?.key,t?.cm,t?.a,t?.b]),u=new Map;for(const t of n.walls||[]){const e=p(t);u.set(e,(u.get(e)||0)+1)}const _=[];for(const t of r.walls||[]){const e=p(t),s=u.get(e)||0;s?u.set(e,s-1):_.push(t)}if(Me(_,d,this.host._wallKeyPitch,$c,n.walls||[]).length)return{ok:!1,reason:"wall-metadata"};const m=function(t,e,s=1e-8){const i=Za(t),o=new Set(e),a=i.flatMap(t=>{if(!o.has(String(t.id||"")))return[];const e=sn(en(t));return e?[e]:[]});return i.flatMap(t=>{const e=String(t.id||""),i=sn(en(t)),n=!!i&&a.some(t=>i.minX<=t.maxX+s&&i.maxX+s>=t.minX&&i.minY<=t.maxY+s&&i.maxY+s>=t.minY);return e&&(o.has(e)||n)?[e]:[]})}(r.rooms||[],i),g=on(r,m);if(!g||!this._rszSpaceCandidateGeometry(this.host._space,g).ok)return{ok:!1,reason:"physical-geometry"};const f={...this.host._serverCfg,spaces:(this.host._serverCfg?.spaces||[]).map(t=>t?.id===this.host._space?r:t)};try{this._resizePreviewNodes=it(g.rooms,g.walls,[],E,this.host._cellCm,this.host._gridPitch,$c)}catch{this._resizePreviewNodes=null}let b;try{const t=new Set(i),e=this.host._junctionLimitViolations(f,this.host._space,{status:"lightweight",multiWallNodes:this._resizePreviewNodes},t);b=Dr(e,this._resizeBaselineLimits.filter(e=>"clearance"!==e.rule||t.has(e.subject)))}catch{b=[{rule:"check_failed",subject:this.host._space,actual:0,limit:0}]}return b.length?(this.host._rszLimitViolation=b[0],{ok:!1,reason:"junction-limit"}):{ok:!0,value:{preview:{space:this.host._space,sp:r},beforeWalls:n.walls||[],afterWalls:r.walls||[],artifact:null}}}_rszAcceptPreview(t,e){if(this.host._cfgEpoch++,this.host._physicalBodiesCache&&(this.host._physicalBodiesCache.key=`${this.host._space}|${this.host._cfgEpoch}|${this.host._cellCm}|${this.host._gridPitch}`),!t||!e)return;const s=De(e);if(!s)return;const i=`${this.host._space}|${this.host._cfgEpoch}|${t.sp.rooms.length}`;Object.defineProperty(s,"sourceFingerprint",{value:d([t.sp,this.host._cellCm,this.host._gridPitch]),enumerable:!1});const o={key:i,value:s};yc(this.host._wallUnionPool,i,o,8),this.host._wallUnionCache=o}_rszSpaceCandidateGeometry(t,e){if(!this.host._serverCfg)return{ok:!1,wallGeometry:null};const s={...this.host._serverCfg,spaces:this.host._serverCfg.spaces.map(s=>s.id===t?e:s)};let i=null;try{return{ok:this.host._checkSpacePhysicalGeometry(s,t,t=>{i=t}).ok,wallGeometry:i}}catch{return{ok:!1,wallGeometry:null}}}_rszSpaceCandidateRenderable(t,e){if(!this.host._serverCfg)return!1;try{const s={...this.host._serverCfg,spaces:this.host._serverCfg.spaces.map(s=>s.id===t?e:s)};return this.host._checkSpacePhysicalGeometry(s,t).ok}catch{return!1}}_rszCandidateRenderable(t){return!!t&&t.space===this.host._space&&this._rszSpaceCandidateRenderable(t.space,t.sp)}_rszEdgeDown(t,e,s){if("resize"!==this.host._tool||this.host._resize.dragging)return;this._resizeBaseFrameStable=!0,t.stopPropagation(),t.preventDefault();const i=this._rszRooms(),o=this._rszResolution(e,s);if(!o.enabled)return void this.host._showToast(this._rszReasonText(o.reason));kc(t);const a=o.plan;try{this._resizeBaselineLimits=this.host._junctionLimitViolations(this.host._serverCfg,this.host._space,null,new Set(a.roomIds))}catch{this._resizeBaselineLimits=[]}const n=this._svgPoint(t),r=`${this.host._space}|${this.host._cfgEpoch}|${i.length}`,l=this.host._wallUnionCache?.key===r?this.host._wallUnionCache.value:null,h=this._rszSnapshot();this.host._resize.begin({pointerId:t.pointerId,start:[n[0],n[1]],roomId:e,plan:a,options:this._rszOptsFor(a.a,a.b),rooms:i,openings:this._rszOpenings(),snapshotIdentity:h,before:JSON.parse(h),wallUnionBefore:l,epochBefore:this.host._cfgEpoch})}_rszReasonText(t){return this.host._t(`resize.disabled.${t}`)}_rszDisabledActivate(t,e){t.stopPropagation(),t.preventDefault(),this.host._showToast(this._rszReasonText(e))}_rszDisabledKey(t,e){"Enter"!==t.key&&" "!==t.key||this._rszDisabledActivate(t,e)}_rszMove(t){this.host._resize.ownsPointer(t.pointerId)&&(t.stopPropagation(),Io(this.host,"resize",()=>this._rszMoveNow(t)))}_rszMoveNow(t){if(!this.host._resize.ownsPointer(t.pointerId))return;t.stopPropagation();const e=this._svgPoint(t),s=this.host._resize.move({pointerId:t.pointerId,point:[e[0],e[1]],step:this.host._gridPitch,snap:t=>{const e=this._snap(t);return[e[0],e[1]]},project:(t,e,s,i,o)=>this._rszProjectPreview(t,e,s,i,o),publish:(t,e)=>this._rszAcceptPreview(t,e),measure:(t,e)=>this._rszEdgeLabels(t,e)});if("rejected"===s.kind)return s.notify&&this.host._showToast(this.host._rszLimitViolation?`${this.host._t("resize.limit_stopped")} — `+this._junctionLimitLabel(this.host._rszLimitViolation):this.host._t("resize.preview_failed")),void this.host.requestUpdate();"accepted"===s.kind&&this.host.requestUpdate()}_rszUp(t){if(To(this.host,"resize"),!this.host._resize.ownsPointer(t.pointerId))return;t.stopPropagation();const e=this.host._resize.finish({pointerId:t.pointerId,currentSnapshotIdentity:this._rszSnapshot(),validatePreview:t=>this._rszCandidateRenderable(t)});if("no-op"===e.kind)return this.host._cfgEpoch++,void this.host.requestUpdate();if("rejected"===e.kind)return this.host._cfgEpoch++,this.host._showToast(this.host._t("resize.commit_failed")),void this.host.requestUpdate();const s=e.preview,i=this.host._serverCfg?.spaces.find(t=>t.id===s.space);i&&(i.rooms=s.sp.rooms,i.openings=s.sp.openings,Array.isArray(s.sp.walls)&&(s.sp.walls.length?i.walls=s.sp.walls:delete i.walls),Array.isArray(s.sp.wall_segments)&&(i.wall_segments=s.sp.wall_segments)),this.host._suppressClick=!0,setTimeout(()=>this.host._suppressClick=!1,0),this._commitPhysicalGeometry(this.host._t("history.resize_room"),e.before),this.host.requestUpdate()}_rszCancelDrag(t){zo(this.host,"resize");const e=this.host._resize.cancel(this._rszSnapshot(),t);if("no-op"!==e.kind){if(null!==e.restoreEpoch?this.host._cfgEpoch=e.restoreEpoch:this.host._cfgEpoch++,this.host._physicalBodiesCache&&(this.host._physicalBodiesCache.key=`${this.host._space}|${this.host._cfgEpoch}|${this.host._cellCm}|${this.host._gridPitch}`),e.restoreWallUnion){const t=this.host._spaceModel();if(t){const s=`${this.host._space}|${this.host._cfgEpoch}|${t.rooms.length}`,i={key:s,value:e.restoreWallUnion};yc(this.host._wallUnionPool,s,i,8),this.host._wallUnionCache=i}}null!==e.restoreEpoch&&"plan"===this.host._mode&&this._resizeBaseFrameStable&&(this.host._terminalFrame=1),this.host.requestUpdate()}}_rszPointerCancel(t){this.host._resize.ownsPointer(t.pointerId)&&(t.stopPropagation(),this._rszCancelDrag(t.pointerId))}_rszEdgeLabels(t,e,s=this.host._resize.rooms){const i=s,o=[],a=t.polys[e.roomId]||i?.find(t=>t.id===e.roomId).poly;if(!a||!i)return o;const n=a.length,r=this._rszInnerSpanCms(e.roomId,a,t.polys);for(const t of function(t,e){const s=t.length;return[(e-1+s)%s,(e+1)%s]}(a,e.edge)){const e=a[t],s=a[(t+1)%n],i=r?.[t];o.push({kind:"length",x:(e[0]+s[0])/2,y:(e[1]+s[1])/2,text:null==i?this.host._fmtLen(e,s):Ce(i,"mi"===this.host.hass?.config?.unit_system?.length),edge:{a:[e[0],e[1]],b:[s[0],s[1]]}})}const l="mi"===this.host.hass?.config?.unit_system?.length,h=e.roomIds,c=this.host._spaceWalls,d=this.host._physicalBodiesR(),p=this.host._baseVb(),u=this.host._view&&this.host._view.w>0&&this.host._view.h>0?this.host._view:{x:p[0],y:p[1],w:p[2],h:p[3]},[_,m]=this.host._lastValidStageSize||[u.w,u.h],g={...u,stageWidth:Math.max(1,_),stageHeight:Math.max(1,m)},f=this.host._spaceModel(),b=this.host._config?.icon_size??2.5,v=f?Pe(b>8?2.5:b,f,u.w,this.host._kiosk?this.host._kioskScale.icon:1)*g.stageWidth/100:24,y=Math.max(10,.77*v),$=this.host._t("room.settings_short"),w=y*(1.457+.66*Math.max(1,$.length)*.42);for(const s of h){const a=t.polys[s]||i.find(t=>t.id===s).poly,n=c.length&&f&&at(f.rooms,s,c,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,$c,null,this._resizePreviewNodes)||a,r=d.length?Ie(Te(n,d))*Math.pow(this.host._cellCm/this.host._gridPitch,2)/1e4:ze(n,this.host._gridPitch,this.host._cellCm),h=Re(r,l),p=tr({poly:a,edge:e.edgeByRoom[s],text:h,view:g,gearCenter:Ae(a),gearWidthPx:w,gearHeightPx:y});o.push({kind:"area",roomId:s,x:p.anchor[0],y:p.anchor[1],text:h,placement:p})}return o}_rszInnerSpanCms(t,e,s){const i=Object.keys(s).length?Object.entries(s).map(([t,e])=>({id:t,poly:e})):this.host._spaceModel()?.rooms;if(!i?.length)return null;const o=this.host._spaceWalls;if(!o.length)return null;const a=this.host._openCuts(),n=Fe(i,t,o,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,$c);if(!n||n.length!==e.length)return null;const r=this.host._cellCm/this.host._gridPitch;return e.map((t,s)=>Ne(e,s,n)*r)}_renderResizeMeasurements(){const t=this.host._resize.liveLabels;if(!t?.length)return l;const e=t.filter(t=>"length"===t.kind),s=t.filter(t=>"area"===t.kind);return _`
  • `}_discoveryFilterState(t){const e=this.host._settings,s=void 0!==t.draftGroupLights?t.draftGroupLights:!1!==e.group_lights,i=e.exclude_integrations,o=void 0!==t.draftExcluded?null===t.draftExcluded?[...wi]:t.draftExcluded:i?[...i]:[...wi],a=void 0!==t.draftExcluded?null===t.draftExcluded:!i,n=void 0!==t.draftGroupLights||void 0!==t.draftExcluded;return{groupLights:s,excluded:o.sort(),usesProductList:a,dirty:n}}_registryIntegrations(){const t=new Set,e=this.host._fullRegistryHass;for(const s of Object.values(e?.entities||{}))s?.platform&&t.add(String(s.platform));for(const s of Object.values(e?.devices||{})){const e=s?.identifiers?.[0],i=Array.isArray(e)?e[0]:null;i&&t.add(String(i))}return[...t].sort()}_discoveryFilterPreview(t){const e=this._discoveryFilterState(t),s=[e.groupLights?1:0,e.usesProductList?"p":e.excluded.join(","),this.host._cfgEpoch,this.host._regSignature].join("|");if(this._discoveryPreviewMemo?.key===s)return this._discoveryPreviewMemo.value;const i={hass:this.host.hass,registry:this.host._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this.host._areaToSpace).map(([t,e])=>[t,e.space])),markers:this.host._markers,showAll:this.host._showAll,firstSpaceId:this.host._model[0]?.id||"",loc:t=>this.host._t(t),iconRules:this.host._iconRules},o=(t,e)=>new Set(Xi({...i,settings:t,excluded:e})),a=(t,e)=>new Set(Zi({...i,settings:t,excluded:e}).map(t=>t.bindingRef||t.id)),n=ki(this.host._settings),r={...this.host._settings,group_lights:e.groupLights},l=new Set(e.excluded),h=o(this.host._settings,n),c=o(r,l),d=a(this.host._settings,n),p=a(r,l);let u=0,_=0,m=0;const g=t=>t.includes("light.");for(const t of h)c.has(t)||(u++,g(t)&&m++);for(const t of c)h.has(t)||(_++,g(t)&&m++);for(const t of p)d.has(t)||(u++,g(t)&&m++);for(const t of d)p.has(t)||(_++,g(t)&&m++);const f={appear:u,hide:_,lights:m};return this._discoveryPreviewMemo={key:s,value:f},f}async _saveDiscoveryFilters(t){const e=this.host._serverCfg;if(!e)return;const s=this._discoveryFilterState(t),i={...e.settings};s.groupLights?delete i.group_lights:i.group_lights=!1,s.usesProductList?delete i.exclude_integrations:i.exclude_integrations=s.excluded,this.host._serverCfg={...e,settings:i},this.host._deviceInboxMemo=null,this._discoveryPreviewMemo=null,this.host._regSignature="",this.host._deviceInbox&&(this.host._deviceInbox={...t,draftGroupLights:void 0,draftExcluded:void 0}),this._saveConfig(),this.host._maybeRebuildDevices(),this.host.requestUpdate()}_renderDiscoveryFilters(t){const e=this._discoveryFilterState(t),s=e=>this.host._deviceInbox={...t,...e},i=t.filtersOpen&&e.dirty?this._discoveryFilterPreview(t):null,o=this._registryIntegrations().filter(t=>!e.excluded.includes(t));return h`
    `}_discoveryFilterState(t){const e=this.host._settings,s=void 0!==t.draftGroupLights?t.draftGroupLights:!1!==e.group_lights,i=e.exclude_integrations,o=void 0!==t.draftExcluded?null===t.draftExcluded?[...ki]:t.draftExcluded:i?[...i]:[...ki],a=void 0!==t.draftExcluded?null===t.draftExcluded:!i,n=void 0!==t.draftGroupLights||void 0!==t.draftExcluded;return{groupLights:s,excluded:o.sort(),usesProductList:a,dirty:n}}_registryIntegrations(){const t=new Set,e=this.host._fullRegistryHass;for(const s of Object.values(e?.entities||{}))s?.platform&&t.add(String(s.platform));for(const s of Object.values(e?.devices||{})){const e=s?.identifiers?.[0],i=Array.isArray(e)?e[0]:null;i&&t.add(String(i))}return[...t].sort()}_discoveryFilterPreview(t){const e=this._discoveryFilterState(t),s=[e.groupLights?1:0,e.usesProductList?"p":e.excluded.join(","),this.host._cfgEpoch,this.host._regSignature].join("|");if(this._discoveryPreviewMemo?.key===s)return this._discoveryPreviewMemo.value;const i={hass:this.host.hass,registry:this.host._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this.host._areaToSpace).map(([t,e])=>[t,e.space])),markers:this.host._markers,showAll:this.host._showAll,firstSpaceId:this.host._model[0]?.id||"",loc:t=>this.host._t(t),iconRules:this.host._iconRules},o=(t,e)=>new Set(Zi({...i,settings:t,excluded:e})),a=(t,e)=>new Set(Qi({...i,settings:t,excluded:e}).map(t=>t.bindingRef||t.id)),n=xi(this.host._settings),r={...this.host._settings,group_lights:e.groupLights},l=new Set(e.excluded),h=o(this.host._settings,n),c=o(r,l),d=a(this.host._settings,n),p=a(r,l);let u=0,_=0,m=0;const g=t=>t.includes("light.");for(const t of h)c.has(t)||(u++,g(t)&&m++);for(const t of c)h.has(t)||(_++,g(t)&&m++);for(const t of p)d.has(t)||(u++,g(t)&&m++);for(const t of d)p.has(t)||(_++,g(t)&&m++);const f={appear:u,hide:_,lights:m};return this._discoveryPreviewMemo={key:s,value:f},f}async _saveDiscoveryFilters(t){const e=this.host._serverCfg;if(!e)return;const s=this._discoveryFilterState(t),i={...e.settings};s.groupLights?delete i.group_lights:i.group_lights=!1,s.usesProductList?delete i.exclude_integrations:i.exclude_integrations=s.excluded,this.host._serverCfg={...e,settings:i},this.host._deviceInboxMemo=null,this._discoveryPreviewMemo=null,this.host._regSignature="",this.host._deviceInbox&&(this.host._deviceInbox={...t,draftGroupLights:void 0,draftExcluded:void 0}),this._saveConfig(),this.host._maybeRebuildDevices(),this.host.requestUpdate()}_renderDiscoveryFilters(t){const e=this._discoveryFilterState(t),s=e=>this.host._deviceInbox={...t,...e},i=t.filtersOpen&&e.dirty?this._discoveryFilterPreview(t):null,o=this._registryIntegrations().filter(t=>!e.excluded.includes(t));return h`
    s({filtersOpen:t.target.open})}> ${this.host._t("device_inbox.filters_title")}
    - `}_markerValueBadgeFields(t){return xi({touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition})}_markerValueSourceFields(t){return Si({touched:t.valueSourceTouched,originalHas:t.originalHasValueSource,original:t.originalValueSource,source:t.valueSource})}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=Ps(t.room),s=$s(t.binding,t.devId,()=>"__hp_device_preview__"),i=this.host._markers.find(e=>e.id===s||e.id===t.devId),o=Ss(t.binding,t.controls,this.host._bindingEntities(t.binding)),a=this._effectiveStoredTapAction(t),n={id:s,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===a&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:o.length?o:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),...this._markerValueSourceFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=ao(t.glowRadius);return null==e||e<=0?null:Math.round(this.host._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:t.hideFromPlan,vacuum:i?.vacuum||null},r=!!i&&("string"==typeof i.area&&i.area.length>0||null===i.area&&!!i.space&&!!i.room_id);return"virtual"===t.binding||t.roomTouched?(n.space=e?.space||("virtual"===t.binding?this.host._space:null),n.area=e?.area||null,n.room_id=e?.roomId||null):r&&(n.space=i.space,n.area=i.area,n.room_id=i.room_id),n}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const s=`${this.host._haRegistry.revision}\n${d(this.host._markers)}\n${JSON.stringify(e)}`;if(this.host._markerPreviewMemo?.key===s)return this.host._markerPreviewMemo.device;const i=Mi({hass:this.host.hass,registry:this.host._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this.host._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,siblingMarkers:this.host._markers,settings:this.host._settings,excluded:this.host._excluded,showAll:this.host._showAll,firstSpaceId:this.host._model[0]?.id||this.host._space,loc:t=>this.host._t(t),iconRules:this.host._iconRules});return this.host._markerPreviewMemo={key:s,device:i},i}_markerPreviewDevices(t){const e=this.host._markerPreviewDevicesMemo;if(e?.base===this.host._devices&&e.preview===t)return e.devices;const s=[...this.host._devices.filter(e=>e.id!==t.id),t];return this.host._markerPreviewDevicesMemo={base:this.host._devices,preview:t,devices:s},s}_toggleIntent(t,e=this.host._devices){return this.host._toggleIntent(t,e)}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const s=this._markerPreviewDevices(e);return this._toggleIntent(e,s)}_toggleStateText(t,e){return this.host._toggleStateText(t,e)}_toggleConfirmationStateText(t){return this.host._toggleConfirmationStateText(t)}_toggleConfirmationLines(t){return this.host._toggleConfirmationLines(t)}_toggleHintLines(t){if(!t)return[];const e=t=>this.host._t(`marker.toggle_effect_${t.replace("-","_")}`),s=t=>this.host._t(`marker.toggle_skip_${t.replace("-","_")}`);return Di(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this.host._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),s=t.name||e;return this.host._t("marker.toggle_hint_single",{name:s,id:e})},group:t=>this.host._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,s)=>"virtual-light"===t.via?this.host._t("marker.virtual_light_current",{state:this.host._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(s)}):this.host._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(s)}),groupCurrentNext:(t,s)=>this.host._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(s)}),skipped:t=>this.host._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${s(t.reason)})`}).join(", ")}),none:t=>this.host._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:Ms(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),s=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},i="toggle"===s.tapAction?this._toggleHintLines(this._toggleIntentForDialog(s)).join(" "):"";return{...s,tapHintAnnouncement:i}}_valueBadgeForBinding(t,e){const s={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},i=this._markerPreviewDevice(s);if(!i)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const o=[...this.host._devices.filter(t=>t.id!==i.id),i],a=ks(this.host._planHass,i,o),n=xs(this.host._planHass,i,a);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!n,valueBadgeSource:n,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const s={...e,hidden:!1};return Ci(Pi(this.host._planHass,[...this.host._devices.filter(t=>t.id!==s.id),s],null,this.host._virtualLights).filter(t=>t.device.id===s.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},s=this._markerPreviewDevice(e);return!!s&&Ii(this.host._planHass,{...s})}_setMarkerLightRole(t){const e=this.host._markerDialog;e&&(this.host._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.host.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this.host._planEntityAvailable(t)};const e=t.slice(7),s=this.host._markers.find(t=>t.id===e),i=this.host._devices.find(t=>t.id===e);if(!s||s.removed||!0!==s.is_light)return{label:this.host._t("marker.control_missing_label"),sub:`${this.host._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const o=this.host._serverCfg?.spaces.find(t=>t.id===(i?.space||s.space)),a=!!i&&Ti(i).length>0;return{label:s.name||i?.name||e,sub:[o?.title||i?.space||s.space,s.room_id||i?.area,a?"":this.host._t("marker.control_passive")].filter(Boolean).join(" · "),icon:s.icon||i?.icon||"mdi:lightbulb-outline",warning:!0===s.hidden||!0===i?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this.host._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this.host._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this.host._t("marker.value_badge_state",{name:t.label});const s=this.host.hass.states[e.entity_id]?.attributes?.friendly_name||this.host._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this.host._t(`marker.value_badge_attr_${e.attribute}`,{name:s})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",s=[],i=new Set;for(const t of this.host._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this.host._bindingStatus(t.binding).kind)continue;const o=this.host._devices.find(e=>e.id===t.id);if(!o||o.hidden)continue;const a=this._controlRefInfo(`marker:${t.id}`);for(const t of Ti(o))i.add(t);s.push({value:`marker:${t.id}`,label:a.label,sub:a.sub,icon:a.icon,search:`${a.label} ${a.sub} ${t.id} ${Ti(o).join(" ")}`.toLowerCase()})}const o=Object.keys(this.host.hass.states||{}).filter(e=>zi(e)&&!i.has(e)&&Ri(t.binding,[e],this.host._bindingEntities(t.binding)).length>0&&this.host._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),a=t.controlsFilter.trim().toLowerCase();return[...s,...o].filter(e=>!t.controls.includes(e.value)&&(!a||e.search.includes(a))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const s=this._markerDraft(t)?.id||t.devId||"";if(!s)return void this.host._showToast(this.host._t("toast.marker_binding_required"));const i=e.slice(7),o=this._markerDraft(t),a=o?[...this.host._markers.filter(t=>t.id!==s),o]:this.host._markers;if(Ai(a,s,i))return void this.host._showToast(this.host._t("toast.marker_control_cycle"))}this.host._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this.host._markerDialog;if(!e)return;if("auto"===t)return void(this.host._markerDialog={...e,glowMode:t,glowTouched:!0});const s=this._markerSpatialSource(e),i=Fi(s?this.host._planHass.states[s.eid]:void 0,null,this.host._fillColors.glow_light.c),o=!e.glowColorDrafted,a="fixed"===t&&!e.glowBrightnessDrafted;this.host._markerDialog={...e,glowMode:t,glowColor:o?i.c:e.glowColor,glowBrightness:a?Math.max(1,Math.round(100*i.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this.host._markerDialog,e="virtual"===t.bindingMode,s=this._bindingCandidates();this.host._bindingEntities(t.binding);const i=e?null:this.host._bindingStatus(t.binding),o=!e&&this.host._bindingHasHaPage(t.binding),a=this._markerPreviewDevice(t),n=this._effectiveMarkerTapAction(t,a),r=a?Ns(this.host._serverCfg?.spaces.find(t=>t.id===a.space)):null,c=a?this._markerPreviewDevices(a):this.host._devices,d="toggle"===n&&a?this._toggleIntent(a,c):null,p=this._toggleHintLines(d),u=a?Ni(this.host._planHass,a,{liveStates:!1!==this.host._config?.live_states,showTemperature:!1!==this.host._config?.show_temperature,showSignal:r?.showLqi??!1!==this.host._config?.show_signal,designPreview:!0,activityRuntime:this.host._activityRt.get(a.id),lightDevices:c,registryHass:this.host._fullRegistryHass,reducedMotion:this.host._reducedMotion}):null,_=a?ks(this.host._planHass,a,c):[],m=a?xs(this.host._planHass,a,_):null,g=t.valueBadgeTouched?t.valueBadgeEnabled:!!u?.valueBadge,f=t.valueBadgeTouched?t.valueBadgeSource:u?.valueBadge?.source||t.valueBadgeSource,b=t.valueBadgeTouched?t.valueBadgePosition:u?.valueBadge?.position||t.valueBadgePosition,v=Hi(f),y=!!f&&!_.some(t=>t.key===v),$=_.find(t=>t.key===v),w=Hi(t.valueSource),k=!(!t.valueSource||w&&_.some(t=>t.key===w)),x=_.find(t=>t.key===w),S=u?.valueSource?.sourceKey||"",M=this._markerAutoHasSpatialSource(t),D=!!a&&Li(this.host._planHass,{...a}),C=Ei(t.lightRole,M,D,t.glowMode),P=!C.sourceExists,I=!C.fromSourceEnabled,T=C.passive,z=C.effectiveMode,R="never"===t.lightRole?this.host._t("marker.glow_disabled_never"):"auto"!==t.lightRole||M?T?this.host._t("marker.glow_passive_hint"):this.host._t("marker.glow_disabled_no_entity"):this.host._t("marker.glow_disabled_auto"),A=a?Ti(a):[],F=a&&Oi(a)||"",N=!!t.lightEntity&&!A.includes(t.lightEntity),H=a?Bi(a):[],L=!!t.toggleEntity&&!H.includes(t.toggleEntity),E="toggle"===n?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,O=E?[...E.targets,...E.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",B=(()=>{if(e)return null;const i=s.find(e=>e.value===t.binding);if(i)return i.label;const[o,a]=t.binding.split(":");return"device"===o?this.host._fullRegistryHass.devices[a]?.name_by_user||this.host._fullRegistryHass.devices[a]?.name||a:this.host._fullRegistryHass.entities[a]?.name||this.host.hass.states[a]?.attributes?.friendly_name||a})();return h``}_markerValueBadgeFields(t){return Si({touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition})}_markerValueSourceFields(t){return Mi({touched:t.valueSourceTouched,originalHas:t.originalHasValueSource,original:t.originalValueSource,source:t.valueSource})}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=Is(t.room),s=ws(t.binding,t.devId,()=>"__hp_device_preview__"),i=this.host._markers.find(e=>e.id===s||e.id===t.devId),o=Ms(t.binding,t.controls,this.host._bindingEntities(t.binding)),a=this._effectiveStoredTapAction(t),n={id:s,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===a&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:o.length?o:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),...this._markerValueSourceFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=ro(t.glowRadius);return null==e||e<=0?null:Math.round(this.host._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:t.hideFromPlan,vacuum:i?.vacuum||null},r=!!i&&("string"==typeof i.area&&i.area.length>0||null===i.area&&!!i.space&&!!i.room_id);return"virtual"===t.binding||t.roomTouched?(n.space=e?.space||("virtual"===t.binding?this.host._space:null),n.area=e?.area||null,n.room_id=e?.roomId||null):r&&(n.space=i.space,n.area=i.area,n.room_id=i.room_id),n}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const s=`${this.host._haRegistry.revision}\n${d(this.host._markers)}\n${JSON.stringify(e)}`;if(this.host._markerPreviewMemo?.key===s)return this.host._markerPreviewMemo.device;const i=Di({hass:this.host.hass,registry:this.host._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this.host._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,siblingMarkers:this.host._markers,settings:this.host._settings,excluded:this.host._excluded,showAll:this.host._showAll,firstSpaceId:this.host._model[0]?.id||this.host._space,loc:t=>this.host._t(t),iconRules:this.host._iconRules});return this.host._markerPreviewMemo={key:s,device:i},i}_markerPreviewDevices(t){const e=this.host._markerPreviewDevicesMemo;if(e?.base===this.host._devices&&e.preview===t)return e.devices;const s=[...this.host._devices.filter(e=>e.id!==t.id),t];return this.host._markerPreviewDevicesMemo={base:this.host._devices,preview:t,devices:s},s}_toggleIntent(t,e=this.host._devices){return this.host._toggleIntent(t,e)}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const s=this._markerPreviewDevices(e);return this._toggleIntent(e,s)}_toggleStateText(t,e){return this.host._toggleStateText(t,e)}_toggleConfirmationStateText(t){return this.host._toggleConfirmationStateText(t)}_toggleConfirmationLines(t){return this.host._toggleConfirmationLines(t)}_toggleHintLines(t){if(!t)return[];const e=t=>this.host._t(`marker.toggle_effect_${t.replace("-","_")}`),s=t=>this.host._t(`marker.toggle_skip_${t.replace("-","_")}`);return Ci(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this.host._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),s=t.name||e;return this.host._t("marker.toggle_hint_single",{name:s,id:e})},group:t=>this.host._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,s)=>"virtual-light"===t.via?this.host._t("marker.virtual_light_current",{state:this.host._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(s)}):this.host._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(s)}),groupCurrentNext:(t,s)=>this.host._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(s)}),skipped:t=>this.host._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${s(t.reason)})`}).join(", ")}),none:t=>this.host._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:Ds(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),s=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},i="toggle"===s.tapAction?this._toggleHintLines(this._toggleIntentForDialog(s)).join(" "):"";return{...s,tapHintAnnouncement:i}}_valueBadgeForBinding(t,e){const s={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},i=this._markerPreviewDevice(s);if(!i)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const o=[...this.host._devices.filter(t=>t.id!==i.id),i],a=xs(this.host._planHass,i,o),n=Ss(this.host._planHass,i,a);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!n,valueBadgeSource:n,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const s={...e,hidden:!1};return Pi(Ii(this.host._planHass,[...this.host._devices.filter(t=>t.id!==s.id),s],null,this.host._virtualLights).filter(t=>t.device.id===s.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},s=this._markerPreviewDevice(e);return!!s&&Ti(this.host._planHass,{...s})}_setMarkerLightRole(t){const e=this.host._markerDialog;e&&(this.host._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.host.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this.host._planEntityAvailable(t)};const e=t.slice(7),s=this.host._markers.find(t=>t.id===e),i=this.host._devices.find(t=>t.id===e);if(!s||s.removed||!0!==s.is_light)return{label:this.host._t("marker.control_missing_label"),sub:`${this.host._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const o=this.host._serverCfg?.spaces.find(t=>t.id===(i?.space||s.space)),a=!!i&&zi(i).length>0;return{label:s.name||i?.name||e,sub:[o?.title||i?.space||s.space,s.room_id||i?.area,a?"":this.host._t("marker.control_passive")].filter(Boolean).join(" · "),icon:s.icon||i?.icon||"mdi:lightbulb-outline",warning:!0===s.hidden||!0===i?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this.host._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this.host._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this.host._t("marker.value_badge_state",{name:t.label});const s=this.host.hass.states[e.entity_id]?.attributes?.friendly_name||this.host._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this.host._t(`marker.value_badge_attr_${e.attribute}`,{name:s})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",s=[],i=new Set;for(const t of this.host._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this.host._bindingStatus(t.binding).kind)continue;const o=this.host._devices.find(e=>e.id===t.id);if(!o||o.hidden)continue;const a=this._controlRefInfo(`marker:${t.id}`);for(const t of zi(o))i.add(t);s.push({value:`marker:${t.id}`,label:a.label,sub:a.sub,icon:a.icon,search:`${a.label} ${a.sub} ${t.id} ${zi(o).join(" ")}`.toLowerCase()})}const o=Object.keys(this.host.hass.states||{}).filter(e=>Ri(e)&&!i.has(e)&&Ai(t.binding,[e],this.host._bindingEntities(t.binding)).length>0&&this.host._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),a=t.controlsFilter.trim().toLowerCase();return[...s,...o].filter(e=>!t.controls.includes(e.value)&&(!a||e.search.includes(a))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const s=this._markerDraft(t)?.id||t.devId||"";if(!s)return void this.host._showToast(this.host._t("toast.marker_binding_required"));const i=e.slice(7),o=this._markerDraft(t),a=o?[...this.host._markers.filter(t=>t.id!==s),o]:this.host._markers;if(Fi(a,s,i))return void this.host._showToast(this.host._t("toast.marker_control_cycle"))}this.host._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this.host._markerDialog;if(!e)return;if("auto"===t)return void(this.host._markerDialog={...e,glowMode:t,glowTouched:!0});const s=this._markerSpatialSource(e),i=Ni(s?this.host._planHass.states[s.eid]:void 0,null,this.host._fillColors.glow_light.c),o=!e.glowColorDrafted,a="fixed"===t&&!e.glowBrightnessDrafted;this.host._markerDialog={...e,glowMode:t,glowColor:o?i.c:e.glowColor,glowBrightness:a?Math.max(1,Math.round(100*i.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this.host._markerDialog,e="virtual"===t.bindingMode,s=this._bindingCandidates();this.host._bindingEntities(t.binding);const i=e?null:this.host._bindingStatus(t.binding),o=!e&&this.host._bindingHasHaPage(t.binding),a=this._markerPreviewDevice(t),n=this._effectiveMarkerTapAction(t,a),r=a?Hs(this.host._serverCfg?.spaces.find(t=>t.id===a.space)):null,c=a?this._markerPreviewDevices(a):this.host._devices,d="toggle"===n&&a?this._toggleIntent(a,c):null,p=this._toggleHintLines(d),u=a?Hi(this.host._planHass,a,{liveStates:!1!==this.host._config?.live_states,showTemperature:!1!==this.host._config?.show_temperature,showSignal:r?.showLqi??!1!==this.host._config?.show_signal,designPreview:!0,activityRuntime:this.host._activityRt.get(a.id),lightDevices:c,registryHass:this.host._fullRegistryHass,reducedMotion:this.host._reducedMotion}):null,_=a?xs(this.host._planHass,a,c):[],m=a?Ss(this.host._planHass,a,_):null,g=t.valueBadgeTouched?t.valueBadgeEnabled:!!u?.valueBadge,f=t.valueBadgeTouched?t.valueBadgeSource:u?.valueBadge?.source||t.valueBadgeSource,b=t.valueBadgeTouched?t.valueBadgePosition:u?.valueBadge?.position||t.valueBadgePosition,v=Li(f),y=!!f&&!_.some(t=>t.key===v),$=_.find(t=>t.key===v),w=Li(t.valueSource),k=!(!t.valueSource||w&&_.some(t=>t.key===w)),x=_.find(t=>t.key===w),S=u?.valueSource?.sourceKey||"",M=this._markerAutoHasSpatialSource(t),D=!!a&&Ei(this.host._planHass,{...a}),C=Oi(t.lightRole,M,D,t.glowMode),P=!C.sourceExists,I=!C.fromSourceEnabled,T=C.passive,z=C.effectiveMode,R="never"===t.lightRole?this.host._t("marker.glow_disabled_never"):"auto"!==t.lightRole||M?T?this.host._t("marker.glow_passive_hint"):this.host._t("marker.glow_disabled_no_entity"):this.host._t("marker.glow_disabled_auto"),A=a?zi(a):[],F=a&&Bi(a)||"",N=!!t.lightEntity&&!A.includes(t.lightEntity),H=a?Wi(a):[],L=!!t.toggleEntity&&!H.includes(t.toggleEntity),E="toggle"===n?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,O=E?[...E.targets,...E.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",B=(()=>{if(e)return null;const i=s.find(e=>e.value===t.binding);if(i)return i.label;const[o,a]=t.binding.split(":");return"device"===o?this.host._fullRegistryHass.devices[a]?.name_by_user||this.host._fullRegistryHass.devices[a]?.name||a:this.host._fullRegistryHass.entities[a]?.name||this.host.hass.states[a]?.attributes?.friendly_name||a})();return h`this._closeMarkerDialog()}>
    @@ -2272,7 +2272,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    @@ -2297,7 +2297,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e @input=${e=>this.host._markerDialog={...t,bindingFilter:e.target.value}} />
    ${s.map(e=>h`
    {if(e.value===t.binding)return void(this.host._markerDialog={...t,bindingOpen:!1});const s={...t,binding:e.value,bindingOpen:!1,controls:Ss(e.value,t.controls,this.host._bindingEntities(e.value)),autoIcon:this.host._autoIconForBinding(e.value)};this.host._markerDialog=this._announceToggleDraft({...s,...this._valueBadgeForBinding(s,e.value),valueSource:null,valueSourceTouched:!0})}}> + @click=${()=>{if(e.value===t.binding)return void(this.host._markerDialog={...t,bindingOpen:!1});const s={...t,binding:e.value,bindingOpen:!1,controls:Ms(e.value,t.controls,this.host._bindingEntities(e.value)),autoIcon:this.host._autoIconForBinding(e.value)};this.host._markerDialog=this._announceToggleDraft({...s,...this._valueBadgeForBinding(s,e.value),valueSource:null,valueSourceTouched:!0})}}> ${e.label}${e.sub}
    `)} ${s.length?l:h`
    ${this.host._t("marker.nothing_found")}
    `} @@ -2320,7 +2320,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e @@ -2495,19 +2495,19 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e -

    ${this.host._t(fc[t.display])}

    +

    ${this.host._t($c[t.display])}

    ${"value"===t.display?h`
    ${this._help("marker.value_source.help")}
    this.host._markerDialog={...t,valueBadgeSource:ji(e.target.value),valueBadgeEnabled:!0,valueBadgeTouched:!0}}> + @change=${e=>this.host._markerDialog={...t,valueBadgeSource:qi(e.target.value),valueBadgeEnabled:!0,valueBadgeTouched:!0}}> ${y?h``:l} @@ -2629,7 +2629,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    ${t.pdfs.map(t=>h` - ${t.name} + ${t.name} this._removeMarkerPdf(t.url)}>`)}
    this.host._spaceDialog={...t,fillMode:e}} /> ${this.host._t(s)} ${"temp"===e&&"temp"===t.fillMode?h` {const s=ao(e.target.value);null!=s&&(this.host._spaceDialog={...t,tempMin:s})}} /> + @input=${e=>{const s=ro(e.target.value);null!=s&&(this.host._spaceDialog={...t,tempMin:s})}} /> – {const s=ao(e.target.value);null!=s&&(this.host._spaceDialog={...t,tempMax:s})}} /> + @input=${e=>{const s=ro(e.target.value);null!=s&&(this.host._spaceDialog={...t,tempMax:s})}} /> °C `:l} @@ -2847,8 +2847,8 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e .label=${this.host._t("space.custom_fill")} .opacityLabel=${this.host._t("space.opacity")} .pickerLabels=${this.host._colorPickerLabels} - .color=${(t.customFill||Ls).c} - .opacity=${(t.customFill||Ls).a} + .color=${(t.customFill||Es).c} + .opacity=${(t.customFill||Es).a} @hp-color-opacity-change=${e=>{this.host._spaceDialog={...t,customFill:{c:e.detail.color,a:e.detail.opacity}}}}> ${t.customFill?h`
    `)}
    -
    `:l}`:l}`}_renderRoomDialog(){const t=!!this.host._roomEditId,e=t?null:this.host._wallFaceBatch,s=e&&e.candidates.length>1?this.host._t("room.queue_progress",{current:e.index+1,total:e.candidates.length}):"",i=!!this.host._areaSel||!!this.host._nameSel.trim(),o=Ns(this.host._curSpaceCfg),a=this.host._roomFill||o.fill,n=this.host._roomCustomFill||o.customFill,r=[...this.host._freeAreas];if(t&&this.host._areaSel&&!r.some(t=>t.area_id===this.host._areaSel)){const t=this.host.hass.areas[this.host._areaSel];t&&r.unshift(t)}return h``:l}`:l}`}_renderRoomDialog(){const t=!!this.host._roomEditId,e=t?null:this.host._wallFaceBatch,s=e&&e.candidates.length>1?this.host._t("room.queue_progress",{current:e.index+1,total:e.candidates.length}):"",i=!!this.host._areaSel||!!this.host._nameSel.trim(),o=Hs(this.host._curSpaceCfg),a=this.host._roomFill||o.fill,n=this.host._roomCustomFill||o.customFill,r=[...this.host._freeAreas];if(t&&this.host._areaSel&&!r.some(t=>t.area_id===this.host._areaSel)){const t=this.host.hass.areas[this.host._areaSel];t&&r.unshift(t)}return h`this._roomDialogCancel()}>
    @@ -2947,7 +2947,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e - ${[["","fill.inherit"],...Vi.map(t=>[t,"fill."+t])].map(([t,e])=>h`
    - ${this.host._renderCardPreview(Ns(this.host._curSpaceCfg).cardFontScale,this.host._roomNameScale,this.host._roomLabelScale)} + ${this.host._renderCardPreview(Hs(this.host._curSpaceCfg).cardFontScale,this.host._roomNameScale,this.host._roomLabelScale)}
    @@ -2991,4 +2991,4 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e ${this.host._t("btn.save")} `}
    - `}}export{xc as EDITOR_RUNTIME_FINGERPRINT,Sc as HouseplanEditorRuntime}; + `}}export{Cc as EDITOR_RUNTIME_FINGERPRINT,Pc as HouseplanEditorRuntime}; diff --git a/dist/houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js b/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js similarity index 98% rename from dist/houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js rename to custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js index 038c6afa..39ec3d62 100644 --- a/dist/houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js +++ b/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{l as t,aZ as s,A as e,x as o,b as a,cg as l,ch as i,ci as h,cj as c,aW as n,ck as r,cp as p,cl as d,cm as _,cn as u,co as g,dg as m,aV as b,aX as $,dh as v}from"./houseplan-card-CODdCIWj.js";import{i as f,c as y,e as w,r as D,a as k,b as S,g as C,t as M}from"./backdrop-pick-BnsHKWaS.js";const F=1e3,x=t=>{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";class L{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_help(l){const i=`${l}.aria`,h=t(this.host.hass,this.host._config?.language);return s(h,l)&&s(h,i)?a`{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";class L{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_help(l){const i=`${l}.aria`,h=t(this.host.hass,this.host._config?.language);return s(h,l)&&s(h,i)?a``:e}_openSpaceDialog(t,s){if(!this.host._serverStorage||!this.host._serverCfg)return void this.host._showToast(this.host._t("toast.integration_missing"));if("edit"===t){const e=this.host._serverCfg.spaces.find(t=>t.id===s);if(!e)return;const o=l(e),a=e.settings?.custom_fill&&"object"==typeof e.settings.custom_fill?i(e.settings.custom_fill):null,p="none"===o.fill?{...a||h,a:0}:a;return void(this.host._spaceDialog={mode:t,spaceId:s,title:e.title,planUrl:e.plan_url||null,planFile:null,source:e.plan_url?"file":"draw",showBorders:o.showBorders,showNames:o.showNames,zeroWallStyle:r(e),displayTouched:!0,hideDecor:o.hideDecor,hideOpenings:o.hideOpenings,roomColor:o.color,roomOpacity:o.opacity,fillMode:"none"===o.fill?"custom":o.fill,customFill:p,glowEnabled:o.glow,bgColor:o.bgColor,bgMode:"static"===e.settings?.bg_mode||"daynight"===e.settings?.bg_mode?e.settings.bg_mode:null,northDeg:n({},e.settings),sunRays:"boolean"==typeof e.settings?.sun_rays?e.settings.sun_rays:null,tempMin:o.tempMin,tempMax:o.tempMax,showLqi:o.showLqi??this.host._config?.show_signal??!0,cardFontScale:o.cardFontScale,labelTemp:o.labelTemp,labelHum:o.labelHum,labelLqi:o.labelLqi,labelLight:o.labelLight,cellCm:Number(e.cell_cm)>0?Number(e.cell_cm):5,cellCmInput:c(Number(e.cell_cm)>0?Number(e.cell_cm):5,this.host._imperial),cellCmTouched:!1,busy:!1})}const e=p(this.host._imperial);this.host._spaceDialog={mode:t,title:"",planUrl:null,planFile:null,...f(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:g,roomOpacity:u,fillMode:"custom",customFill:{...h,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:_,tempMax:d,showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:e,cellCmInput:c(e,this.host._imperial),cellCmTouched:!1,busy:!1}}async _pickPlanFile(t){const s=t.target,e=s.files?.[0];if(!e||!this.host._spaceDialog)return;s.value="";const o=await y(e);if("reject"===o.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===o.kind)return void(this.host._backdropGuard=o.state);const a=await w(e,o.ext,e.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:a})}_renderBackdropGuard(){return D(this.host,t=>{this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:t})},()=>{this.host._backdropGuard=null},this.host.hass)??e}_useServerPlan(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this.host._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let s=0;s<40;s++){const s=this.host._display(t);if(s){const e=await new Promise(t=>{const e=new Image;e.onload=()=>t(e.naturalWidth&&e.naturalHeight?e.naturalWidth/e.naturalHeight:0),e.onerror=()=>t(0),e.src=s}),o=this.host._spaceDialog;return o&&o.planUrl===t&&Number.isFinite(e)&&e>0?(this.host._spaceDialog={...o,savedAspect:e},e):0}if(await new Promise(t=>setTimeout(t,150)),this.host._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){const s=this.host._spaceDialog,e=s?.saved?.find(s=>s.name===t);if(!s||!e||e.used_by.length||e.url===s.planUrl)return;const o=await this.host._confirmDanger({key:"delete-plan",kind:"destructive",title:this.host._t("confirm.delete_plan_title"),message:this.host._t("confirm.delete_plan_body"),objectName:t,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),a=this.host._spaceDialog,l=a?.saved?.find(s=>s.name===t);if(o&&a&&l&&l.url===e.url&&l.modified===e.modified&&!l.used_by.length&&l.url!==a.planUrl)try{await this.host.hass.callWS({type:"houseplan/plans/delete",name:t});const s=this.host._spaceDialog;s?.saved&&(this.host._spaceDialog={...s,saved:s.saved.filter(s=>s.name!==t)})}catch(t){this.host._showToast(this.host._t("toast.plan_delete_failed",{err:this.host._errText(t)}))}}_renderServerPlans(t){if(t.savedBusy)return a`
    ${this.host._t("space.loading")}
    `;const s=t.saved||[];if(!s.length)return a`
    ${this.host._t("space.no_saved")}
    `;return a`
    ${s.map(s=>{return a`
    diff --git a/custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js b/custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js similarity index 93% rename from custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js rename to custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js index a71173c1..3b8b6ac1 100644 --- a/custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js +++ b/custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{t as e,l as t,A as i,dO as r,w as o,b as s,q as n}from"./houseplan-card-CODdCIWj.js";import{t as a,a as h,r as d}from"./zigbee-topology-BUFPOnoy.js";import{zigbeeTopologyRuntimeSnapshot as p,subscribeZigbeeTopology as l}from"./zigbee-topology-runtime-Jy73PIeo.js";function c(e,t,i,r,o,s=9,n=4.5){const a=t.x-e.x,h=t.y-e.y,d=Math.hypot(a,h),p=d-Math.max(0,i)-Math.max(0,r);if(!Number.isFinite(d)||d<=0||p<4)return null;const l=a/d,c=h/d,_="toward-neighbor"===o,u=_?{x:t.x-l*Math.max(0,r),y:t.y-c*Math.max(0,r)}:{x:e.x+l*Math.max(0,i),y:e.y+c*Math.max(0,i)},m=Math.min(s,Math.max(4,.45*p)),v=Math.min(n,.5*m),b=_?-1:1,g=u.x+l*m*b,y=u.y+c*m*b,x=-c;return{tip:u,points:[u,{x:g+x*v,y:y+l*v},{x:g-x*v,y:y-l*v}]}}const _={revision:0,topologies:[],states:{}},u="data-hp-zigbee-topology-endpoint";class m extends e{constructor(){super(...arguments),this.devices=[],this.currentSpace="",this._runtime=_,this._hovered="",this._desiredEndpointIds=new Set,this._endpointSetDirty=!1,this._endpointElements=new Set,this._pointerOver=e=>{if(!this._mouseAllowed(e))return void this._clear();const t=this._deviceFromEvent(e),i=t?.dataset.id||"";i&&i!==this._hovered&&(this._hovered=i,this.requestUpdate())},this._pointerOut=e=>{const t=this._deviceFromEvent(e);if(!t||t.dataset.id!==this._hovered)return;const i=e.relatedTarget instanceof Element?e.relatedTarget.closest('[data-hp="device"]'):null;i?.dataset.id!==this._hovered&&this._clear()},this._pointerDown=e=>{"mouse"!==e.pointerType&&this._clear()}}connectedCallback(){super.connectedCallback();const e=this.getRootNode();e.host&&"undefined"!=typeof MutationObserver&&(this._hoverGateObserver=new MutationObserver(()=>{e.host.hasAttribute("data-pointer-hover")||this._clear()}),this._hoverGateObserver.observe(e.host,{attributes:!0,attributeFilter:["data-pointer-hover"]})),queueMicrotask(()=>this._connectParent())}disconnectedCallback(){this._release?.(),this._release=void 0,this._disconnectParent(),this._hoverGateObserver?.disconnect(),this._hoverGateObserver=void 0,this._hovered="",this._desiredEndpointIds.clear(),super.disconnectedCallback()}updated(e){e.has("hass")&&(this._release?.(),this._acceptRuntime(p(this.hass)),this._release=l(this.hass,()=>{this._acceptRuntime(p(this.hass))}));const t=e.has("currentSpace")||e.has("devices")||e.has("registry");t&&(this._mappedMemo=void 0,this.devices.some(e=>e.id===this._hovered&&e.space===this.currentSpace)||this._clear()),this._connectParent(),(this._endpointSetDirty||t)&&this._syncEndpointOwnership()}_acceptRuntime(e){e.revision===this._runtime.revision&&e.topologies===this._runtime.topologies&&e.states===this._runtime.states||(this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._runtime=e,this._mappedMemo=void 0,this.requestUpdate())}_connectParent(){const e=this.parentElement;e&&e!==this._parent&&(this._disconnectParent(),this._parent=e,e.addEventListener("pointerover",this._pointerOver),e.addEventListener("pointerout",this._pointerOut),e.addEventListener("pointerdown",this._pointerDown,!0),"undefined"!=typeof MutationObserver&&(this._markerObserver=new MutationObserver(()=>this._syncEndpointOwnership()),this._markerObserver.observe(e,{childList:!0})),this._syncEndpointOwnership())}_disconnectParent(){this._parent?.removeEventListener("pointerover",this._pointerOver),this._parent?.removeEventListener("pointerout",this._pointerOut),this._parent?.removeEventListener("pointerdown",this._pointerDown,!0),this._markerObserver?.disconnect(),this._markerObserver=void 0,this._clearEndpointOwnership(),this._parent=void 0}_deviceFromEvent(e){for(const t of e.composedPath())if(t instanceof HTMLElement&&"device"===t.dataset.hp)return t;return null}_mouseAllowed(e){const t=this.getRootNode();return"mouse"===e.pointerType&&t.host?.hasAttribute?.("data-pointer-hover")}_clear(){this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._hovered&&(this._hovered="",this.requestUpdate())}_setDesiredEndpointIds(e){const t=new Set(e);t.size===this._desiredEndpointIds.size&&[...t].every(e=>this._desiredEndpointIds.has(e))||(this._desiredEndpointIds=t,this._endpointSetDirty=!0)}_marker(e){return[...this._parent?.querySelectorAll('.dev[data-hp="device"][data-id]')||[]].find(t=>t.dataset.id===e)||null}_clearEndpointOwnership(){for(const e of this._endpointElements)e.removeAttribute(u);for(const e of this._parent?.querySelectorAll(`[${u}]`)||[])e.removeAttribute(u);this._endpointElements.clear()}_syncEndpointOwnership(){const e=new Set;for(const t of this._desiredEndpointIds){const i=this._marker(t);i&&e.add(i)}for(const t of this._endpointElements)e.has(t)||t.removeAttribute(u);for(const t of this._parent?.querySelectorAll(`[${u}]`)||[])e.has(t)||t.removeAttribute(u);for(const t of e)this._endpointElements.has(t)&&t.hasAttribute(u)||t.setAttribute(u,"");this._endpointElements=e,this._endpointSetDirty=!1}_position(e,t,i){const r=this._marker(e);if(!r)return null;const o=Number.parseFloat(r.style.left),s=Number.parseFloat(r.style.top),n=r.getBoundingClientRect();return Number.isFinite(o)&&Number.isFinite(s)?{x:o*t/100,y:s*i/100,width:n.width,height:n.height}:null}_targetText(e){if("remote-space"===e.kind){const i=this.spaces?.find(t=>t.id===e.spaceId)?.title;return"string"==typeof i&&i.trim()||a(t(this.hass),"route_other_space")}return a(t(this.hass),"unplaced-coordinator"===e.kind?"route_coordinator_not_on_plan":"route_device_not_on_plan")}_markerClearance(e){return.61*Math.max(e.width,e.height)+3}_points(e){return e.map(e=>`${e.x.toFixed(2)},${e.y.toFixed(2)}`).join(" ")}render(){if(!this._hovered||!this.registry||!this._runtime.topologies.length)return this._setDesiredEndpointIds([]),i;const e=this._mappedMemo,n=e&&e.runtime===this._runtime&&e.devices===this.devices&&e.registry===this.registry?e.mapped:h(this._runtime.topologies,this.devices,this.registry);e&&n===e.mapped||(this._mappedMemo={runtime:this._runtime,devices:this.devices,registry:this.registry,mapped:n});const p=d(n,this.currentSpace,this._hovered),l=this.clientWidth||this._parent?.clientWidth||1,_=this.clientHeight||this._parent?.clientHeight||1,u=this._position(this._hovered,l,_);if(!u)return this._setDesiredEndpointIds([]),i;const m=p.lines.map(e=>({...e,point:this._position(e.neighborMarkerId,l,_)})).filter(e=>!!e.point).map(e=>{const t=void 0===e.lqi?"rgba(145,155,165,.85)":r(e.lqi),i=e.routeDirection?c(u,e.point,this._markerClearance(u),this._markerClearance(e.point),e.routeDirection):null;return{...e,color:t,arrow:i}}),v=u.x>l/2,b=this._markerClearance(u)+18,g=p.parentTargets.map((e,t)=>{const i=30*(t-(p.parentTargets.length-1)/2),r={x:u.x+(v?-b:b),y:Math.max(14,Math.min(_-14,u.y+i))};return{target:e,point:r,arrow:c(u,r,this._markerClearance(u),0,"toward-neighbor")}});return this._setDesiredEndpointIds(m.length||g.length||p.remoteCount?[this._hovered,...m.map(e=>e.neighborMarkerId)]:[]),s` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{t as e,l as t,A as i,dQ as r,w as o,b as s,q as n}from"./houseplan-card-Bhpi71t0.js";import{t as a,a as h,r as d}from"./zigbee-topology-B-C5QCCD.js";import{zigbeeTopologyRuntimeSnapshot as p,subscribeZigbeeTopology as l}from"./zigbee-topology-runtime-C4ZtGWbD.js";function c(e,t,i,r,o,s=9,n=4.5){const a=t.x-e.x,h=t.y-e.y,d=Math.hypot(a,h),p=d-Math.max(0,i)-Math.max(0,r);if(!Number.isFinite(d)||d<=0||p<4)return null;const l=a/d,c=h/d,_="toward-neighbor"===o,u=_?{x:t.x-l*Math.max(0,r),y:t.y-c*Math.max(0,r)}:{x:e.x+l*Math.max(0,i),y:e.y+c*Math.max(0,i)},m=Math.min(s,Math.max(4,.45*p)),b=Math.min(n,.5*m),v=_?-1:1,g=u.x+l*m*v,y=u.y+c*m*v,x=-c;return{tip:u,points:[u,{x:g+x*b,y:y+l*b},{x:g-x*b,y:y-l*b}]}}const _={revision:0,topologies:[],states:{}},u="data-hp-zigbee-topology-endpoint";class m extends e{constructor(){super(...arguments),this.devices=[],this.currentSpace="",this._runtime=_,this._hovered="",this._desiredEndpointIds=new Set,this._endpointSetDirty=!1,this._endpointElements=new Set,this._pointerOver=e=>{if(!this._mouseAllowed(e))return void this._clear();const t=this._deviceFromEvent(e),i=t?.dataset.id||"";i&&i!==this._hovered&&(this._hovered=i,this.requestUpdate())},this._pointerOut=e=>{const t=this._deviceFromEvent(e);if(!t||t.dataset.id!==this._hovered)return;const i=e.relatedTarget instanceof Element?e.relatedTarget.closest('[data-hp="device"]'):null;i?.dataset.id!==this._hovered&&this._clear()},this._pointerDown=e=>{"mouse"!==e.pointerType&&this._clear()}}connectedCallback(){super.connectedCallback();const e=this.getRootNode();e.host&&"undefined"!=typeof MutationObserver&&(this._hoverGateObserver=new MutationObserver(()=>{e.host.hasAttribute("data-pointer-hover")||this._clear()}),this._hoverGateObserver.observe(e.host,{attributes:!0,attributeFilter:["data-pointer-hover"]})),queueMicrotask(()=>this._connectParent())}disconnectedCallback(){this._release?.(),this._release=void 0,this._disconnectParent(),this._hoverGateObserver?.disconnect(),this._hoverGateObserver=void 0,this._hovered="",this._desiredEndpointIds.clear(),super.disconnectedCallback()}updated(e){e.has("hass")&&(this._release?.(),this._acceptRuntime(p(this.hass)),this._release=l(this.hass,()=>{this._acceptRuntime(p(this.hass))}));const t=e.has("currentSpace")||e.has("devices")||e.has("registry");t&&(this._mappedMemo=void 0,this.devices.some(e=>e.id===this._hovered&&e.space===this.currentSpace)||this._clear()),this._connectParent(),(this._endpointSetDirty||t)&&this._syncEndpointOwnership()}_acceptRuntime(e){e.revision===this._runtime.revision&&e.topologies===this._runtime.topologies&&e.states===this._runtime.states||(this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._runtime=e,this._mappedMemo=void 0,this.requestUpdate())}_connectParent(){const e=this.parentElement;e&&e!==this._parent&&(this._disconnectParent(),this._parent=e,e.addEventListener("pointerover",this._pointerOver),e.addEventListener("pointerout",this._pointerOut),e.addEventListener("pointerdown",this._pointerDown,!0),"undefined"!=typeof MutationObserver&&(this._markerObserver=new MutationObserver(()=>this._syncEndpointOwnership()),this._markerObserver.observe(e,{childList:!0})),this._syncEndpointOwnership())}_disconnectParent(){this._parent?.removeEventListener("pointerover",this._pointerOver),this._parent?.removeEventListener("pointerout",this._pointerOut),this._parent?.removeEventListener("pointerdown",this._pointerDown,!0),this._markerObserver?.disconnect(),this._markerObserver=void 0,this._clearEndpointOwnership(),this._parent=void 0}_deviceFromEvent(e){for(const t of e.composedPath())if(t instanceof HTMLElement&&"device"===t.dataset.hp)return t;return null}_mouseAllowed(e){const t=this.getRootNode();return"mouse"===e.pointerType&&t.host?.hasAttribute?.("data-pointer-hover")}_clear(){this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._hovered&&(this._hovered="",this.requestUpdate())}_setDesiredEndpointIds(e){const t=new Set(e);t.size===this._desiredEndpointIds.size&&[...t].every(e=>this._desiredEndpointIds.has(e))||(this._desiredEndpointIds=t,this._endpointSetDirty=!0)}_marker(e){return[...this._parent?.querySelectorAll('.dev[data-hp="device"][data-id]')||[]].find(t=>t.dataset.id===e)||null}_clearEndpointOwnership(){for(const e of this._endpointElements)e.removeAttribute(u);for(const e of this._parent?.querySelectorAll(`[${u}]`)||[])e.removeAttribute(u);this._endpointElements.clear()}_syncEndpointOwnership(){const e=new Set;for(const t of this._desiredEndpointIds){const i=this._marker(t);i&&e.add(i)}for(const t of this._endpointElements)e.has(t)||t.removeAttribute(u);for(const t of this._parent?.querySelectorAll(`[${u}]`)||[])e.has(t)||t.removeAttribute(u);for(const t of e)this._endpointElements.has(t)&&t.hasAttribute(u)||t.setAttribute(u,"");this._endpointElements=e,this._endpointSetDirty=!1}_position(e,t,i){const r=this._marker(e);if(!r)return null;const o=Number.parseFloat(r.style.left),s=Number.parseFloat(r.style.top),n=r.getBoundingClientRect();return Number.isFinite(o)&&Number.isFinite(s)?{x:o*t/100,y:s*i/100,width:n.width,height:n.height}:null}_targetText(e){if("remote-space"===e.kind){const i=this.spaces?.find(t=>t.id===e.spaceId)?.title;return"string"==typeof i&&i.trim()||a(t(this.hass),"route_other_space")}return a(t(this.hass),"unplaced-coordinator"===e.kind?"route_coordinator_not_on_plan":"route_device_not_on_plan")}_markerClearance(e){return.61*Math.max(e.width,e.height)+3}_points(e){return e.map(e=>`${e.x.toFixed(2)},${e.y.toFixed(2)}`).join(" ")}render(){if(!this._hovered||!this.registry||!this._runtime.topologies.length)return this._setDesiredEndpointIds([]),i;const e=this._mappedMemo,n=e&&e.runtime===this._runtime&&e.devices===this.devices&&e.registry===this.registry?e.mapped:h(this._runtime.topologies,this.devices,this.registry);e&&n===e.mapped||(this._mappedMemo={runtime:this._runtime,devices:this.devices,registry:this.registry,mapped:n});const p=d(n,this.currentSpace,this._hovered),l=this.clientWidth||this._parent?.clientWidth||1,_=this.clientHeight||this._parent?.clientHeight||1,u=this._position(this._hovered,l,_);if(!u)return this._setDesiredEndpointIds([]),i;const m=p.lines.map(e=>({...e,point:this._position(e.neighborMarkerId,l,_)})).filter(e=>!!e.point).map(e=>{const t=void 0===e.lqi?"rgba(145,155,165,.85)":r(e.lqi),i=e.routeDirection?c(u,e.point,this._markerClearance(u),this._markerClearance(e.point),e.routeDirection):null;return{...e,color:t,arrow:i}}),b=u.x>l/2,v=this._markerClearance(u)+18,g=p.parentTargets.map((e,t)=>{const i=30*(t-(p.parentTargets.length-1)/2),r={x:u.x+(b?-v:v),y:Math.max(14,Math.min(_-14,u.y+i))};return{target:e,point:r,arrow:c(u,r,this._markerClearance(u),0,"toward-neighbor")}});return this._setDesiredEndpointIds(m.length||g.length||p.remoteCount?[this._hovered,...m.map(e=>e.neighborMarkerId)]:[]),s` ${m.length||g.length?o`
    `)} - ${g.map(e=>s`
    s`
    ${this._targetText(e.target)}
    `)} ${p.remoteCount?s`
    `${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function j(e){let t=0;for(let n=0;nArray.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])).map(e=>[Number(e[0]),Number(e[1])]),n=t[t.length-1];return t.length>1&&t[0][0]===n[0]&&t[0][1]===n[1]&&t.pop(),t}(e);if(n.length<3)return[];const o=!t;return j(n)>0===o?n:[...n].reverse()}function O(e,t,o){return e.length?`M ${e.map(e=>C(n(e,o,t))).join(" L ")} Z`:""}function A(e,t,n){const o=t[1]-e[1],a=-(t[0]-e[0]),i=n.rotDeg*Math.PI/180;return o*Math.sin(i)+a*Math.cos(i)}function B(t,o,a=e){if(!Number.isFinite(o)||o<0)throw new Error("invalid floor edge height");const i=(t||[]).map(e=>(e||[]).map((e,t)=>function(e,t){const n=N(e,t);if(!n.length)return n;let o=0;for(let e=1;e0)).filter(e=>e.length>=3&&Math.abs(j(e))>=1e-9)).filter(e=>e.length&&j(e[0])>0);i.sort((e,t)=>{const n=e[0][0],o=t[0][0];return n[0]-o[0]||n[1]-o[1]||Math.abs(j(t[0]))-Math.abs(j(e[0]))});const r=[],s=[];let l=0;for(let e=0;ee.depth-t.depth||e.component-t.component||e.edge-t.edge),{footprintPath:r.join(" "),sides:s,componentCount:i.length,edgeCount:l}}function R(e,t){return e^=Math.round(64*(Number.isFinite(t)?t:0)),Math.imul(e,16777619)>>>0}const F=Object.freeze({revision:1,leafThicknessRatio:.04,frameThicknessRatio:.055,gateTurnDeg:10,gateTopRatio:.88,windowBottomRatio:.27,windowTopRatio:.78,doorTopRatio:.92});F.leafThicknessRatio,F.frameThicknessRatio;const H=e=>e.every(Number.isFinite);function T(e,t){return Object.freeze([Object.is(e,-0)?0:e,Object.is(t,-0)?0:t])}function L(e,t){return[e[0]+t[0],e[1]+t[1]]}function V(e,t){return[e[0]-t[0],e[1]-t[1]]}function G(e,t){return[e[0]*t,e[1]*t]}function W(e,t,n,o){const a=e[0]*n,i=e[1]*o,r=t*Math.PI/180;return[a*Math.cos(r)-i*Math.sin(r),a*Math.sin(r)+i*Math.cos(r)]}function E(e,t,n,a,i,r,s){const l=e.flipH?-1:1,c="gate"===e.type?1:e.flipV?-1:1,d=o(e.type,e.flipV,e.angle,e.face);return{leaf:t,hinge:L([e.x+d.ox,e.y+d.oy],W(n,e.angle,l,c)),closedVector:W(a,e.angle,l,c),quarterVector:W([-a[1],a[0]],e.angle,l,c),turnDeg:i,bottom:r,top:s}}const q=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function D(e,t,o,a,i={}){const r=o.map(e=>n(e.point,e.z,a));return Object.freeze({kind:e,material:t,d:`M ${r.map(q).join(" L ")} Z`,depth:Math.max(...r.map(e=>e[1])),...i})}function _(e,t,n,o,a,i,r,s={}){return D(e,t,[{point:n,z:a},{point:o,z:a},{point:o,z:i},{point:n,z:i}],r,s)}function U(t,o,a=e){const i=Math.max(0,Math.min(1,Number.isFinite(o)?o:0));return t.leaves.map(e=>{const o=function(e,t){const n=e.turnDeg*t*Math.PI/180;return[e.hinge[0]+e.closedVector[0]*Math.cos(n)+e.quarterVector[0]*Math.sin(n),e.hinge[1]+e.closedVector[1]*Math.cos(n)+e.quarterVector[1]*Math.sin(n)]}(e,i),r=n(e.hinge,e.bottom,a),s=n(o,e.bottom,a),l=n(o,e.top,a),c=n(e.hinge,e.top,a),d="window"===t.type?"light-window":"matte-leaf",u="window"===t.type?Object.freeze([_("window-insert","light-window",e.hinge,o,e.bottom,e.top,a)]):function(e,t,n,o){const a=V(t,e.hinge),i=Math.hypot(a[0],a[1]);if(!(i>1e-9&&n>0))return Object.freeze([]);const r=T(-a[1]*n/(2*i),a[0]*n/(2*i)),s=L(e.hinge,r),l=L(t,r),c=V(e.hinge,r),d=V(t,r),u=[_("leaf-back","matte-leaf",d,c,e.bottom,e.top,o),_("leaf-front","matte-leaf",s,l,e.bottom,e.top,o),_("leaf-edge","matte-leaf",c,s,e.bottom,e.top,o,{edge:"hinge"}),_("leaf-edge","matte-leaf",l,d,e.bottom,e.top,o,{edge:"tip"}),D("leaf-top","matte-leaf",[{point:s,z:e.top},{point:c,z:e.top},{point:d,z:e.top},{point:l,z:e.top}],o)];return Object.freeze(u.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||String(e.edge||"").localeCompare(String(t.edge||""))))}(e,o,t.leafThickness,a);return Object.freeze({id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${q(r)} L ${q(s)} L ${q(l)} L ${q(c)} Z`,shadowD:`M ${q(n(e.hinge,0,a))} L ${q(n(o,0,a))}`,depth:Math.max(r[1],s[1]),material:d,thickness:"window"===t.type?0:t.leafThickness,surfaces:u})})}const K=1e-9,Z=e=>e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function Q(e){let t=0;for(let n=0;n=3&&e.every(Z)&&Math.abs(Q(e))>K}function X(e,t,n){const o=n[0]-t[0],a=n[1]-t[1],i=o*o+a*a,r=i?Math.max(0,Math.min(1,((e[0]-t[0])*o+(e[1]-t[1])*a)/i)):0;return Math.hypot(e[0]-t[0]-r*o,e[1]-t[1]-r*a)}function Y(e,t,n=1e-7){for(let o=0;oe[1]!=r[1]>e[1]&&e[0]<(r[0]-i[0])*(e[1]-i[1])/(r[1]-i[1])+i[0]&&(n=!n)}return n}function te(e){return Math.max(0,Math.abs(Q(e.outer))-(e.holes||[]).reduce((e,t)=>e+Math.abs(Q(t)),0))}function ne(e){return!!e.id&&J(e.outer)&&(e.holes||[]).every(J)&&te(e)>K}function oe(e,t){if(!ne(t)||Y(e,t.outer)||!ee(e,t.outer))return!1;for(const n of t.holes||[])if(Y(e,n)||ee(e,n))return!1;return!0}function ae(e){if(!ne(e))return null;if(e.safePoint&&oe(e.safePoint,e))return[e.safePoint[0],e.safePoint[1]];const t=e.outer.map(e=>e[0]),n=e.outer.map(e=>e[1]),o=Math.min(...t),a=Math.max(...t),i=Math.min(...n),r=Math.max(...n),s=[[(o+a)/2,(i+r)/2],[t.reduce((e,t)=>e+t,0)/t.length,n.reduce((e,t)=>e+t,0)/n.length]];for(let t=0;t{if(!oe(t,e))return;const n=function(e,t){let n=1/0;for(const o of[t.outer,...t.holes||[]])for(let t=0;tc+K&&(l=t,c=n)};s.forEach(d);for(let e=1;e<16;e++)for(let t=1;t<16;t++)d([o+(a-o)*e/16,i+(r-i)*t/16]);return l}function ie(e){if(!Z(e.floorAnchor))return null;const t=e.roomsValidated?e.rooms:e.rooms.filter(ne),n=e.preferredRoomId&&t.find(t=>t.id===e.preferredRoomId)||null;let o=null;return"device"===e.kind?(n&&oe(e.floorAnchor,n)&&(o=n),o||(o=t.filter(t=>oe(e.floorAnchor,t)).sort((e,t)=>te(e)-te(t)||((e,t)=>et?1:0)(e.id,t.id))[0]||null)):o=n,o?{id:o.id,area:te(o),safePoint:e.roomsValidated&&o.safePoint?[o.safePoint[0],o.safePoint[1]]:ae(o)}:null}function re(t,o,a,i=e,r=[0,0]){if(!Z(t)||!Z(o)||o[0]<0||o[1]<0||!Number.isFinite(a)||!Z(r))throw new Error("invalid isometric overlay footprint");return[[t[0]-o[0],t[1]-o[1]],[t[0]+o[0],t[1]-o[1]],[t[0]+o[0],t[1]+o[1]],[t[0]-o[0],t[1]+o[1]]].map(e=>{const t=n(e,a,i);return[t[0]+r[0],t[1]+r[1]]})}function se(e,t,n){return(t[0]-e[0])*(n[1]-e[1])-(t[1]-e[1])*(n[0]-e[0])}function le(e,t,n,o){const a=se(e,t,n),i=se(e,t,o),r=se(n,o,e),s=se(n,o,t);return(a>K&&i<-K||a<-K&&i>K)&&(r>K&&s<-K||r<-K&&s>K)||(Math.abs(a)<=K&&X(n,e,t)<=K||Math.abs(i)<=K&&X(o,e,t)<=K||Math.abs(r)<=K&&X(e,n,o)<=K||Math.abs(s)<=K&&X(t,n,o)<=K)}function ce(e,t,n,o){return le(e,t,n,o)?0:Math.min(X(e,n,o),X(t,n,o),X(n,e,t),X(o,e,t))}const de=new WeakMap;function ue(e){if(!e.length)return null;let t=1/0,n=1/0,o=-1/0,a=-1/0;for(const i of e){if(!Z(i))return null;t=Math.min(t,i[0]),n=Math.min(n,i[1]),o=Math.max(o,i[0]),a=Math.max(a,i[1])}return[t,n,o,a]}function he(e,t){if(!t)return ue(e.outer);if(de.has(e))return de.get(e)??null;const n=ue(e.outer);return de.set(e,n),n}function fe(e,t,n){return e[0]<=t[2]+n&&e[2]>=t[0]-n&&e[1]<=t[3]+n&&e[3]>=t[1]-n}function pe(e,t,n,o){return Math.min(t[0],n[0])<=e[2]+o&&Math.max(t[0],n[0])>=e[0]-o&&Math.min(t[1],n[1])<=e[3]+o&&Math.max(t[1],n[1])>=e[1]-o}function me(e,t,n,o,a){const i=he(n,a);if(!i||!fe(t,i,o))return!1;if(e.some(e=>function(e,t){return!!ee(e,t.outer)&&!(t.holes||[]).some(t=>ee(e,t))}(e,n)))return!0;if(n.outer.some(n=>n[0]>=t[0]&&n[0]<=t[2]&&n[1]>=t[1]&&n[1]<=t[3]&&ee(n,e)))return!0;for(const a of[n.outer,...n.holes||[]])for(let n=0;n"wall-side"===e.layer?0:"wall-top"===e.layer?1:2,Me=e=>{if("wall-side"===e.layer)return`${e.face.polygon}:${e.face.ring}:${e.face.edge}`;if("wall-top"===e.layer)return String(e.face.component);const t=e.surface;return`${t.sourceIndex}:${t.leaf??-1}:${t.kind}:${t.jamb??-1}:${t.edge??""}:${t.id}:${t.material}`};function be(e,t){const n=[...e.sides.map(e=>({layer:"wall-side",depth:e.depth,face:e})),...e.topFaces.map(e=>({layer:"wall-top",depth:e.depth,face:e})),...t.map(e=>({layer:"opening",depth:e.depth,surface:e}))];return n.sort((e,t)=>e.depth-t.depth||xe(e)-xe(t)||Me(e).localeCompare(Me(t))),Object.freeze(n)}const Se=Object.freeze({textLatinAdvance:.72,textWideAsciiAdvance:1,textWideAdvance:1.1,textSpaceAdvance:.4,textWidthSafety:1.08,deviceShellInset:.134375,deviceShellGap:.1,deviceSectionGap:.08,deviceBadgeMinWidth:.7875,deviceBadgeHeight:.7875,deviceBadgeInlinePadding:.28,deviceValueInlinePadding:.32,deviceAuxiliaryExtent:.7,deviceLqiFontSize:.38,deviceLqiTop:.734375,deviceLqiBelowBottomBadgeTop:1.571875,devicePadding:.08,roomNameLineHeight:1.25,roomAreaLinkWidth:1.1,roomMetricsTopGap:.15,roomMetricFontSize:.75,roomMetricLineHeight:1.25,roomMetricIconWidth:1.05,roomMetricInnerGap:.12,roomMetricRowGap:.55,roomMetricMinWidth:11,roomPadding:.4,openingLockHalfSize:.62,roomMetricTextCharacters:Object.freeze({temperature:10,humidity:8,lqi:6,light:24})});function $e(e){return[...String(e)].reduce((e,t)=>/\s/.test(t)?e+Se.textSpaceAdvance:/[MW@#%&]/.test(t)?e+Se.textWideAsciiAdvance:e+(t.codePointAt(0)>255?Se.textWideAdvance:Se.textLatinAdvance),0)*Se.textWidthSafety}function ke(e,t){return $e(e)*z(t||e)}function ze(e,t){return[Math.max(Math.abs(e.left),Math.abs(e.right))+t,Math.max(Math.abs(e.top),Math.abs(e.bottom))+t]}function Ie(e){if("opening-lock"===e.kind){const t=(Number.isFinite(e.size)&&e.size>0?e.size:0)*Se.openingLockHalfSize;return[t,t]}if("room-label"===e.kind){const t=Number.isFinite(e.font)&&e.font>0?e.font:0,n=v(e.room.settings?.name_scale),o=v(e.room.settings?.label_scale),a=($e(e.room.name||"")+(e.room.area?Se.roomAreaLinkWidth:0))*n,i=Se.roomNameLineHeight*n,r=[e.display.labelTemp?Se.roomMetricTextCharacters.temperature:0,e.display.labelHum?Se.roomMetricTextCharacters.humidity:0,e.display.labelLqi&&e.room.area?Se.roomMetricTextCharacters.lqi:0,e.display.labelLight?Se.roomMetricTextCharacters.light:0].filter(e=>e>0),s=Se.roomMetricFontSize*o,l=r.length?Math.max(Se.roomMetricMinWidth,r.reduce((e,t)=>e+Se.roomMetricIconWidth+Se.roomMetricInnerGap+t*Se.textLatinAdvance*Se.textWidthSafety,0)+(r.length-1)*Se.roomMetricRowGap)*s:0,c=r.length?s*Se.roomMetricLineHeight:0,d=ze({left:-Math.max(a,l)/2,right:Math.max(a,l)/2,top:-i/2,bottom:r.length?i/2+Se.roomMetricsTopGap+c:i/2},Se.roomPadding);return[d[0]*t,d[1]*t]}const t=Number.isFinite(e.core)&&e.core>0?e.core:0,n=e.presentation,o=null==n.valueText?1:Math.max(1,ke(n.valueText,n.valueFullText||n.valueText)+Se.deviceValueInlinePadding),a=[];n.valueBadge&&a.push(Math.max(Se.deviceBadgeMinWidth,ke(n.valueBadge.text,n.valueBadge.fullText||n.valueBadge.text)+Se.deviceBadgeInlinePadding));for(const e of x(n)){const t=e.text+e.suffix;a.push(Math.max(Se.deviceBadgeMinWidth,ke(t,t)+Se.deviceBadgeInlinePadding))}const i=n.valueBadge?.position||"right";let r;if(!a.length||"left"!==i&&"right"!==i)if(a.length){const e=a.reduce((e,t)=>e+t,0)+(a.length-1)*Se.deviceSectionGap,t=Math.max(o,e),n=1+Se.deviceShellGap+Se.deviceBadgeHeight;r="bottom"===i?{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:-.5+n+Se.deviceShellInset}:{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:.5-n-Se.deviceShellInset,bottom:.5+Se.deviceShellInset}}else r={left:-.5-Se.deviceShellInset,right:-.5+o+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:.5+Se.deviceShellInset};else{const e=Math.max(...a),t=a.length*Se.deviceBadgeHeight+(a.length-1)*Se.deviceSectionGap,n=o+Se.deviceShellGap+e,s=Math.max(1,t);r="right"===i?{left:-.5-Se.deviceShellInset,right:-.5+n+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}:{left:.5-n-Se.deviceShellInset,right:.5+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}}const s=Se.deviceAuxiliaryExtent;if(r.left=Math.min(r.left,-s),r.right=Math.max(r.right,s),r.top=Math.min(r.top,-s),r.bottom=Math.max(r.bottom,s),n.pulse.animated){const e=Math.max(1,n.pulse.diameterScale)/2;r.left=Math.min(r.left,-e),r.right=Math.max(r.right,e),r.top=Math.min(r.top,-e),r.bottom=Math.max(r.bottom,e)}if(null!=n.lqiText){const e="bottom"===n.valueBadge?.position?Se.deviceLqiBelowBottomBadgeTop:Se.deviceLqiTop,t=$e(n.lqiText)*Se.deviceLqiFontSize/2;r.left=Math.min(r.left,-t),r.right=Math.max(r.right,t),r.bottom=Math.max(r.bottom,e+Se.deviceLqiFontSize)}const l=ze(r,Se.devicePadding);return[l[0]*t,l[1]*t]}function Pe(e,t){return e.flatMap((e,n)=>e.orphanReason?[]:[{id:String(e.id||n),sourceIndex:n,type:e.type,x:e.rx,y:e.ry,angle:Number(e.angle)||0,length:e.rlen>0?e.rlen:.9*t,flipH:!!e.flip_h,flipV:!!e.flip_v}])}function Ce(e){return{id:e.id,x:e.x,y:e.y,w:e.w,h:e.h,poly:e.poly,wall_ids:e.wall_ids}}function je(e,t){const n=e?.partitionHost;if(!n)return null;const o="gate"===t.type?!t.flipV:t.flipV;return{sourceIndex:t.sourceIndex,hostId:n.host.id,t:n.t,depth:n.depth,face:p(n,o)}}function Ne(n,o=F){const a=Pe(n.openings,n.coordinateScale),r=a.map(e=>je(n.openings[e.sourceIndex],e)),p=i(t,n.cellCm),m=i(s,n.cellCm),g=i(l,n.cellCm);return{key:`${n.space.id}|${function(e){let t=2166136261;const n=e=>{if("number"!=typeof e)if("string"!=typeof e)if("boolean"!=typeof e)if(Array.isArray(e)){t=R(t,e.length);for(const t of e)n(t)}else{if(e&&"object"==typeof e){const t=e;for(const e of Object.keys(t).sort())n(e),n(t[e]);return}t=R(t,-1)}else t=R(t,e?1:0);else for(const n of e)t=R(t,n.codePointAt(0)||0);else t=R(t,e)};return n(e),t.toString(36)}({rooms:n.space.rooms.map(Ce),walls:n.walls,openCuts:n.openCuts,openings:a,openingHosts:r,openingGeometryPolicy:o,partitions:n.space.partitions,roomDrafts:n.space.room_drafts,columns:n.space.wall_columns,cellCm:n.cellCm,gridPitch:n.gridPitch,wallKeyPitch:n.wallKeyPitch,camera:e,wallHeight:p,raisedHeight:g,floorEdgeHeight:m,algorithm:4})}`,build:()=>{n.onBuild();const i=c(n.space,n.cellCm,n.gridPitch,2e-4*n.gridPitch,n.partitionCuts()).all,s=n.roomOpenings(),l=n.walls.length||i.length?d(n.space.rooms,n.walls,n.openCuts,s,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale,i):null;if(l&&("failed-core"===l.status||"not-applicable"===l.status))throw new Error("wall boolean geometry failed");const m=l?.paperGeom??u(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale);if(!m)throw new Error("floor boolean geometry failed");const g=l?.openingIndex||h(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale),w=a.map((e,a)=>{const i=r[a],s="gate"===e.type?!e.flipV:e.flipV,l=i?i.face:n.walls.length||"gate"===e.type?f(g,{x:e.x,y:e.y,angle:e.angle,length:e.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(e,n=t,o=F){const a=e.face.cm??0;if(!H([e.x,e.y,e.angle,e.length,e.face.ox,e.face.oy,a,n])||!(e.length>0)||!(n>0)||-1!==e.face.side&&1!==e.face.side||a<0)throw new Error("invalid isometric opening input");const i=e.length/2,r=e.angle*Math.PI/180,s=T(Math.cos(r),Math.sin(r)),l=T(-Math.sin(r),Math.cos(r)),c=T(e.x,e.y),d=T(e.x-s[0]*i,e.y-s[1]*i),u=T(e.x+s[0]*i,e.y+s[1]*i),h=T(e.face.ox,e.face.oy),f=T(d[0]+h[0],d[1]+h[1]),p=T(u[0]+h[0],u[1]+h[1]),m=T(d[0]-h[0],d[1]-h[1]),g=T(u[0]-h[0],u[1]-h[1]),w=Object.freeze({center:c,tangent:s,normal:l,start:d,end:u}),y=Object.freeze({side:e.face.side,cm:a,depth:2*Math.hypot(e.face.ox,e.face.oy),offset:h,selectedStart:f,selectedEnd:p,oppositeStart:m,oppositeEnd:g}),v="passage"===e.type?[]:[Object.freeze({jamb:0,center:d,selected:f,opposite:m}),Object.freeze({jamb:1,center:u,selected:p,opposite:g})];let x;if("passage"===e.type)x=[];else if("gate"===e.type){const t=e.face.side*o.gateTurnDeg;x=[E(e,0,[-i,0],[i,0],t,0,n*o.gateTopRatio),E(e,1,[i,0],[-i,0],-t,0,n*o.gateTopRatio)]}else x="window"===e.type?[E(e,0,[-i,0],[i,0],-90,n*o.windowBottomRatio,n*o.windowTopRatio),E(e,1,[i,0],[-i,0],90,n*o.windowBottomRatio,n*o.windowTopRatio)]:[E(e,0,[-i,0],[e.length,0],-90,0,n*o.doorTopRatio)];return Object.freeze({id:e.id,sourceIndex:e.sourceIndex,type:e.type,wallHeight:n,leafThickness:n*o.leafThicknessRatio,frameThickness:n*o.frameThicknessRatio,axis:w,face:y,reveals:Object.freeze(v),leaves:Object.freeze(x.map(e=>Object.freeze({...e,hinge:T(e.hinge[0],e.hinge[1]),closedVector:T(e.closedVector[0],e.closedVector[1]),quarterVector:T(e.quarterVector[0],e.quarterVector[1])})))})}({...e,face:l},p,o)}),y=Object.freeze(w);return{walls:l?.components.flatMap(e=>e.geom)||[],floor:m,openings:y,openingSurfaces:Object.freeze(y.flatMap(t=>function(t,n=e){if("passage"===t.type)return Object.freeze([]);const o=[];if(t.face.depth>1e-9)for(const e of t.reveals)o.push(_("jamb-reveal","reveal",e.selected,e.opposite,0,t.wallHeight,n,{jamb:e.jamb}));if("window"!==t.type||!t.leaves.length)return Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)));const a=Math.min(...t.leaves.map(e=>e.bottom)),i=Math.max(...t.leaves.map(e=>e.top)),r=Math.min(t.frameThickness,Math.hypot(t.axis.end[0]-t.axis.start[0],t.axis.end[1]-t.axis.start[1])/4,(i-a)/4),s=L(t.axis.start,G(t.axis.tangent,r)),l=V(t.axis.end,G(t.axis.tangent,r)),c=t.face.depth>1e-9?[t.face.offset,T(-t.face.offset[0],-t.face.offset[1])]:[t.face.offset];for(const e of c){const c=L(t.axis.start,e),d=L(t.axis.end,e),u=L(s,e),h=L(l,e);o.push(_("window-frame-side","light-frame",c,u,a,i,n,{jamb:0}),_("window-frame-side","light-frame",h,d,a,i,n,{jamb:1}),_("window-frame-top","light-frame",u,h,Math.max(a,i-r),i,n))}return t.face.depth>1e-9&&o.push(D("window-sill","light-sill",[{point:t.face.selectedStart,z:a},{point:t.face.selectedEnd,z:a},{point:t.face.oppositeEnd,z:a},{point:t.face.oppositeStart,z:a}],n)),Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)))}(t).map(e=>Object.freeze({...e,id:t.id,sourceIndex:t.sourceIndex,type:t.type}))))}}}}const Oe=e=>Array.isArray(e)?e:[];function Ae(e,t){const o=e=>Oe(e).flatMap(e=>Array.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])?[n([Number(e[0]),Number(e[1])],t)]:[]);return Oe(e).flatMap(e=>{const t=Oe(e);if(!t.length)return[];const n=o(t[0]);if(n.length<3)return[];return[{outer:n,holes:t.slice(1).map(o).filter(e=>e.length>=3)}]})}function Be(o){const a=i(t,o.cellCm),r=i(s,o.cellCm),c=i(l,o.cellCm),d=S(o.cache,o.source.key);let u=d.hit?d.value:void 0;if(!u){const i=o.source.build(),s=function(o,a=e,i=t){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const r=[],s=[],l=[],c=[];let d=0;for(let e=0;e<(o||[]).length;e++){const t=o[e],u=[];let h=-1/0;for(let o=0;o<(t||[]).length;o++){const s=N(t[o],o>0);if(s.length<3||Math.abs(j(s))<1e-9)continue;const f=O(s,a,i);r.push(f),u.push(f),h=Math.max(h,...s.map(e=>n(e,i,a)[1])),d+=s.length;for(let t=0;te.depth-t.depth||e.polygon-t.polygon||e.ring-t.ring||e.edge-t.edge),s.sort((e,t)=>e.depth-t.depth||e.component-t.component),{topPath:r.join(" "),topFaces:s,sides:l,contactPath:c.join(" "),edgeCount:d}}(i.walls,e,a),l=Ae(i.walls,a);u={geometry:s,floor:B(i.floor,r),wallSilhouettes:Object.freeze([...l,...s.sides.map(e=>({outer:e.points}))]),openings:i.openings,openingSurfaces:i.openingSurfaces},$(o.cache,o.source.key,u,8)}const h=function(e){let t=1/0,n=1/0,o=-1/0,a=-1/0;const i=(e,i=0)=>{t=Math.min(t,e[0]-i),n=Math.min(n,e[1]-i),o=Math.max(o,e[0]+i),a=Math.max(a,e[1]+i)};for(const t of e)if("passage"!==t.type){i(t.axis.start),i(t.axis.end),i(t.face.selectedStart),i(t.face.selectedEnd),i(t.face.oppositeStart),i(t.face.oppositeEnd);for(const e of t.leaves){const n=Math.hypot(e.closedVector[0],e.closedVector[1])+t.leafThickness/2;i(e.hinge,n)}}return H([t,n,o,a])?{x:t,y:n,w:o-t,h:a-n}:null}(u.openings),f=h?Re(o.liveFrame,h):o.liveFrame,p=k({rect:f,wallHeight:a,openingHeight:a,floorDepth:r,raisedHeight:c});return{key:o.source.key,...u,frame:p}}const Re=(e,t)=>{const n=Math.min(e.x,t.x),o=Math.min(e.y,t.y);return{x:n,y:o,w:Math.max(e.x+e.w,t.x+t.w)-n,h:Math.max(e.y+e.h,t.y+t.h)-o}},Fe=e=>{if(!e.length||!e.every(e=>Number.isFinite(e[0])&&Number.isFinite(e[1])))return null;const t=e.map(e=>e[0]),n=e.map(e=>e[1]),o=Math.min(...t),a=Math.min(...n);return{x:o,y:a,w:Math.max(...t)-o,h:Math.max(...n)-a}},He=(e,t)=>{const n=e.placement,o=t?n.visualScene:n.raisedScene,[a,i]=e.screenHalfSize,r=t?n.footprint:n.footprint.map(e=>[e[0]-n.nudgeScene[0],e[1]-n.nudgeScene[1]]);return[n.floorScene,...r,[o[0]-a,o[1]-i],[o[0]+a,o[1]-i],[o[0]+a,o[1]+i],[o[0]-a,o[1]+i]]},Te=(e,t)=>void 0===t?e:e.filter(e=>e.placement.owner?.id===t);function Le(e,t){return e?Fe(Te(e.entries,t).flatMap(e=>He(e,!0))):null}function Ve(e){const t=Te(e.entries,e.ownerId),n=Fe(t.flatMap(e=>He(e,!1))),o=n?Re(e.baseBounds,n):e.baseBounds,a=e.targetView(o);if(!(a&&a.w>0&&a.h>0&&[a.x,a.y,a.w,a.h].every(Number.isFinite)))return null;const i=e.stageSize;if(!(n&&i&&i.width>0&&i.height>0))return{bounds:o,view:a};const r=e=>Math.max(e.w/i.width,e.h/i.height),s=t=>{const o=48*t,a={x:n.x-o,y:n.y-o,w:n.w+2*o,h:n.h+2*o},i=Re(e.baseBounds,a),r=e.targetView(i);return r&&[r.x,r.y,r.w,r.h].every(Number.isFinite)&&r.w>0&&r.h>0?{bounds:i,view:r}:null};let l=0,c=Math.max(r(a),Number.EPSILON),d=s(c);for(let e=0;d&&r(d.view)>c*(1+1e-10)&&e<24;e++)l=c,c*=2,d=s(c);if(!d)return null;for(let e=0;e<40;e++){const e=(l+c)/2,t=s(e);if(!t)return null;r(t.view)<=e?(c=e,d=t):l=e}return d}const Ge=new WeakMap,We=2048,Ee=new WeakMap,qe=new WeakMap,De=new WeakMap;function _e(e,t){if(e.size!==t.size)return!1;for(const[n,o]of t)if(e.get(n)!==o)return!1;return!0}function Ue(e){const t=Ge.get(e.rooms);if(t)return t;const n=e.rooms.flatMap((e,t)=>{const n=w(e);return n&&n.length>=3?[{room:e,index:t,poly:n}]:[]}),o=Object.freeze(n.map(({room:e,index:t,poly:o})=>{const a=y(o,n.filter(e=>e.index!==t).map(e=>e.poly)),i={id:e.id||`room-index-${t}`,outer:o.map(e=>[e[0],e[1]]),holes:a.map(e=>e.map(e=>[e[0],e[1]]))};return{room:e,overlayRoom:{...i,safePoint:ae(i)||void 0}}}));return Ge.set(e.rooms,o),o}function Ke(o){const s=o.stageSize&&o.stageSize.width>0&&o.stageSize.height>0?Math.max(o.view.w/o.stageSize.width,o.view.h/o.stageSize.height):Math.max(o.view.w,o.view.h)/1e3,l=Ue(o.space),c=l.map(e=>e.overlayRoom),d=i(t,o.cellCm),u=i(a,o.cellCm),h=new Map,f=new Map,p=new Map,m=[];let g=Ee.get(o.wallSilhouettes);g||(g=new Map,Ee.set(o.wallSilhouettes,g));let w=qe.get(l);w||(w=new Map,qe.set(l,w));const y=o.iconPct*r(o.space)*o.kioskIconScale/100,v=o.deviceBasePct*r(o.space)*o.kioskIconScale/100,x=(i,r,l,h,f,p=!1)=>{const m=`${!1===o.resolveCollisions?"fit":"live"}\0${i}\0${r}`,y=[l[0],l[1],h[0],h[1],f||"",d,u,o.layers.shadows?1:0,p?1:0].join("|"),v=`${y}|${s}`,x=S(g,m);if(x.hit&&x.value.signature===v)return x.value.placement;if(x.hit&&x.value.shapeSignature===y&&s<=x.value.unitsPerPixel){const e=x.value.placement,t=e.nudgeDistanceCss*x.value.unitsPerPixel/s;if(!e.nearWallBefore||e.cleared&&t<=48)return e}const M=`${i}\0${r}`,b=[l[0],l[1],f||""].join("|"),k=S(w,M),z=k.hit&&k.value.signature===b?k.value.owner:ie({kind:i,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:f});k.hit&&k.value.signature===b||$(w,M,{signature:b,owner:z},We);const I=function(o){const i=o.camera||e,r=o.wallHeight??t,s=o.visualOffset??a,l=o.sceneUnitsPerCssPixel??1,c=o.safetyGapCssPx??4,d=o.maxNudgeCssPx??48;if(!Z(o.floorAnchor)||!Z(o.footprintHalfSize)||o.footprintHalfSize[0]<0||o.footprintHalfSize[1]<0||!Number.isFinite(r)||r<0||!Number.isFinite(s)||s<0||!Number.isFinite(l)||l<=0||!Number.isFinite(c)||c<0||!Number.isFinite(d)||d<0)throw new Error("invalid isometric overlay input");const u=[o.floorAnchor[0],o.floorAnchor[1]],h=n(u,0,i),f=(p=o.kind,!o.showBorders||"device"!==p&&"room-label"!==p&&"opening-lock"!==p?"floor":"raised");var p;if("floor"===f)return{plane:f,owner:null,floorAnchor:u,floorScene:h,raisedScene:h,visualScene:h,footprint:[],nudgeScene:[0,0],nudgeCss:[0,0],nudgeDistanceCss:0,nudged:!1,nearWallBefore:!1,nearWallAfter:!1,cleared:!0,capped:!1,grounding:{center:h,visible:!1},tether:ye(h,h,!1),status:"ok",reason:null};const m=r+s,g=n(u,m,i),w=o.ownerAlreadyResolved?o.resolvedOwner??null:ie(o),y=o.wallGeometryValidated??o.wallSilhouettes.every(ge),v=c*l,x=re(u,o.footprintHalfSize,m,i),M=e=>{const t=ue(e);return!!t&&o.wallSilhouettes.some(n=>me(e,t,n,v,!0===o.wallGeometryValidated))},b=!y||M(x);let S=0,$=[0,0],k=null,z=!1,I=y?"ok":"degraded",P=y?null:"invalid-wall-geometry";if(y&&b)if(w)if(w.safePoint){const e=o.rooms.find(e=>e.id===w.id)||null,t=n(w.safePoint,m,i),a=t[0]-g[0],r=t[1]-g[1],s=Math.hypot(a,r);if(s<=K)I="degraded",P="invalid-safe-point";else{const t=a/s,n=r/s,i=Math.min(d,s/l),c=i*l/s,h=[u[0]+(w.safePoint[0]-u[0])*c,u[1]+(w.safePoint[1]-u[1])*c],f=[t*i*l,n*i*l],p=ue([...x,...x.map(e=>[e[0]+f[0],e[1]+f[1]])]),m=p?o.wallSilhouettes.filter(e=>{const t=he(e,!0===o.wallGeometryValidated);return!!t&&fe(p,t,v)}):o.wallSilhouettes,g=!!e&&we(u,h,e),y=e=>{const a=[t*e*l,n*e*l],i=x.map(e=>[e[0]+a[0],e[1]+a[1]]),r=ue(i);return!!r&&m.some(e=>me(i,r,e,v,!0===o.wallGeometryValidated))},M=o.nudgeHintCss;if(Number.isFinite(M)&&M>=0&&M<=i){const t=M*l/s,n=[u[0]+(w.safePoint[0]-u[0])*t,u[1]+(w.safePoint[1]-u[1])*t];(g||e&&we(u,n,e))&&!y(M)&&(S=M,k=!1)}if(null===k){let t=null,n=0,o=!1;const a=Math.ceil(i);for(let r=1;r<=a;r++){const a=Math.min(i,r),c=a*l/s,d=[u[0]+(w.safePoint[0]-u[0])*c,u[1]+(w.safePoint[1]-u[1])*c];if(!(g||e&&we(u,d,e))){o=!0;break}if(!y(a)){t=a;break}n=a}if(null!==t){let e=n,o=t;for(let t=0;t<14;t++){const t=(e+o)/2;y(t)?e=t:o=t}S=o}else S=n,z=!0,I="degraded",P=o?"owner-boundary":"nudge-cap"}$=[t*S*l,n*S*l]}}else I="degraded",P="invalid-safe-point";else I="degraded",P="missing-owner";const C=[g[0]+$[0],g[1]+$[1]],j=re(u,o.footprintHalfSize,m,i,$),N=!y||(k??M(j)),O=S>K,A=O||b||N||!!o.hovered||!!o.focused||!!o.selected;return{plane:f,owner:w,floorAnchor:u,floorScene:h,raisedScene:g,visualScene:C,footprint:j,nudgeScene:$,nudgeCss:[$[0]/l,$[1]/l],nudgeDistanceCss:S,nudged:O,nearWallBefore:b,nearWallAfter:N,cleared:!N,capped:z,grounding:{center:h,visible:!1!==o.filtersSupported},tether:ye(h,C,A),status:I,reason:P}}({kind:i,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:f,ownerAlreadyResolved:!0,resolvedOwner:z,nudgeHintCss:x.hit&&x.value.shapeSignature===y?x.value.placement.nudgeDistanceCss*x.value.unitsPerPixel/s:void 0,showBorders:!0,wallSilhouettes:!1===o.resolveCollisions?[]:o.wallSilhouettes,wallGeometryValidated:!0,footprintHalfSize:h,wallHeight:d,visualOffset:u,sceneUnitsPerCssPixel:s,filtersSupported:o.layers.shadows,hovered:!0,selected:p});return $(g,m,{signature:v,shapeSignature:y,unitsPerPixel:s,placement:I},We),I};for(const e of o.devices){const t=o.positionOf(e),n=o.presentationOf(e,o.showLqi),a=v*n.scale,i=Ie({kind:"device",core:a,presentation:n}),r=e.marker?.room_id||l.find(t=>!!e.area&&t.room.area===e.area)?.overlayRoom.id||null,s=x("device",e.id,[t.x,t.y],i,r,o.selectedDeviceId===e.id);h.set(e.id,s),m.push({id:e.id,kind:"device",placement:s,groundRadius:Math.max(.32*a,2),screenHalfSize:i})}for(const{room:e,overlayRoom:t}of l){if(!o.display.showNames||!e.name)continue;const n=o.labelPositionOf(e,o.space.id),a=.5*y*(o.labelScaleOf(e)*o.kioskFontScale*o.display.cardFontScale),i=Ie({kind:"room-label",font:a,room:e,display:o.display}),r=x("room-label",t.id,[n.x,n.y],i,t.id,o.focusedRoomId===e.id);f.set(e,r),m.push({id:t.id,kind:"room-label",placement:r,groundRadius:Math.max(.75*a,2),screenHalfSize:i})}const M=o.openings.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&"string"==typeof e.lock&&!!e.lock&&o.openingEntityAvailable(e.lock));if(M.length){const e=o.openingWallIndex();for(const t of M){const n=Qe(t,e,o.cellCm),a=n.floorAnchor,i=.62*y,r=Ie({kind:"opening-lock",size:i}),s=x("opening-lock",String(t.id),a,r,n.preferredRoomId,o.selectedOpeningId===t.id);p.set(String(t.id),s),m.push({id:String(t.id),kind:"opening-lock",placement:s,groundRadius:Math.max(.28*i,2),screenHalfSize:r})}}const b={devices:h,rooms:f,locks:p,entries:Object.freeze(m)},k=!1===o.resolveCollisions?"fit":"live";let z=De.get(o.wallSilhouettes);z||(z=new Map,De.set(o.wallSilhouettes,z));const I=z.get(k);return I&&function(e,t){return e.length===t.length&&t.every((t,n)=>{const o=e[n];return o.id===t.id&&o.kind===t.kind&&o.placement===t.placement&&o.groundRadius===t.groundRadius&&o.screenHalfSize[0]===t.screenHalfSize[0]&&o.screenHalfSize[1]===t.screenHalfSize[1]})}(I.entries,b.entries)&&_e(I.devices,b.devices)&&_e(I.rooms,b.rooms)&&_e(I.locks,b.locks)?I:(z.set(k,b),b)}function Ze(e,t,n){return Qe(e,t,n).floorAnchor}function Qe(e,t,n){const o=!e.flip_v,a="gate"===e.type?e.partitionHost?p(e.partitionHost,o):f(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen,flip_v:o}):null,[i,r]=m({x:e.rx,y:e.ry,angle:e.angle,flipV:!!e.flip_v,gateFace:a},n);if(e.partitionHost)return{floorAnchor:i,preferredRoomId:null};const s=g(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen},!0),l=r?"negative":"positive";return{floorAnchor:i,preferredRoomId:s[l]?.roomId||null}}function Je(e){let t=!1;try{t="undefined"!=typeof CSS&&"function"==typeof CSS.supports&&CSS.supports("filter","blur(1px)")}catch{t=!1}let n=!1;try{n="function"==typeof matchMedia&&matchMedia("(forced-colors: active)").matches}catch{n=!0}return function(e){const t=!!e.showBorders;return{structural:t,panels:t&&!e.hideOpenings,shadows:t&&e.filtersSupported&&!e.forcedColors,materialNuance:t&&e.filtersSupported&&!e.forcedColors,floorSymbols:!e.hideOpenings&&!t}}({showBorders:e.showBorders,hideOpenings:e.hideOpenings,filtersSupported:t,forcedColors:n})}function Xe(e,t,n,o){if(!e.panels||!t)return[];return t.openings.flatMap(e=>{const t=n[e.sourceIndex];return t?U(e,o(t)):[]}).sort((e,t)=>e.depth-t.depth||e.sourceIndex-t.sourceIndex||e.leaf-t.leaf)}function Ye(e){const t=Je(e.display),n=t.panels?Xe(t,e.scene,e.openings,e.amountOf):[],o=e.overlays(t),a=t=>({layers:t,panels:n,overlays:o,underlay:it(t,e.scene?.floor,e.cellCm),shadows:rt(t,n,e.scene?.geometry,e.cellCm),walls:st(e.projection,t,e.scene,n,e.cellCm),grounds:ot(o,t,e.cellCm),raised:at(o)});try{return a(t)}catch(e){if(!t.shadows&&!t.materialNuance)throw e;return a({...t,shadows:!1,materialNuance:!1})}}const et=()=>b``;function tt(e){return`translate(${i(4,e)} ${i(8,e)})`}function nt(e,t,n){const o=I(n);return b` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{ds as e,dt as t,a$ as n,du as o,dv as a,m as i,dw as r,dx as s,dy as l,dz as c,a4 as d,dA as f,ah as u,bS as h,bR as p,dB as m,ai as g,Q as w,dC as y,cL as v,dD as x,A as M,w as b,dE as S,dF as $,dG as k,dH as z,dI as I}from"./houseplan-card-Bhpi71t0.js";import{i as P}from"./guard-BgTQLSGB.js";const C=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function j(e){let t=0;for(let n=0;nArray.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])).map(e=>[Number(e[0]),Number(e[1])]),n=t[t.length-1];return t.length>1&&t[0][0]===n[0]&&t[0][1]===n[1]&&t.pop(),t}(e);if(n.length<3)return[];const o=!t;return j(n)>0===o?n:[...n].reverse()}function O(e,t,o){return e.length?`M ${e.map(e=>C(n(e,o,t))).join(" L ")} Z`:""}function A(e,t,n){const o=t[1]-e[1],a=-(t[0]-e[0]),i=n.rotDeg*Math.PI/180;return o*Math.sin(i)+a*Math.cos(i)}function B(t,o,a=e){if(!Number.isFinite(o)||o<0)throw new Error("invalid floor edge height");const i=(t||[]).map(e=>(e||[]).map((e,t)=>function(e,t){const n=N(e,t);if(!n.length)return n;let o=0;for(let e=1;e0)).filter(e=>e.length>=3&&Math.abs(j(e))>=1e-9)).filter(e=>e.length&&j(e[0])>0);i.sort((e,t)=>{const n=e[0][0],o=t[0][0];return n[0]-o[0]||n[1]-o[1]||Math.abs(j(t[0]))-Math.abs(j(e[0]))});const r=[],s=[];let l=0;for(let e=0;ee.depth-t.depth||e.component-t.component||e.edge-t.edge),{footprintPath:r.join(" "),sides:s,componentCount:i.length,edgeCount:l}}function R(e,t){return e^=Math.round(64*(Number.isFinite(t)?t:0)),Math.imul(e,16777619)>>>0}const H=Object.freeze({revision:1,leafThicknessRatio:.04,frameThicknessRatio:.055,gateTurnDeg:10,gateTopRatio:.88,windowBottomRatio:.27,windowTopRatio:.78,doorTopRatio:.92});H.leafThicknessRatio,H.frameThicknessRatio;const F=e=>e.every(Number.isFinite);function T(e,t){return Object.freeze([Object.is(e,-0)?0:e,Object.is(t,-0)?0:t])}function L(e,t){return[e[0]+t[0],e[1]+t[1]]}function V(e,t){return[e[0]-t[0],e[1]-t[1]]}function G(e,t){return[e[0]*t,e[1]*t]}function W(e,t,n,o){const a=e[0]*n,i=e[1]*o,r=t*Math.PI/180;return[a*Math.cos(r)-i*Math.sin(r),a*Math.sin(r)+i*Math.cos(r)]}function E(e,t,n,a,i,r,s){const l=e.flipH?-1:1,c="gate"===e.type?1:e.flipV?-1:1,d=o(e.type,e.flipV,e.angle,e.face);return{leaf:t,hinge:L([e.x+d.ox,e.y+d.oy],W(n,e.angle,l,c)),closedVector:W(a,e.angle,l,c),quarterVector:W([-a[1],a[0]],e.angle,l,c),turnDeg:i,bottom:r,top:s}}const q=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function D(e,t,o,a,i={}){const r=o.map(e=>n(e.point,e.z,a));return Object.freeze({kind:e,material:t,d:`M ${r.map(q).join(" L ")} Z`,depth:Math.max(...r.map(e=>e[1])),...i})}function _(e,t,n,o,a,i,r,s={}){return D(e,t,[{point:n,z:a},{point:o,z:a},{point:o,z:i},{point:n,z:i}],r,s)}function U(t,o,a=e){const i=Math.max(0,Math.min(1,Number.isFinite(o)?o:0));return t.leaves.map(e=>{const o=function(e,t){const n=e.turnDeg*t*Math.PI/180;return[e.hinge[0]+e.closedVector[0]*Math.cos(n)+e.quarterVector[0]*Math.sin(n),e.hinge[1]+e.closedVector[1]*Math.cos(n)+e.quarterVector[1]*Math.sin(n)]}(e,i),r=n(e.hinge,e.bottom,a),s=n(o,e.bottom,a),l=n(o,e.top,a),c=n(e.hinge,e.top,a),d="window"===t.type?"light-window":"matte-leaf",f="window"===t.type?Object.freeze([_("window-insert","light-window",e.hinge,o,e.bottom,e.top,a)]):function(e,t,n,o){const a=V(t,e.hinge),i=Math.hypot(a[0],a[1]);if(!(i>1e-9&&n>0))return Object.freeze([]);const r=T(-a[1]*n/(2*i),a[0]*n/(2*i)),s=L(e.hinge,r),l=L(t,r),c=V(e.hinge,r),d=V(t,r),f=[_("leaf-back","matte-leaf",d,c,e.bottom,e.top,o),_("leaf-front","matte-leaf",s,l,e.bottom,e.top,o),_("leaf-edge","matte-leaf",c,s,e.bottom,e.top,o,{edge:"hinge"}),_("leaf-edge","matte-leaf",l,d,e.bottom,e.top,o,{edge:"tip"}),D("leaf-top","matte-leaf",[{point:s,z:e.top},{point:c,z:e.top},{point:d,z:e.top},{point:l,z:e.top}],o)];return Object.freeze(f.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||String(e.edge||"").localeCompare(String(t.edge||""))))}(e,o,t.leafThickness,a);return Object.freeze({id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${q(r)} L ${q(s)} L ${q(l)} L ${q(c)} Z`,shadowD:`M ${q(n(e.hinge,0,a))} L ${q(n(o,0,a))}`,depth:Math.max(r[1],s[1]),material:d,thickness:"window"===t.type?0:t.leafThickness,surfaces:f})})}const K=1e-9,Z=e=>e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function Q(e){let t=0;for(let n=0;n=3&&e.every(Z)&&Math.abs(Q(e))>K}function X(e,t,n){const o=n[0]-t[0],a=n[1]-t[1],i=o*o+a*a,r=i?Math.max(0,Math.min(1,((e[0]-t[0])*o+(e[1]-t[1])*a)/i)):0;return Math.hypot(e[0]-t[0]-r*o,e[1]-t[1]-r*a)}function Y(e,t,n=1e-7){for(let o=0;oe[1]!=r[1]>e[1]&&e[0]<(r[0]-i[0])*(e[1]-i[1])/(r[1]-i[1])+i[0]&&(n=!n)}return n}function te(e){return Math.max(0,Math.abs(Q(e.outer))-(e.holes||[]).reduce((e,t)=>e+Math.abs(Q(t)),0))}function ne(e){return!!e.id&&J(e.outer)&&(e.holes||[]).every(J)&&te(e)>K}function oe(e,t){if(!ne(t)||Y(e,t.outer)||!ee(e,t.outer))return!1;for(const n of t.holes||[])if(Y(e,n)||ee(e,n))return!1;return!0}function ae(e){if(!ne(e))return null;if(e.safePoint&&oe(e.safePoint,e))return[e.safePoint[0],e.safePoint[1]];const t=e.outer.map(e=>e[0]),n=e.outer.map(e=>e[1]),o=Math.min(...t),a=Math.max(...t),i=Math.min(...n),r=Math.max(...n),s=[[(o+a)/2,(i+r)/2],[t.reduce((e,t)=>e+t,0)/t.length,n.reduce((e,t)=>e+t,0)/n.length]];for(let t=0;t{if(!oe(t,e))return;const n=function(e,t){let n=1/0;for(const o of[t.outer,...t.holes||[]])for(let t=0;tc+K&&(l=t,c=n)};s.forEach(d);for(let e=1;e<16;e++)for(let t=1;t<16;t++)d([o+(a-o)*e/16,i+(r-i)*t/16]);return l}function ie(e){if(!Z(e.floorAnchor))return null;const t=e.roomsValidated?e.rooms:e.rooms.filter(ne),n=e.preferredRoomId&&t.find(t=>t.id===e.preferredRoomId)||null;let o=null;return"device"===e.kind?(n&&oe(e.floorAnchor,n)&&(o=n),o||(o=t.filter(t=>oe(e.floorAnchor,t)).sort((e,t)=>te(e)-te(t)||((e,t)=>et?1:0)(e.id,t.id))[0]||null)):o=n,o?{id:o.id,area:te(o),safePoint:e.roomsValidated&&o.safePoint?[o.safePoint[0],o.safePoint[1]]:ae(o)}:null}function re(t,o,a,i=e,r=[0,0]){if(!Z(t)||!Z(o)||o[0]<0||o[1]<0||!Number.isFinite(a)||!Z(r))throw new Error("invalid isometric overlay footprint");return[[t[0]-o[0],t[1]-o[1]],[t[0]+o[0],t[1]-o[1]],[t[0]+o[0],t[1]+o[1]],[t[0]-o[0],t[1]+o[1]]].map(e=>{const t=n(e,a,i);return[t[0]+r[0],t[1]+r[1]]})}function se(e,t,n){return(t[0]-e[0])*(n[1]-e[1])-(t[1]-e[1])*(n[0]-e[0])}function le(e,t,n,o){const a=se(e,t,n),i=se(e,t,o),r=se(n,o,e),s=se(n,o,t);return(a>K&&i<-K||a<-K&&i>K)&&(r>K&&s<-K||r<-K&&s>K)||(Math.abs(a)<=K&&X(n,e,t)<=K||Math.abs(i)<=K&&X(o,e,t)<=K||Math.abs(r)<=K&&X(e,n,o)<=K||Math.abs(s)<=K&&X(t,n,o)<=K)}function ce(e,t,n,o){return le(e,t,n,o)?0:Math.min(X(e,n,o),X(t,n,o),X(n,e,t),X(o,e,t))}const de=new WeakMap;function fe(e){if(!e.length)return null;let t=1/0,n=1/0,o=-1/0,a=-1/0;for(const i of e){if(!Z(i))return null;t=Math.min(t,i[0]),n=Math.min(n,i[1]),o=Math.max(o,i[0]),a=Math.max(a,i[1])}return[t,n,o,a]}function ue(e,t){if(!t)return fe(e.outer);if(de.has(e))return de.get(e)??null;const n=fe(e.outer);return de.set(e,n),n}function he(e,t,n){return e[0]<=t[2]+n&&e[2]>=t[0]-n&&e[1]<=t[3]+n&&e[3]>=t[1]-n}function pe(e,t,n,o){return Math.min(t[0],n[0])<=e[2]+o&&Math.max(t[0],n[0])>=e[0]-o&&Math.min(t[1],n[1])<=e[3]+o&&Math.max(t[1],n[1])>=e[1]-o}function me(e,t,n,o,a){const i=ue(n,a);if(!i||!he(t,i,o))return!1;if(e.some(e=>function(e,t){return!!ee(e,t.outer)&&!(t.holes||[]).some(t=>ee(e,t))}(e,n)))return!0;if(n.outer.some(n=>n[0]>=t[0]&&n[0]<=t[2]&&n[1]>=t[1]&&n[1]<=t[3]&&ee(n,e)))return!0;for(const a of[n.outer,...n.holes||[]])for(let n=0;n"wall-side"===e.layer?0:"wall-top"===e.layer?1:2,Me=e=>{if("wall-side"===e.layer)return`${e.face.polygon}:${e.face.ring}:${e.face.edge}`;if("wall-top"===e.layer)return String(e.face.component);const t=e.surface;return`${t.sourceIndex}:${t.leaf??-1}:${t.kind}:${t.jamb??-1}:${t.edge??""}:${t.id}:${t.material}`};function be(e,t){const n=[...e.sides.map(e=>({layer:"wall-side",depth:e.depth,face:e})),...e.topFaces.map(e=>({layer:"wall-top",depth:e.depth,face:e})),...t.map(e=>({layer:"opening",depth:e.depth,surface:e}))];return n.sort((e,t)=>e.depth-t.depth||xe(e)-xe(t)||Me(e).localeCompare(Me(t))),Object.freeze(n)}const Se=Object.freeze({textLatinAdvance:.72,textWideAsciiAdvance:1,textWideAdvance:1.1,textSpaceAdvance:.4,textWidthSafety:1.08,deviceShellInset:.134375,deviceShellGap:.1,deviceSectionGap:.08,deviceBadgeMinWidth:.7875,deviceBadgeHeight:.7875,deviceBadgeInlinePadding:.28,deviceValueInlinePadding:.32,deviceAuxiliaryExtent:.7,deviceLqiFontSize:.38,deviceLqiTop:.734375,deviceLqiBelowBottomBadgeTop:1.571875,devicePadding:.08,roomNameLineHeight:1.25,roomAreaLinkWidth:1.1,roomMetricsTopGap:.15,roomMetricFontSize:.75,roomMetricLineHeight:1.25,roomMetricIconWidth:1.05,roomMetricInnerGap:.12,roomMetricRowGap:.55,roomMetricMinWidth:11,roomPadding:.4,openingLockHalfSize:.62,roomMetricTextCharacters:Object.freeze({temperature:10,humidity:8,lqi:6,light:24})});function $e(e){return[...String(e)].reduce((e,t)=>/\s/.test(t)?e+Se.textSpaceAdvance:/[MW@#%&]/.test(t)?e+Se.textWideAsciiAdvance:e+(t.codePointAt(0)>255?Se.textWideAdvance:Se.textLatinAdvance),0)*Se.textWidthSafety}function ke(e,t){return $e(e)*z(t||e)}function ze(e,t){return[Math.max(Math.abs(e.left),Math.abs(e.right))+t,Math.max(Math.abs(e.top),Math.abs(e.bottom))+t]}function Ie(e){if("opening-lock"===e.kind){const t=(Number.isFinite(e.size)&&e.size>0?e.size:0)*Se.openingLockHalfSize;return[t,t]}if("room-label"===e.kind){const t=Number.isFinite(e.font)&&e.font>0?e.font:0,n=v(e.room.settings?.name_scale),o=v(e.room.settings?.label_scale),a=($e(e.room.name||"")+(e.room.area?Se.roomAreaLinkWidth:0))*n,i=Se.roomNameLineHeight*n,r=[e.display.labelTemp?Se.roomMetricTextCharacters.temperature:0,e.display.labelHum?Se.roomMetricTextCharacters.humidity:0,e.display.labelLqi&&e.room.area?Se.roomMetricTextCharacters.lqi:0,e.display.labelLight?Se.roomMetricTextCharacters.light:0].filter(e=>e>0),s=Se.roomMetricFontSize*o,l=r.length?Math.max(Se.roomMetricMinWidth,r.reduce((e,t)=>e+Se.roomMetricIconWidth+Se.roomMetricInnerGap+t*Se.textLatinAdvance*Se.textWidthSafety,0)+(r.length-1)*Se.roomMetricRowGap)*s:0,c=r.length?s*Se.roomMetricLineHeight:0,d=ze({left:-Math.max(a,l)/2,right:Math.max(a,l)/2,top:-i/2,bottom:r.length?i/2+Se.roomMetricsTopGap+c:i/2},Se.roomPadding);return[d[0]*t,d[1]*t]}const t=Number.isFinite(e.core)&&e.core>0?e.core:0,n=e.presentation,o=null==n.valueText?1:Math.max(1,ke(n.valueText,n.valueFullText||n.valueText)+Se.deviceValueInlinePadding),a=[];n.valueBadge&&a.push(Math.max(Se.deviceBadgeMinWidth,ke(n.valueBadge.text,n.valueBadge.fullText||n.valueBadge.text)+Se.deviceBadgeInlinePadding));for(const e of x(n)){const t=e.text+e.suffix;a.push(Math.max(Se.deviceBadgeMinWidth,ke(t,t)+Se.deviceBadgeInlinePadding))}const i=n.valueBadge?.position||"right";let r;if(!a.length||"left"!==i&&"right"!==i)if(a.length){const e=a.reduce((e,t)=>e+t,0)+(a.length-1)*Se.deviceSectionGap,t=Math.max(o,e),n=1+Se.deviceShellGap+Se.deviceBadgeHeight;r="bottom"===i?{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:-.5+n+Se.deviceShellInset}:{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:.5-n-Se.deviceShellInset,bottom:.5+Se.deviceShellInset}}else r={left:-.5-Se.deviceShellInset,right:-.5+o+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:.5+Se.deviceShellInset};else{const e=Math.max(...a),t=a.length*Se.deviceBadgeHeight+(a.length-1)*Se.deviceSectionGap,n=o+Se.deviceShellGap+e,s=Math.max(1,t);r="right"===i?{left:-.5-Se.deviceShellInset,right:-.5+n+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}:{left:.5-n-Se.deviceShellInset,right:.5+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}}const s=Se.deviceAuxiliaryExtent;if(r.left=Math.min(r.left,-s),r.right=Math.max(r.right,s),r.top=Math.min(r.top,-s),r.bottom=Math.max(r.bottom,s),n.pulse.animated){const e=Math.max(1,n.pulse.diameterScale)/2;r.left=Math.min(r.left,-e),r.right=Math.max(r.right,e),r.top=Math.min(r.top,-e),r.bottom=Math.max(r.bottom,e)}if(null!=n.lqiText){const e="bottom"===n.valueBadge?.position?Se.deviceLqiBelowBottomBadgeTop:Se.deviceLqiTop,t=$e(n.lqiText)*Se.deviceLqiFontSize/2;r.left=Math.min(r.left,-t),r.right=Math.max(r.right,t),r.bottom=Math.max(r.bottom,e+Se.deviceLqiFontSize)}const l=ze(r,Se.devicePadding);return[l[0]*t,l[1]*t]}function Pe(e,t){return e.flatMap((e,n)=>e.orphanReason?[]:[{id:String(e.id||n),sourceIndex:n,type:e.type,x:e.rx,y:e.ry,angle:Number(e.angle)||0,length:e.rlen>0?e.rlen:.9*t,flipH:!!e.flip_h,flipV:!!e.flip_v}])}function Ce(e){return{id:e.id,x:e.x,y:e.y,w:e.w,h:e.h,poly:e.poly,wall_ids:e.wall_ids}}function je(e,t){const n=e?.partitionHost;if(!n)return null;const o="gate"===t.type?!t.flipV:t.flipV;return{sourceIndex:t.sourceIndex,hostId:n.host.id,t:n.t,depth:n.depth,face:p(n,o)}}function Ne(n,o=H){const a=Pe(n.openings,n.coordinateScale),r=a.map(e=>je(n.openings[e.sourceIndex],e)),p=i(t,n.cellCm),m=i(s,n.cellCm),g=i(l,n.cellCm);return{key:`${n.space.id}|${function(e){let t=2166136261;const n=e=>{if("number"!=typeof e)if("string"!=typeof e)if("boolean"!=typeof e)if(Array.isArray(e)){t=R(t,e.length);for(const t of e)n(t)}else{if(e&&"object"==typeof e){const t=e;for(const e of Object.keys(t).sort())n(e),n(t[e]);return}t=R(t,-1)}else t=R(t,e?1:0);else for(const n of e)t=R(t,n.codePointAt(0)||0);else t=R(t,e)};return n(e),t.toString(36)}({rooms:n.space.rooms.map(Ce),walls:n.walls,openCuts:n.openCuts,openings:a,openingHosts:r,openingGeometryPolicy:o,partitions:n.space.partitions,roomDrafts:n.space.room_drafts,columns:n.space.wall_columns,cellCm:n.cellCm,gridPitch:n.gridPitch,wallKeyPitch:n.wallKeyPitch,camera:e,wallHeight:p,raisedHeight:g,floorEdgeHeight:m,algorithm:4})}`,build:()=>{n.onBuild();const i=c(n.space,n.cellCm,n.gridPitch,2e-4*n.gridPitch,n.partitionCuts()).all,s=n.roomOpenings(),l=n.walls.length||i.length?d(n.space.rooms,n.walls,n.openCuts,s,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale,i):null;if(l&&("failed-core"===l.status||"not-applicable"===l.status))throw new Error("wall boolean geometry failed");const m=l?.paperGeom??f(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale);if(!m)throw new Error("floor boolean geometry failed");const g=l?.openingIndex||u(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale),w=a.map((e,a)=>{const i=r[a],s="gate"===e.type?!e.flipV:e.flipV,l=i?i.face:n.walls.length||"gate"===e.type?h(g,{x:e.x,y:e.y,angle:e.angle,length:e.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(e,n=t,o=H){const a=e.face.cm??0;if(!F([e.x,e.y,e.angle,e.length,e.face.ox,e.face.oy,a,n])||!(e.length>0)||!(n>0)||-1!==e.face.side&&1!==e.face.side||a<0)throw new Error("invalid isometric opening input");const i=e.length/2,r=e.angle*Math.PI/180,s=T(Math.cos(r),Math.sin(r)),l=T(-Math.sin(r),Math.cos(r)),c=T(e.x,e.y),d=T(e.x-s[0]*i,e.y-s[1]*i),f=T(e.x+s[0]*i,e.y+s[1]*i),u=T(e.face.ox,e.face.oy),h=T(d[0]+u[0],d[1]+u[1]),p=T(f[0]+u[0],f[1]+u[1]),m=T(d[0]-u[0],d[1]-u[1]),g=T(f[0]-u[0],f[1]-u[1]),w=Object.freeze({center:c,tangent:s,normal:l,start:d,end:f}),y=Object.freeze({side:e.face.side,cm:a,depth:2*Math.hypot(e.face.ox,e.face.oy),offset:u,selectedStart:h,selectedEnd:p,oppositeStart:m,oppositeEnd:g}),v="passage"===e.type?[]:[Object.freeze({jamb:0,center:d,selected:h,opposite:m}),Object.freeze({jamb:1,center:f,selected:p,opposite:g})];let x;if("passage"===e.type)x=[];else if("gate"===e.type){const t=e.face.side*o.gateTurnDeg;x=[E(e,0,[-i,0],[i,0],t,0,n*o.gateTopRatio),E(e,1,[i,0],[-i,0],-t,0,n*o.gateTopRatio)]}else x="window"===e.type?[E(e,0,[-i,0],[i,0],-90,n*o.windowBottomRatio,n*o.windowTopRatio),E(e,1,[i,0],[-i,0],90,n*o.windowBottomRatio,n*o.windowTopRatio)]:[E(e,0,[-i,0],[e.length,0],-90,0,n*o.doorTopRatio)];return Object.freeze({id:e.id,sourceIndex:e.sourceIndex,type:e.type,wallHeight:n,leafThickness:n*o.leafThicknessRatio,frameThickness:n*o.frameThicknessRatio,axis:w,face:y,reveals:Object.freeze(v),leaves:Object.freeze(x.map(e=>Object.freeze({...e,hinge:T(e.hinge[0],e.hinge[1]),closedVector:T(e.closedVector[0],e.closedVector[1]),quarterVector:T(e.quarterVector[0],e.quarterVector[1])})))})}({...e,face:l},p,o)}),y=Object.freeze(w);return{walls:l?.components.flatMap(e=>e.geom)||[],floor:m,openings:y,openingSurfaces:Object.freeze(y.flatMap(t=>function(t,n=e){if("passage"===t.type)return Object.freeze([]);const o=[];if(t.face.depth>1e-9)for(const e of t.reveals)o.push(_("jamb-reveal","reveal",e.selected,e.opposite,0,t.wallHeight,n,{jamb:e.jamb}));if("window"!==t.type||!t.leaves.length)return Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)));const a=Math.min(...t.leaves.map(e=>e.bottom)),i=Math.max(...t.leaves.map(e=>e.top)),r=Math.min(t.frameThickness,Math.hypot(t.axis.end[0]-t.axis.start[0],t.axis.end[1]-t.axis.start[1])/4,(i-a)/4),s=L(t.axis.start,G(t.axis.tangent,r)),l=V(t.axis.end,G(t.axis.tangent,r)),c=t.face.depth>1e-9?[t.face.offset,T(-t.face.offset[0],-t.face.offset[1])]:[t.face.offset];for(const e of c){const c=L(t.axis.start,e),d=L(t.axis.end,e),f=L(s,e),u=L(l,e);o.push(_("window-frame-side","light-frame",c,f,a,i,n,{jamb:0}),_("window-frame-side","light-frame",u,d,a,i,n,{jamb:1}),_("window-frame-top","light-frame",f,u,Math.max(a,i-r),i,n))}return t.face.depth>1e-9&&o.push(D("window-sill","light-sill",[{point:t.face.selectedStart,z:a},{point:t.face.selectedEnd,z:a},{point:t.face.oppositeEnd,z:a},{point:t.face.oppositeStart,z:a}],n)),Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)))}(t).map(e=>Object.freeze({...e,id:t.id,sourceIndex:t.sourceIndex,type:t.type}))))}}}}const Oe=e=>Array.isArray(e)?e:[];function Ae(e,t){const o=e=>Oe(e).flatMap(e=>Array.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])?[n([Number(e[0]),Number(e[1])],t)]:[]);return Oe(e).flatMap(e=>{const t=Oe(e);if(!t.length)return[];const n=o(t[0]);if(n.length<3)return[];return[{outer:n,holes:t.slice(1).map(o).filter(e=>e.length>=3)}]})}function Be(o){const a=i(t,o.cellCm),r=i(s,o.cellCm),c=i(l,o.cellCm),d=S(o.cache,o.source.key);let f=d.hit?d.value:void 0;if(!f){const i=o.source.build(),s=function(o,a=e,i=t){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const r=[],s=[],l=[],c=[];let d=0;for(let e=0;e<(o||[]).length;e++){const t=o[e],f=[];let u=-1/0;for(let o=0;o<(t||[]).length;o++){const s=N(t[o],o>0);if(s.length<3||Math.abs(j(s))<1e-9)continue;const h=O(s,a,i);r.push(h),f.push(h),u=Math.max(u,...s.map(e=>n(e,i,a)[1])),d+=s.length;for(let t=0;te.depth-t.depth||e.polygon-t.polygon||e.ring-t.ring||e.edge-t.edge),s.sort((e,t)=>e.depth-t.depth||e.component-t.component),{topPath:r.join(" "),topFaces:s,sides:l,contactPath:c.join(" "),edgeCount:d}}(i.walls,e,a),l=Ae(i.walls,a);f={geometry:s,floor:B(i.floor,r),wallSilhouettes:Object.freeze([...l,...s.sides.map(e=>({outer:e.points}))]),openings:i.openings,openingSurfaces:i.openingSurfaces},$(o.cache,o.source.key,f,8)}const u=function(e){let t=1/0,n=1/0,o=-1/0,a=-1/0;const i=(e,i=0)=>{t=Math.min(t,e[0]-i),n=Math.min(n,e[1]-i),o=Math.max(o,e[0]+i),a=Math.max(a,e[1]+i)};for(const t of e)if("passage"!==t.type){i(t.axis.start),i(t.axis.end),i(t.face.selectedStart),i(t.face.selectedEnd),i(t.face.oppositeStart),i(t.face.oppositeEnd);for(const e of t.leaves){const n=Math.hypot(e.closedVector[0],e.closedVector[1])+t.leafThickness/2;i(e.hinge,n)}}return F([t,n,o,a])?{x:t,y:n,w:o-t,h:a-n}:null}(f.openings),h=u?Re(o.liveFrame,u):o.liveFrame,p=k({rect:h,wallHeight:a,openingHeight:a,floorDepth:r,raisedHeight:c});return{key:o.source.key,...f,frame:p}}const Re=(e,t)=>{const n=Math.min(e.x,t.x),o=Math.min(e.y,t.y);return{x:n,y:o,w:Math.max(e.x+e.w,t.x+t.w)-n,h:Math.max(e.y+e.h,t.y+t.h)-o}},He=e=>{if(!e.length||!e.every(e=>Number.isFinite(e[0])&&Number.isFinite(e[1])))return null;const t=e.map(e=>e[0]),n=e.map(e=>e[1]),o=Math.min(...t),a=Math.min(...n);return{x:o,y:a,w:Math.max(...t)-o,h:Math.max(...n)-a}},Fe=(e,t)=>{const n=e.placement,o=t?n.visualScene:n.raisedScene,[a,i]=e.screenHalfSize,r=t?n.footprint:n.footprint.map(e=>[e[0]-n.nudgeScene[0],e[1]-n.nudgeScene[1]]);return[n.floorScene,...r,[o[0]-a,o[1]-i],[o[0]+a,o[1]-i],[o[0]+a,o[1]+i],[o[0]-a,o[1]+i]]},Te=(e,t)=>void 0===t?e:e.filter(e=>e.placement.owner?.id===t);function Le(e,t){return e?He(Te(e.entries,t).flatMap(e=>Fe(e,!0))):null}function Ve(e){const t=Te(e.entries,e.ownerId),n=He(t.flatMap(e=>Fe(e,!1))),o=n?Re(e.baseBounds,n):e.baseBounds,a=e.targetView(o);if(!(a&&a.w>0&&a.h>0&&[a.x,a.y,a.w,a.h].every(Number.isFinite)))return null;const i=e.stageSize;if(!(n&&i&&i.width>0&&i.height>0))return{bounds:o,view:a};const r=e=>Math.max(e.w/i.width,e.h/i.height),s=t=>{const o=48*t,a={x:n.x-o,y:n.y-o,w:n.w+2*o,h:n.h+2*o},i=Re(e.baseBounds,a),r=e.targetView(i);return r&&[r.x,r.y,r.w,r.h].every(Number.isFinite)&&r.w>0&&r.h>0?{bounds:i,view:r}:null};let l=0,c=Math.max(r(a),Number.EPSILON),d=s(c);for(let e=0;d&&r(d.view)>c*(1+1e-10)&&e<24;e++)l=c,c*=2,d=s(c);if(!d)return null;for(let e=0;e<40;e++){const e=(l+c)/2,t=s(e);if(!t)return null;r(t.view)<=e?(c=e,d=t):l=e}return d}const Ge=new WeakMap,We=2048,Ee=new WeakMap,qe=new WeakMap,De=new WeakMap;function _e(e,t){if(e.size!==t.size)return!1;for(const[n,o]of t)if(e.get(n)!==o)return!1;return!0}function Ue(e){const t=Ge.get(e.rooms);if(t)return t;const n=e.rooms.flatMap((e,t)=>{const n=w(e);return n&&n.length>=3?[{room:e,index:t,poly:n}]:[]}),o=Object.freeze(n.map(({room:e,index:t,poly:o})=>{const a=y(o,n.filter(e=>e.index!==t).map(e=>e.poly)),i={id:e.id||`room-index-${t}`,outer:o.map(e=>[e[0],e[1]]),holes:a.map(e=>e.map(e=>[e[0],e[1]]))};return{room:e,overlayRoom:{...i,safePoint:ae(i)||void 0}}}));return Ge.set(e.rooms,o),o}function Ke(o){const s=o.stageSize&&o.stageSize.width>0&&o.stageSize.height>0?Math.max(o.view.w/o.stageSize.width,o.view.h/o.stageSize.height):Math.max(o.view.w,o.view.h)/1e3,l=Ue(o.space),c=l.map(e=>e.overlayRoom),d=i(t,o.cellCm),f=i(a,o.cellCm),u=new Map,h=new Map,p=new Map,m=[];let g=Ee.get(o.wallSilhouettes);g||(g=new Map,Ee.set(o.wallSilhouettes,g));let w=qe.get(l);w||(w=new Map,qe.set(l,w));const y=o.iconPct*r(o.space)*o.kioskIconScale/100,v=o.deviceBasePct*r(o.space)*o.kioskIconScale/100,x=(i,r,l,u,h,p=!1)=>{const m=`${!1===o.resolveCollisions?"fit":"live"}\0${i}\0${r}`,y=[l[0],l[1],u[0],u[1],h||"",d,f,o.layers.shadows?1:0,p?1:0].join("|"),v=`${y}|${s}`,x=S(g,m);if(x.hit&&x.value.signature===v)return x.value.placement;if(x.hit&&x.value.shapeSignature===y&&s<=x.value.unitsPerPixel){const e=x.value.placement,t=e.nudgeDistanceCss*x.value.unitsPerPixel/s;if(!e.nearWallBefore||e.cleared&&t<=48)return e}const M=`${i}\0${r}`,b=[l[0],l[1],h||""].join("|"),k=S(w,M),z=k.hit&&k.value.signature===b?k.value.owner:ie({kind:i,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:h});k.hit&&k.value.signature===b||$(w,M,{signature:b,owner:z},We);const I=function(o){const i=o.camera||e,r=o.wallHeight??t,s=o.visualOffset??a,l=o.sceneUnitsPerCssPixel??1,c=o.safetyGapCssPx??4,d=o.maxNudgeCssPx??48;if(!Z(o.floorAnchor)||!Z(o.footprintHalfSize)||o.footprintHalfSize[0]<0||o.footprintHalfSize[1]<0||!Number.isFinite(r)||r<0||!Number.isFinite(s)||s<0||!Number.isFinite(l)||l<=0||!Number.isFinite(c)||c<0||!Number.isFinite(d)||d<0)throw new Error("invalid isometric overlay input");const f=[o.floorAnchor[0],o.floorAnchor[1]],u=n(f,0,i),h=(p=o.kind,!o.showBorders||"device"!==p&&"room-label"!==p&&"opening-lock"!==p?"floor":"raised");var p;if("floor"===h)return{plane:h,owner:null,floorAnchor:f,floorScene:u,raisedScene:u,visualScene:u,footprint:[],nudgeScene:[0,0],nudgeCss:[0,0],nudgeDistanceCss:0,nudged:!1,nearWallBefore:!1,nearWallAfter:!1,cleared:!0,capped:!1,grounding:{center:u,visible:!1},tether:ye(u,u,!1),status:"ok",reason:null};const m=r+s,g=n(f,m,i),w=o.ownerAlreadyResolved?o.resolvedOwner??null:ie(o),y=o.wallGeometryValidated??o.wallSilhouettes.every(ge),v=c*l,x=re(f,o.footprintHalfSize,m,i),M=e=>{const t=fe(e);return!!t&&o.wallSilhouettes.some(n=>me(e,t,n,v,!0===o.wallGeometryValidated))},b=!y||M(x);let S=0,$=[0,0],k=null,z=!1,I=y?"ok":"degraded",P=y?null:"invalid-wall-geometry";if(y&&b)if(w)if(w.safePoint){const e=o.rooms.find(e=>e.id===w.id)||null,t=n(w.safePoint,m,i),a=t[0]-g[0],r=t[1]-g[1],s=Math.hypot(a,r);if(s<=K)I="degraded",P="invalid-safe-point";else{const t=a/s,n=r/s,i=Math.min(d,s/l),c=i*l/s,u=[f[0]+(w.safePoint[0]-f[0])*c,f[1]+(w.safePoint[1]-f[1])*c],h=[t*i*l,n*i*l],p=fe([...x,...x.map(e=>[e[0]+h[0],e[1]+h[1]])]),m=p?o.wallSilhouettes.filter(e=>{const t=ue(e,!0===o.wallGeometryValidated);return!!t&&he(p,t,v)}):o.wallSilhouettes,g=!!e&&we(f,u,e),y=e=>{const a=[t*e*l,n*e*l],i=x.map(e=>[e[0]+a[0],e[1]+a[1]]),r=fe(i);return!!r&&m.some(e=>me(i,r,e,v,!0===o.wallGeometryValidated))},M=o.nudgeHintCss;if(Number.isFinite(M)&&M>=0&&M<=i){const t=M*l/s,n=[f[0]+(w.safePoint[0]-f[0])*t,f[1]+(w.safePoint[1]-f[1])*t];(g||e&&we(f,n,e))&&!y(M)&&(S=M,k=!1)}if(null===k){let t=null,n=0,o=!1;const a=Math.ceil(i);for(let r=1;r<=a;r++){const a=Math.min(i,r),c=a*l/s,d=[f[0]+(w.safePoint[0]-f[0])*c,f[1]+(w.safePoint[1]-f[1])*c];if(!(g||e&&we(f,d,e))){o=!0;break}if(!y(a)){t=a;break}n=a}if(null!==t){let e=n,o=t;for(let t=0;t<14;t++){const t=(e+o)/2;y(t)?e=t:o=t}S=o}else S=n,z=!0,I="degraded",P=o?"owner-boundary":"nudge-cap"}$=[t*S*l,n*S*l]}}else I="degraded",P="invalid-safe-point";else I="degraded",P="missing-owner";const C=[g[0]+$[0],g[1]+$[1]],j=re(f,o.footprintHalfSize,m,i,$),N=!y||(k??M(j)),O=S>K,A=O||b||N||!!o.hovered||!!o.focused||!!o.selected;return{plane:h,owner:w,floorAnchor:f,floorScene:u,raisedScene:g,visualScene:C,footprint:j,nudgeScene:$,nudgeCss:[$[0]/l,$[1]/l],nudgeDistanceCss:S,nudged:O,nearWallBefore:b,nearWallAfter:N,cleared:!N,capped:z,grounding:{center:u,visible:!1!==o.filtersSupported},tether:ye(u,C,A),status:I,reason:P}}({kind:i,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:h,ownerAlreadyResolved:!0,resolvedOwner:z,nudgeHintCss:x.hit&&x.value.shapeSignature===y?x.value.placement.nudgeDistanceCss*x.value.unitsPerPixel/s:void 0,showBorders:!0,wallSilhouettes:!1===o.resolveCollisions?[]:o.wallSilhouettes,wallGeometryValidated:!0,footprintHalfSize:u,wallHeight:d,visualOffset:f,sceneUnitsPerCssPixel:s,filtersSupported:o.layers.shadows,hovered:!0,selected:p});return $(g,m,{signature:v,shapeSignature:y,unitsPerPixel:s,placement:I},We),I};for(const e of o.devices){const t=o.positionOf(e),n=o.presentationOf(e,o.showLqi),a=v*n.scale,i=Ie({kind:"device",core:a,presentation:n}),r=e.marker?.room_id||l.find(t=>!!e.area&&t.room.area===e.area)?.overlayRoom.id||null,s=x("device",e.id,[t.x,t.y],i,r,o.selectedDeviceId===e.id);u.set(e.id,s),m.push({id:e.id,kind:"device",placement:s,groundRadius:Math.max(.32*a,2),screenHalfSize:i})}for(const{room:e,overlayRoom:t}of l){if(!o.display.showNames||!e.name)continue;const n=o.labelPositionOf(e,o.space.id),a=.5*y*(o.labelScaleOf(e)*o.kioskFontScale*o.display.cardFontScale),i=Ie({kind:"room-label",font:a,room:e,display:o.display}),r=x("room-label",t.id,[n.x,n.y],i,t.id,o.focusedRoomId===e.id);h.set(e,r),m.push({id:t.id,kind:"room-label",placement:r,groundRadius:Math.max(.75*a,2),screenHalfSize:i})}const M=o.openings.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&"string"==typeof e.lock&&!!e.lock&&o.openingEntityAvailable(e.lock));if(M.length){const e=o.openingWallIndex();for(const t of M){const n=Qe(t,e,o.cellCm),a=n.floorAnchor,i=.62*y,r=Ie({kind:"opening-lock",size:i}),s=x("opening-lock",String(t.id),a,r,n.preferredRoomId,o.selectedOpeningId===t.id);p.set(String(t.id),s),m.push({id:String(t.id),kind:"opening-lock",placement:s,groundRadius:Math.max(.28*i,2),screenHalfSize:r})}}const b={devices:u,rooms:h,locks:p,entries:Object.freeze(m)},k=!1===o.resolveCollisions?"fit":"live";let z=De.get(o.wallSilhouettes);z||(z=new Map,De.set(o.wallSilhouettes,z));const I=z.get(k);return I&&function(e,t){return e.length===t.length&&t.every((t,n)=>{const o=e[n];return o.id===t.id&&o.kind===t.kind&&o.placement===t.placement&&o.groundRadius===t.groundRadius&&o.screenHalfSize[0]===t.screenHalfSize[0]&&o.screenHalfSize[1]===t.screenHalfSize[1]})}(I.entries,b.entries)&&_e(I.devices,b.devices)&&_e(I.rooms,b.rooms)&&_e(I.locks,b.locks)?I:(z.set(k,b),b)}function Ze(e,t,n){return Qe(e,t,n).floorAnchor}function Qe(e,t,n){const o=!e.flip_v,a="gate"===e.type?e.partitionHost?p(e.partitionHost,o):h(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen,flip_v:o}):null,[i,r]=m({x:e.rx,y:e.ry,angle:e.angle,flipV:!!e.flip_v,gateFace:a},n);if(e.partitionHost)return{floorAnchor:i,preferredRoomId:null};const s=g(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen},!0),l=r?"negative":"positive";return{floorAnchor:i,preferredRoomId:s[l]?.roomId||null}}function Je(e){let t=!1;try{t="undefined"!=typeof CSS&&"function"==typeof CSS.supports&&CSS.supports("filter","blur(1px)")}catch{t=!1}let n=!1;try{n="function"==typeof matchMedia&&matchMedia("(forced-colors: active)").matches}catch{n=!0}return function(e){const t=!!e.showBorders;return{structural:t,panels:t&&!e.hideOpenings,shadows:t&&e.filtersSupported&&!e.forcedColors,materialNuance:t&&e.filtersSupported&&!e.forcedColors,floorSymbols:!e.hideOpenings&&!t}}({showBorders:e.showBorders,hideOpenings:e.hideOpenings,filtersSupported:t,forcedColors:n})}function Xe(e,t,n,o){if(!e.panels||!t)return[];return t.openings.flatMap(e=>{const t=n[e.sourceIndex];return t?U(e,o(t)):[]}).sort((e,t)=>e.depth-t.depth||e.sourceIndex-t.sourceIndex||e.leaf-t.leaf)}function Ye(e){const t=Je(e.display),n=t.panels?Xe(t,e.scene,e.openings,e.amountOf):[],o=e.overlays(t),a=t=>({layers:t,panels:n,overlays:o,underlay:it(t,e.scene?.floor,e.cellCm),shadows:rt(t,n,e.scene?.geometry,e.cellCm),walls:st(e.projection,t,e.scene,n,e.cellCm),grounds:ot(o,t,e.cellCm),raised:at(o)});try{return a(t)}catch(e){if(!t.shadows&&!t.materialNuance)throw e;return a({...t,shadows:!1,materialNuance:!1})}}const et=()=>b``;function tt(e){return`translate(${i(4,e)} ${i(8,e)})`}function nt(e,t,n){const o=I(n);return b` ${"walls"===t&&e.materialNuance?b` diff --git a/custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-D5KHv4hp.js b/custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-DNx7W_iY.js similarity index 80% rename from custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-D5KHv4hp.js rename to custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-DNx7W_iY.js index 1b95ecdf..5b5893e6 100644 --- a/custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-D5KHv4hp.js +++ b/custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-DNx7W_iY.js @@ -1 +1 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{dO as e}from"./houseplan-card-CODdCIWj.js";const t=new WeakMap,n=e=>{let n=t.get(e);return n||(n={painted:null,pending:null,raf:0},t.set(e,n)),n},o=e=>`${e.x} ${e.y} ${e.w} ${e.h}`;const r=e=>0===e.translateXPercent&&0===e.translateYPercent&&1===e.scaleX&&1===e.scaleY,a=e=>[e.x,e.y,e.w,e.h].every(Number.isFinite)&&e.w>0&&e.h>0,s=(e,t)=>{if(!t)return e.style.removeProperty("transform"),e.style.removeProperty("transform-origin"),void e.style.removeProperty("will-change");e.style.transformOrigin="0 0",e.style.willChange="transform",e.style.transform=`translate(${t.translateXPercent}%,${t.translateYPercent}%) scale(${t.scaleX},${t.scaleY})`};function i(e,t,n){if(!a(t.view)||!a(n.view)||!a(n.floor))return;const i=o(n.view),l=o(n.floor);for(const t of e.querySelectorAll('[data-hp-live-viewbox="camera"]'))t.setAttribute("viewBox",i);for(const t of e.querySelectorAll('[data-hp-live-viewbox="floor"]'))t.setAttribute("viewBox",l);const c=(f=t.view,u=n.view,{translateXPercent:(f.x-u.x)/u.w*100,translateYPercent:(f.y-u.y)/u.h*100,scaleX:f.w/u.w,scaleY:f.h/u.h});var f,u;for(const t of e.querySelectorAll('[data-hp-live-layer="camera"]'))s(t,r(c)?null:c);const d=e.querySelector("[data-hp-live-zoom]");if(d){d.hidden=n.zoom<=1;const e=d.querySelector("[data-hp-live-zoom-value]");e&&(e.textContent=`${Math.round(100*n.zoom)}%`)}}const l=e=>{const t=e._viewOr(e._baseVb());return{view:{...t},floor:{...e._floorView(t)},zoom:e._zoom}};const c=new WeakMap,f=(e,t,n,o)=>{if(!n)return;const r=document.createElement("span");if(r.className="m",t){r.append(`${t} `);const e=document.createElement("b");e.textContent=n,o&&(e.style.color=o),r.append(e)}else r.textContent=n;e.append(r)},u=(e,t,n)=>{const o=e.querySelector(t);o&&(o.setAttribute("d",n),o.toggleAttribute("hidden",!n))};function d(t){const n=t,o=n.renderRoot;if(!o)return;((t,n)=>{const o=n.querySelector("[data-hp-live-tip]");if(!o)return;const r=t._tip;if(!r)return o.hidden=!0,void o.replaceChildren();o.style.left=`${r.x+12}px`,o.style.top=`${r.y+12}px`,o.replaceChildren();const a=document.createElement("b");a.textContent=r.title,o.append(a),f(o,"",r.meta),f(o,t._t("tip.temp_avg"),null==r.temp?"":`${r.temp}°`),f(o,t._t("tip.hum_avg"),null==r.hum?"":`${r.hum}%`),f(o,t._t("tip.lqi"),null==r.lqi?"":String(r.lqi),null==r.lqi?void 0:e(r.lqi)),o.hidden=!1})(n,o);const r=n._hoverRoom,a=c.get(t),s=r?.space||"",i=r?.room||null;if(a?.room===i&&a?.space===s)return;c.set(t,{room:i,space:s});const l=r&&n._spaceModel(),d=l?n._roomHoverPaths(l):null;u(o,'[data-hp-live-room-hover="fill"]',d?.fillD||""),u(o,'[data-hp-live-room-hover="halo"]',d?.outlineD||""),u(o,'[data-hp-live-room-hover="outline"]',d?.outlineD||"")}function m(e){c.delete(e)}class p{constructor(e){this.host=e,this.deferredHass=!1}hass(e,t,n,o){const r=function(e,t,n){if(e===t)return"none";if(!e||!t||!n)return"structural";if(e.connection!==t.connection||e.entities!==t.entities||e.devices!==t.devices||e.areas!==t.areas||e.themes!==t.themes||e.user!==t.user||e.config!==t.config||e.floors!==t.floors||e.services!==t.services||e.panels!==t.panels||e.language!==t.language||e.locale?.language!==t.locale?.language||e.locale?.number_format!==t.locale?.number_format||e.locale?.time_format!==t.locale?.time_format||e.locale?.date_format!==t.locale?.date_format)return"structural";const o=new Set(["states","connection","entities","devices","areas","themes","user","config","floors","services","panels","language","locale"]);for(const n of new Set([...Object.keys(e),...Object.keys(t)]))if(!o.has(n)&&e[n]!==t[n])return"structural";for(const o of n.entityIds)if(e.states?.[o]!==t.states?.[o])return"state";return"none"}(e,t,n),a="state"===r&&this.active();a&&(this.deferredHass=!0);const s="none"!==r&&!a;return s||this.host._renderLife.observe(e,t,n,o),s}clear(){this.deferredHass=!1}take(){const e=this.deferredHass;return this.deferredHass=!1,e}viewport(e=!1){!function(e,t=!1){const o=e,r=n(e),a=l(o);if(t)return r.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(r.raf),r.raf=0,r.pending=null,r.painted||(r.painted=a),void i(o.renderRoot,r.painted,a);r.pending=a,r.raf||"function"!=typeof requestAnimationFrame||(r.raf=requestAnimationFrame(()=>{r.raf=0;const e=r.pending;r.pending=null;const t=o.renderRoot;e&&t&&(r.painted||(r.painted=e),i(t,r.painted,e))}))}(this.host,e)}hover(){d(this.host)}active(){const e=this.host;return e._pointers.size>0||e._cameraTransition.active||!!e._deviceDrag||!!e._physicalDrag||!!e._physicalRotate||!!e._decorMove||!!e._decorDraft||!!e._dtDrag||!!e._bdDrag||!!e._opDrag||!!e._resize?.dragging}commit(){!function(e){const t=e,o=n(e);o.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(o.raf),o.raf=0,o.pending=null,o.painted=l(t);const r=t.renderRoot;if(r){for(const e of r.querySelectorAll('[data-hp-live-layer="camera"]'))s(e,null);i(r,o.painted,o.painted)}}(this.host),m(this.host),d(this.host)}dispose(){!function(e){const n=t.get(e);n?.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(n.raf),t.delete(e)}(this.host),m(this.host)}}export{p as LiveRuntime}; +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{dQ as e}from"./houseplan-card-Bhpi71t0.js";const t=new WeakMap,n=e=>{let n=t.get(e);return n||(n={painted:null,pending:null,raf:0},t.set(e,n)),n},o=e=>`${e.x} ${e.y} ${e.w} ${e.h}`;const r=e=>0===e.translateXPercent&&0===e.translateYPercent&&1===e.scaleX&&1===e.scaleY,a=e=>[e.x,e.y,e.w,e.h].every(Number.isFinite)&&e.w>0&&e.h>0,s=(e,t)=>{if(!t)return e.style.removeProperty("transform"),e.style.removeProperty("transform-origin"),void e.style.removeProperty("will-change");e.style.transformOrigin="0 0",e.style.willChange="transform",e.style.transform=`translate(${t.translateXPercent}%,${t.translateYPercent}%) scale(${t.scaleX},${t.scaleY})`};function i(e,t,n){if(!a(t.view)||!a(n.view)||!a(n.floor))return;const i=o(n.view),l=o(n.floor);for(const t of e.querySelectorAll('[data-hp-live-viewbox="camera"]'))t.setAttribute("viewBox",i);for(const t of e.querySelectorAll('[data-hp-live-viewbox="floor"]'))t.setAttribute("viewBox",l);const c=(f=t.view,d=n.view,{translateXPercent:(f.x-d.x)/d.w*100,translateYPercent:(f.y-d.y)/d.h*100,scaleX:f.w/d.w,scaleY:f.h/d.h});var f,d;for(const t of e.querySelectorAll('[data-hp-live-layer="camera"]'))s(t,r(c)?null:c);const u=e.querySelector("[data-hp-live-zoom]");if(u){u.hidden=n.zoom<=1;const e=u.querySelector("[data-hp-live-zoom-value]");e&&(e.textContent=`${Math.round(100*n.zoom)}%`)}}const l=e=>{const t=e._viewOr(e._baseVb());return{view:{...t},floor:{...e._floorView(t)},zoom:e._zoom}};const c=new WeakMap,f=(e,t,n,o)=>{if(!n)return;const r=document.createElement("span");if(r.className="m",t){r.append(`${t} `);const e=document.createElement("b");e.textContent=n,o&&(e.style.color=o),r.append(e)}else r.textContent=n;e.append(r)},d=(e,t,n)=>{const o=e.querySelector(t);o&&(o.setAttribute("d",n),o.toggleAttribute("hidden",!n))};function u(t){const n=t,o=n.renderRoot;if(!o)return;((t,n)=>{const o=n.querySelector("[data-hp-live-tip]");if(!o)return;const r=t._tip;if(!r)return o.hidden=!0,void o.replaceChildren();o.style.left=`${r.x+12}px`,o.style.top=`${r.y+12}px`,o.replaceChildren();const a=document.createElement("b");a.textContent=r.title,o.append(a),f(o,"",r.meta),f(o,t._t("tip.temp_avg"),null==r.temp?"":`${r.temp}°`),f(o,t._t("tip.hum_avg"),null==r.hum?"":`${r.hum}%`),f(o,t._t("tip.lqi"),null==r.lqi?"":String(r.lqi),null==r.lqi?void 0:e(r.lqi)),o.hidden=!1})(n,o);const r=n._hoverRoom,a=c.get(t),s=r?.space||"",i=r?.room||null;if(a?.room===i&&a?.space===s)return;c.set(t,{room:i,space:s});const l=r&&n._spaceModel(),u=l?n._roomHoverPaths(l):null;d(o,'[data-hp-live-room-hover="fill"]',u?.fillD||""),d(o,'[data-hp-live-room-hover="halo"]',u?.outlineD||""),d(o,'[data-hp-live-room-hover="outline"]',u?.outlineD||"")}function m(e){c.delete(e)}class p{constructor(e){this.host=e,this.deferredHass=!1}hass(e,t,n,o){const r=function(e,t,n){if(e===t)return"none";if(!e||!t||!n)return"structural";if(e.connection!==t.connection||e.entities!==t.entities||e.devices!==t.devices||e.areas!==t.areas||e.themes!==t.themes||e.user!==t.user||e.config!==t.config||e.floors!==t.floors||e.services!==t.services||e.panels!==t.panels||e.language!==t.language||e.locale?.language!==t.locale?.language||e.locale?.number_format!==t.locale?.number_format||e.locale?.time_format!==t.locale?.time_format||e.locale?.date_format!==t.locale?.date_format)return"structural";const o=new Set(["states","connection","entities","devices","areas","themes","user","config","floors","services","panels","language","locale"]);for(const n of new Set([...Object.keys(e),...Object.keys(t)]))if(!o.has(n)&&e[n]!==t[n])return"structural";for(const o of n.entityIds)if(e.states?.[o]!==t.states?.[o])return"state";return"none"}(e,t,n),a="state"===r&&this.active();a&&(this.deferredHass=!0);const s="none"!==r&&!a;return s||this.host._renderLife.observe(e,t,n,o),s}clear(){this.deferredHass=!1}take(){const e=this.deferredHass;return this.deferredHass=!1,e}viewport(e=!1){!function(e,t=!1){const o=e,r=n(e),a=l(o);if(t)return r.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(r.raf),r.raf=0,r.pending=null,r.painted||(r.painted=a),void i(o.renderRoot,r.painted,a);r.pending=a,r.raf||"function"!=typeof requestAnimationFrame||(r.raf=requestAnimationFrame(()=>{r.raf=0;const e=r.pending;r.pending=null;const t=o.renderRoot;e&&t&&(r.painted||(r.painted=e),i(t,r.painted,e))}))}(this.host,e)}hover(){u(this.host)}active(){const e=this.host;return e._pointers.size>0||e._cameraTransition.active||!!e._deviceDrag||!!e._physicalDrag||!!e._physicalRotate||!!e._decorMove||!!e._decorDraft||!!e._dtDrag||!!e._bdDrag||!!e._opDrag||!!e._resize?.dragging}commit(){!function(e){const t=e,o=n(e);o.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(o.raf),o.raf=0,o.pending=null,o.painted=l(t);const r=t.renderRoot;if(r){for(const e of r.querySelectorAll('[data-hp-live-layer="camera"]'))s(e,null);i(r,o.painted,o.painted)}}(this.host),m(this.host),u(this.host)}dispose(){!function(e){const n=t.get(e);n?.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(n.raf),t.delete(e)}(this.host),m(this.host)}}export{p as LiveRuntime}; diff --git a/custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-BUFPOnoy.js b/custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-B-C5QCCD.js similarity index 95% rename from custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-BUFPOnoy.js rename to custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-B-C5QCCD.js index d1356412..e54b0c11 100644 --- a/custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-BUFPOnoy.js +++ b/custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-B-C5QCCD.js @@ -1 +1 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{s as e,F as n}from"./houseplan-card-CODdCIWj.js";var t={title:"Zigbee links",toggle:"Show Zigbee links when hovering over a device",hint:"Shows observed direct neighbours only. Nothing is fetched while you hover.",help:"Shows which Zigbee devices each device talks to directly. Line colour is link quality (LQI) on the same scale as the device's LQI reading: red at 40 and below, green at 180 and above. A dashed line means quality was not reported. An arrow points to the next device on the way to the coordinator: one arrow leads out, incoming arrows are the devices that route through this one. A line without an arrow is a spare neighbour. This is the route tree House Plan builds, not the path a packet takes right now: a label at the end of an arrow means its target is not on this plan, and no arrow at all means the route is unknown. Data comes from the last load and goes stale; links are shown with a mouse only.",help_aria:"Help: Zigbee links",admin_only:"Topology data is available to Home Assistant administrators only.",save_first:"Save this setting before loading topology data.",zha:"ZHA",zha_read:"Read ZHA data",zha_hint:"Reads ZHA's cached topology; it does not start a radio scan.",z2m:"Zigbee2MQTT",z2m_topics:"Base topics (one per line)",z2m_update:"Update map",z2m_warning:"A network-map scan can take 10 seconds to 2 minutes and may temporarily reduce Zigbee responsiveness.",status_idle:"Data not loaded",status_loading:"Loading…",status_ready:"Received {time}",status_stale:"Received {time} · stale",status_partial:"Received {time} · some nodes were omitted",status_no_links:"Received {time} · no observed links found",error_permission:"Administrator permission is required.",error_unsupported:"This provider or Home Assistant API is unavailable.",error_timeout:"The provider did not respond in time.",error_invalid_topic:"Check the Zigbee2MQTT base topic.",error_invalid_payload:"The provider returned unsupported topology data.",error_provider:"Topology data could not be loaded.",remote_count:"+{n} in other spaces",route_device_not_on_plan:"device is not on the plan",route_coordinator_not_on_plan:"coordinator is not on the plan",route_other_space:"another space"};const i={en:t,ru:{title:"Связи Zigbee",toggle:"Показывать связи Zigbee при наведении на устройство",hint:"Показываются только наблюдаемые прямые соседи. Наведение ничего не запрашивает.",help:"Показывает, с какими устройствами Zigbee каждое связано напрямую. Цвет линии — качество связи (LQI) по той же шкале, что у показателя LQI устройства: красный при 40 и ниже, зелёный при 180 и выше. Пунктир — качество не сообщено. Стрелка ведёт к следующему устройству по пути к координатору: исходящая одна, входящие — те, кто ходит через это устройство. Линия без стрелки — запасной сосед. Это дерево маршрутов, которое строит House Plan, а не путь пакета в эту секунду: подпись на конце стрелки значит, что цель не на этом плане, а отсутствие стрелки — что путь неизвестен. Данные из последней загрузки и устаревают, связи видны только при работе мышью.",help_aria:"Справка: связи Zigbee",admin_only:"Данные топологии доступны только администраторам Home Assistant.",save_first:"Сохраните настройку перед загрузкой данных топологии.",zha:"ZHA",zha_read:"Прочитать данные ZHA",zha_hint:"Читает сохранённую топологию ZHA и не запускает радио-сканирование.",z2m:"Zigbee2MQTT",z2m_topics:"Базовые топики (по одному в строке)",z2m_update:"Обновить карту",z2m_warning:"Сканирование карты сети занимает от 10 секунд до 2 минут и временно может снизить отзывчивость Zigbee.",status_idle:"Данные не загружены",status_loading:"Загрузка…",status_ready:"Получено: {time}",status_stale:"Получено: {time} · данные устарели",status_partial:"Получено: {time} · часть узлов не показана",status_no_links:"Получено: {time} · наблюдаемые связи не найдены",error_permission:"Нужны права администратора.",error_unsupported:"Провайдер или API Home Assistant недоступен.",error_timeout:"Провайдер не ответил вовремя.",error_invalid_topic:"Проверьте базовый топик Zigbee2MQTT.",error_invalid_payload:"Провайдер вернул неподдерживаемые данные топологии.",error_provider:"Не удалось загрузить данные топологии.",remote_count:"+{n} в других пространствах",route_device_not_on_plan:"устройства нет на плане",route_coordinator_not_on_plan:"координатора нет на плане",route_other_space:"другое пространство"},de:{title:"Zigbee-Verbindungen",toggle:"Zigbee-Verbindungen beim Darüberfahren über ein Gerät anzeigen",hint:"Es werden nur beobachtete direkte Nachbarn angezeigt. Beim Darüberfahren werden keine Daten abgerufen.",help:"Zeigt, mit welchen Zigbee-Geräten jedes Gerät direkt verbunden ist. Die Linienfarbe ist die Verbindungsqualität (LQI) auf derselben Skala wie der LQI-Wert des Geräts: rot bei 40 und darunter, grün bei 180 und darüber. Eine gestrichelte Linie bedeutet, dass die Qualität nicht gemeldet wurde. Ein Pfeil zeigt auf das nächste Gerät auf dem Weg zum Koordinator: ein Pfeil führt hinaus, eingehende Pfeile sind die Geräte, die über dieses Gerät routen. Eine Linie ohne Pfeil ist ein Ersatznachbar. Das ist der Routenbaum, den House Plan bildet, nicht der Weg eines Pakets in diesem Moment: eine Beschriftung am Pfeilende bedeutet, dass das Ziel nicht auf diesem Plan liegt, und ein fehlender Pfeil, dass die Route unbekannt ist. Die Daten stammen aus dem letzten Laden und veralten; Verbindungen sind nur mit der Maus sichtbar.",help_aria:"Hilfe: Zigbee-Verbindungen",admin_only:"Topologiedaten sind nur für Home-Assistant-Administratoren verfügbar.",save_first:"Speichere diese Einstellung, bevor Topologiedaten geladen werden.",zha:"ZHA",zha_read:"ZHA-Daten lesen",zha_hint:"Liest den ZHA-Topologiecache; es wird kein Funkscan gestartet.",z2m:"Zigbee2MQTT",z2m_topics:"Basistopics (eines pro Zeile)",z2m_update:"Karte aktualisieren",z2m_warning:"Ein Netzwerkscan kann 10 Sekunden bis 2 Minuten dauern und Zigbee vorübergehend verlangsamen.",status_idle:"Daten nicht geladen",status_loading:"Wird geladen…",status_ready:"Empfangen: {time}",status_stale:"Empfangen: {time} · veraltet",status_partial:"Empfangen: {time} · einige Knoten fehlen",status_no_links:"Empfangen: {time} · keine beobachteten Verbindungen gefunden",error_permission:"Administratorrechte sind erforderlich.",error_unsupported:"Dieser Anbieter oder die Home-Assistant-API ist nicht verfügbar.",error_timeout:"Der Anbieter hat nicht rechtzeitig geantwortet.",error_invalid_topic:"Prüfe das Zigbee2MQTT-Basistopic.",error_invalid_payload:"Der Anbieter hat nicht unterstützte Topologiedaten geliefert.",error_provider:"Topologiedaten konnten nicht geladen werden.",remote_count:"+{n} in anderen Bereichen",route_device_not_on_plan:"Gerät ist nicht im Plan",route_coordinator_not_on_plan:"Koordinator ist nicht im Plan",route_other_space:"anderer Bereich"},fr:{title:"Liens Zigbee",toggle:"Afficher les liens Zigbee au survol d’un appareil",hint:"Seuls les voisins directs observés sont affichés. Le survol ne lance aucune requête.",help:"Montre avec quels appareils Zigbee chaque appareil communique directement. La couleur de la ligne est la qualité du lien (LQI) sur la même échelle que l'indicateur LQI de l'appareil : rouge à 40 et en dessous, vert à 180 et au-dessus. Une ligne pointillée signifie que la qualité n'a pas été communiquée. Une flèche pointe vers l'appareil suivant sur le chemin du coordinateur : une flèche part, les flèches entrantes sont les appareils qui passent par celui-ci. Une ligne sans flèche est un voisin de secours. C'est l'arbre de routes que construit House Plan, pas le trajet d'un paquet à cet instant : une étiquette au bout d'une flèche signifie que sa cible n'est pas sur ce plan, et l'absence de flèche que la route est inconnue. Les données proviennent du dernier chargement et vieillissent ; les liens ne sont visibles qu'à la souris.",help_aria:"Aide : liens Zigbee",admin_only:"Les données de topologie sont réservées aux administrateurs Home Assistant.",save_first:"Enregistrez ce réglage avant de charger les données de topologie.",zha:"ZHA",zha_read:"Lire les données ZHA",zha_hint:"Lit la topologie en cache de ZHA sans lancer d’analyse radio.",z2m:"Zigbee2MQTT",z2m_topics:"Topics de base (un par ligne)",z2m_update:"Actualiser la carte",z2m_warning:"L’analyse de la carte réseau peut durer de 10 secondes à 2 minutes et réduire temporairement la réactivité de Zigbee.",status_idle:"Données non chargées",status_loading:"Chargement…",status_ready:"Reçu : {time}",status_stale:"Reçu : {time} · obsolète",status_partial:"Reçu : {time} · certains nœuds sont omis",status_no_links:"Reçu : {time} · aucun lien observé trouvé",error_permission:"Les droits administrateur sont requis.",error_unsupported:"Ce fournisseur ou l’API Home Assistant n’est pas disponible.",error_timeout:"Le fournisseur n’a pas répondu à temps.",error_invalid_topic:"Vérifiez le topic de base Zigbee2MQTT.",error_invalid_payload:"Le fournisseur a renvoyé des données de topologie non prises en charge.",error_provider:"Impossible de charger les données de topologie.",remote_count:"+{n} dans d’autres espaces",route_device_not_on_plan:"appareil absent du plan",route_coordinator_not_on_plan:"coordinateur absent du plan",route_other_space:"autre espace"}};function r(e,n){const r=i[e]?.[n]??t[n];return"string"==typeof r&&r.trim().length>0}function o(n,r,o){return e(i[n]?.[r]??t[r]??r,o)}const s=3e5,a=2097152,d=6e3;function l(e){return null!==e&&"object"==typeof e?e:null}function u(e){if("string"!=typeof e&&"number"!=typeof e)return null;let n=String(e).trim().toLowerCase();return n=/^0x[0-9a-f]{16}$/.test(n)?n.slice(2):n.replace(/[:-]/g,""),/^[0-9a-f]{16}$/.test(n)?n:null}function c(e,n,t){return`${e}:${n}:${t}`}function p(e){const n=String(e||"").toLowerCase().replace(/[ _-]/g,"");return n.includes("coordinator")?"coordinator":n.includes("router")?"router":n.includes("enddevice")||"end"===n?"end":"unknown"}const h=["parent","child","sibling","none","previous_child"];function g(e){const n=l(e),t=function(e){const n=Number(e);return Number.isFinite(n)&&n>=0&&n<=255?Math.round(n):void 0}(n?.lqi??n?.linkquality??n?.link_quality),i=function(e){if("number"==typeof e)return h[e];if("string"!=typeof e)return;const n=e.trim().toLowerCase().replace(/[\s_-]+/g,"");return"previouschild"===n?"previous_child":n.slice(0,40)||void 0}(n?.relationship);return{...void 0===t?{}:{lqi:t},...i?{relationship:i}:{}}}function f(e,n){return Array.isArray(e)&&e.length<=n?e:null}function _(e){if("string"==typeof e)return e.length<=a;try{return JSON.stringify(e).length<=a}catch{return!1}}function m(e,n,t,i,r){if(t===i)return void n.push({code:"self_link",nodeKey:t});const o=t=d){t.push({code:"invalid_payload"});break}const n=l(e),i=u(n?.ieee??n?.ieee_address);if(!i){t.push({code:"invalid_payload",nodeKey:s});continue}const a=c("zha","zha",i);r.has(a)||r.set(a,{key:a,ieee:i,role:p(n?.device_type)}),m(o,t,s,a,e)}else null!=n?.neighbors&&t.push({code:"invalid_payload",nodeKey:s})}return{provider:"zha",instanceId:"zha",obtainedAt:n,freshness:"provider-cache",nodes:[...r.values()],links:[...o.values()],warnings:t}}function v(e,n){const t=l(e),i=u(t?.ieeeAddr??t?.ieee_address??t?.ieee??e);if(i)return i;for(const i of[t?.id,t?.networkAddress,t?.network_address,e])if(null!=i){const e=n.get(String(i));if(e)return e}return null}function y(e,t,i=Date.now()){const r=[],o=n(t)||"invalid",s=_(e)?function(e){let n=e;if("string"==typeof n){if(n.length>a)return null;try{n=JSON.parse(n)}catch{return null}}const t=l(n),i=l(t?.data);if(n=i?.value??t?.value??t?.data??n,"string"==typeof n){if(n.length>a)return null;try{n=JSON.parse(n)}catch{return null}}return n}(e):null,h=l(s),g=f(h?.nodes,1e3),b=f(h?.links,d);if(!g||!b)return{provider:"z2m",instanceId:o,obtainedAt:i,freshness:"fresh-scan",nodes:[],links:[],warnings:[{code:"invalid_payload"}]};const y=new Map,k=new Map;for(const e of g){const n=l(e),t=u(n?.ieeeAddr??n?.ieee_address??n?.ieee);if(!t){r.push({code:"invalid_payload"});continue}const i=c("z2m",o,t);y.set(i,{key:i,ieee:t,role:p(n?.type??n?.device_type),..."boolean"==typeof n?.failed?{available:!n.failed}:{}});for(const e of[n?.id,n?.networkAddress,n?.network_address])null!=e&&k.set(String(e),t)}const w=new Map;for(const e of b){const n=l(e),t=u(n?.sourceIeeeAddr)??v(n?.source,k),i=u(n?.targetIeeeAddr)??v(n?.target,k);if(!t||!i){r.push({code:"invalid_payload"});continue}const s=c("z2m",o,t),a=c("z2m",o,i);y.has(s)||y.set(s,{key:s,ieee:t,role:"unknown"}),y.has(a)||y.set(a,{key:a,ieee:i,role:"unknown"}),m(w,r,s,a,e)}return{provider:"z2m",instanceId:o,obtainedAt:i,freshness:"fresh-scan",nodes:[...y.values()],links:[...w.values()],warnings:r}}function k(e){if("string"!=typeof e)return null;const n=u(e);if(n)return n;const t=e.toLowerCase().match(/^zigbee2mqtt(?:_bridge)?_(.+)$/);return t?u(t[1]):null}function w(e,n){if(e.deviceId&&n.devices[e.deviceId])return[e.deviceId];const t=new Set;for(const[i,r]of Object.entries(n.devices)){const n=l(r);(Array.isArray(n?.identifiers)?n.identifiers:[]).some(n=>Array.isArray(n)&&k(n[1])===e.ieee)&&t.add(i)}if(t.size)return[...t];for(const i of Object.values(n.entities)){const n=l(i);"string"==typeof n?.device_id&&"string"==typeof n.unique_id&&(k(n.unique_id)===e.ieee&&t.add(n.device_id))}return[...t]}function z(e){return!e.hidden&&!e.virtual&&"ha_disabled"!==e.bindingStatus?.kind&&"orphaned"!==e.bindingStatus?.kind&&"unverified"!==e.bindingStatus?.kind}function A(e){const n=new Map,t=new Map,i=e.nodes.filter(e=>"coordinator"===e.role).map(e=>e.key).sort();if(1!==i.length)return{distances:n,parents:t};const r=i[0],o=function(e){const n=new Set(e.nodes.map(e=>e.key)),t=new Map;for(const e of[...n].sort())t.set(e,[]);for(const i of[...e.links].sort((e,n)=>`${e.a}\0${e.b}`.localeCompare(`${n.a}\0${n.b}`)))n.has(i.a)&&n.has(i.b)&&(t.get(i.a).push({neighborKey:i.b,observation:i.aToB}),t.get(i.b).push({neighborKey:i.a,observation:i.bToA}));for(const e of t.values())e.sort((e,n)=>e.neighborKey.localeCompare(n.neighborKey));return t}(e);if(!o.has(r))return{distances:n,parents:t};n.set(r,0);const s=[r];for(let e=0;en.get(e)===i-1).sort((e,n)=>{const t="parent"===e.observation?.relationship?1:0,i="parent"===n.observation?.relationship?1:0;if(t!==i)return i-t;const r=e.observation?.lqi??-1;return(n.observation?.lqi??-1)-r||e.neighborKey.localeCompare(n.neighborKey)});r[0]&&t.set(e,r[0].neighborKey)}return{coordinatorKey:r,distances:n,parents:t}}function Z(e,n,t){const i=new Map,r=[];for(const o of e.nodes){if(!1===o.available){r.push({code:"provider_scan_failure",nodeKey:o.key});continue}const e=w(o,t);if(1!==e.length){r.push({code:"unmatched_device",nodeKey:o.key});continue}const s=e[0];let a=n.filter(e=>z(e)&&"device"===e.bindingKind&&e.bindingRef===s);a.length||(a=n.filter(e=>z(e)&&"entity"===e.bindingKind&&!!e.bindingRef&&t.entities[e.bindingRef]?.device_id===s)),1===a.length?i.set(o.key,{markerId:a[0].id,space:a[0].space}):r.push({code:a.length>1?"ambiguous_placement":"unmatched_device",nodeKey:o.key})}return{placements:i,warnings:r}}function T(e,n,t){return e.map(e=>({topology:e,placements:Z(e,n,t).placements,routes:A(e)}))}function q(e,n,t){const i=new Map,r=new Set,o=new Map;let s=0;for(const{topology:a,placements:d,routes:l}of e){const e=new Set([...d].filter(([,e])=>e.markerId===t&&e.space===n).map(([e])=>e));if(e.size){for(const t of e){const e=l.parents.get(t);if(!e)continue;const i=d.get(e);if(i?.space===n)continue;let r;r=i?{kind:"remote-space",spaceId:i.space}:"coordinator"===a.nodes.find(n=>n.key===e)?.role?{kind:"unplaced-coordinator"}:{kind:"unplaced-device"};const s="remote-space"===r.kind?`${r.kind}:${r.spaceId}`:r.kind;o.set(s,r)}for(const o of a.links){const a=e.has(o.a),u=e.has(o.b);if(!a&&!u)continue;const c=a?o.a:o.b,p=a?o.b:o.a,h=d.get(p);if(!h||h.markerId===t){s++;continue}const g=l.parents.get(c)===p;if(h.space!==n){g||r.add(h.markerId);continue}const f=a?o.aToB:o.bToA,_=g?"toward-neighbor":l.parents.get(p)===c?"toward-origin":void 0,m=i.get(h.markerId);m?(void 0===m.line.lqi&&void 0!==f?.lqi&&(m.line.lqi=f.lqi),_&&m.directions.add(_)):i.set(h.markerId,{line:{neighborMarkerId:h.markerId,lqi:f?.lqi},directions:new Set(_?[_]:[])})}}}return{lines:[...i.values()].map(({line:e,directions:n})=>1===n.size?{...e,routeDirection:[...n][0]}:e),remoteCount:r.size,omittedCount:s,parentTargets:[...o.values()]}}export{s as T,T as a,y as b,r as h,Z as m,b as n,q as r,o as t}; +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{s as e,F as n}from"./houseplan-card-Bhpi71t0.js";var t={title:"Zigbee links",toggle:"Show Zigbee links when hovering over a device",hint:"Shows observed direct neighbours only. Nothing is fetched while you hover.",help:"Shows which Zigbee devices each device talks to directly. Line colour is link quality (LQI) on the same scale as the device's LQI reading: red at 40 and below, green at 180 and above. A dashed line means quality was not reported. An arrow points to the next device on the way to the coordinator: one arrow leads out, incoming arrows are the devices that route through this one. A line without an arrow is a spare neighbour. This is the route tree House Plan builds, not the path a packet takes right now: a label at the end of an arrow means its target is not on this plan, and no arrow at all means the route is unknown. Data comes from the last load and goes stale; links are shown with a mouse only.",help_aria:"Help: Zigbee links",admin_only:"Topology data is available to Home Assistant administrators only.",save_first:"Save this setting before loading topology data.",zha:"ZHA",zha_read:"Read ZHA data",zha_hint:"Reads ZHA's cached topology; it does not start a radio scan.",z2m:"Zigbee2MQTT",z2m_topics:"Base topics (one per line)",z2m_update:"Update map",z2m_warning:"A network-map scan can take 10 seconds to 2 minutes and may temporarily reduce Zigbee responsiveness.",status_idle:"Data not loaded",status_loading:"Loading…",status_ready:"Received {time}",status_stale:"Received {time} · stale",status_partial:"Received {time} · some nodes were omitted",status_no_links:"Received {time} · no observed links found",error_permission:"Administrator permission is required.",error_unsupported:"This provider or Home Assistant API is unavailable.",error_timeout:"The provider did not respond in time.",error_invalid_topic:"Check the Zigbee2MQTT base topic.",error_invalid_payload:"The provider returned unsupported topology data.",error_provider:"Topology data could not be loaded.",remote_count:"+{n} in other spaces",route_device_not_on_plan:"device is not on the plan",route_coordinator_not_on_plan:"coordinator is not on the plan",route_other_space:"another space"};const i={en:t,ru:{title:"Связи Zigbee",toggle:"Показывать связи Zigbee при наведении на устройство",hint:"Показываются только наблюдаемые прямые соседи. Наведение ничего не запрашивает.",help:"Показывает, с какими устройствами Zigbee каждое связано напрямую. Цвет линии — качество связи (LQI) по той же шкале, что у показателя LQI устройства: красный при 40 и ниже, зелёный при 180 и выше. Пунктир — качество не сообщено. Стрелка ведёт к следующему устройству по пути к координатору: исходящая одна, входящие — те, кто ходит через это устройство. Линия без стрелки — запасной сосед. Это дерево маршрутов, которое строит House Plan, а не путь пакета в эту секунду: подпись на конце стрелки значит, что цель не на этом плане, а отсутствие стрелки — что путь неизвестен. Данные из последней загрузки и устаревают, связи видны только при работе мышью.",help_aria:"Справка: связи Zigbee",admin_only:"Данные топологии доступны только администраторам Home Assistant.",save_first:"Сохраните настройку перед загрузкой данных топологии.",zha:"ZHA",zha_read:"Прочитать данные ZHA",zha_hint:"Читает сохранённую топологию ZHA и не запускает радио-сканирование.",z2m:"Zigbee2MQTT",z2m_topics:"Базовые топики (по одному в строке)",z2m_update:"Обновить карту",z2m_warning:"Сканирование карты сети занимает от 10 секунд до 2 минут и временно может снизить отзывчивость Zigbee.",status_idle:"Данные не загружены",status_loading:"Загрузка…",status_ready:"Получено: {time}",status_stale:"Получено: {time} · данные устарели",status_partial:"Получено: {time} · часть узлов не показана",status_no_links:"Получено: {time} · наблюдаемые связи не найдены",error_permission:"Нужны права администратора.",error_unsupported:"Провайдер или API Home Assistant недоступен.",error_timeout:"Провайдер не ответил вовремя.",error_invalid_topic:"Проверьте базовый топик Zigbee2MQTT.",error_invalid_payload:"Провайдер вернул неподдерживаемые данные топологии.",error_provider:"Не удалось загрузить данные топологии.",remote_count:"+{n} в других пространствах",route_device_not_on_plan:"устройства нет на плане",route_coordinator_not_on_plan:"координатора нет на плане",route_other_space:"другое пространство"},de:{title:"Zigbee-Verbindungen",toggle:"Zigbee-Verbindungen beim Darüberfahren über ein Gerät anzeigen",hint:"Es werden nur beobachtete direkte Nachbarn angezeigt. Beim Darüberfahren werden keine Daten abgerufen.",help:"Zeigt, mit welchen Zigbee-Geräten jedes Gerät direkt verbunden ist. Die Linienfarbe ist die Verbindungsqualität (LQI) auf derselben Skala wie der LQI-Wert des Geräts: rot bei 40 und darunter, grün bei 180 und darüber. Eine gestrichelte Linie bedeutet, dass die Qualität nicht gemeldet wurde. Ein Pfeil zeigt auf das nächste Gerät auf dem Weg zum Koordinator: ein Pfeil führt hinaus, eingehende Pfeile sind die Geräte, die über dieses Gerät routen. Eine Linie ohne Pfeil ist ein Ersatznachbar. Das ist der Routenbaum, den House Plan bildet, nicht der Weg eines Pakets in diesem Moment: eine Beschriftung am Pfeilende bedeutet, dass das Ziel nicht auf diesem Plan liegt, und ein fehlender Pfeil, dass die Route unbekannt ist. Die Daten stammen aus dem letzten Laden und veralten; Verbindungen sind nur mit der Maus sichtbar.",help_aria:"Hilfe: Zigbee-Verbindungen",admin_only:"Topologiedaten sind nur für Home-Assistant-Administratoren verfügbar.",save_first:"Speichere diese Einstellung, bevor Topologiedaten geladen werden.",zha:"ZHA",zha_read:"ZHA-Daten lesen",zha_hint:"Liest den ZHA-Topologiecache; es wird kein Funkscan gestartet.",z2m:"Zigbee2MQTT",z2m_topics:"Basistopics (eines pro Zeile)",z2m_update:"Karte aktualisieren",z2m_warning:"Ein Netzwerkscan kann 10 Sekunden bis 2 Minuten dauern und Zigbee vorübergehend verlangsamen.",status_idle:"Daten nicht geladen",status_loading:"Wird geladen…",status_ready:"Empfangen: {time}",status_stale:"Empfangen: {time} · veraltet",status_partial:"Empfangen: {time} · einige Knoten fehlen",status_no_links:"Empfangen: {time} · keine beobachteten Verbindungen gefunden",error_permission:"Administratorrechte sind erforderlich.",error_unsupported:"Dieser Anbieter oder die Home-Assistant-API ist nicht verfügbar.",error_timeout:"Der Anbieter hat nicht rechtzeitig geantwortet.",error_invalid_topic:"Prüfe das Zigbee2MQTT-Basistopic.",error_invalid_payload:"Der Anbieter hat nicht unterstützte Topologiedaten geliefert.",error_provider:"Topologiedaten konnten nicht geladen werden.",remote_count:"+{n} in anderen Bereichen",route_device_not_on_plan:"Gerät ist nicht im Plan",route_coordinator_not_on_plan:"Koordinator ist nicht im Plan",route_other_space:"anderer Bereich"},fr:{title:"Liens Zigbee",toggle:"Afficher les liens Zigbee au survol d’un appareil",hint:"Seuls les voisins directs observés sont affichés. Le survol ne lance aucune requête.",help:"Montre avec quels appareils Zigbee chaque appareil communique directement. La couleur de la ligne est la qualité du lien (LQI) sur la même échelle que l'indicateur LQI de l'appareil : rouge à 40 et en dessous, vert à 180 et au-dessus. Une ligne pointillée signifie que la qualité n'a pas été communiquée. Une flèche pointe vers l'appareil suivant sur le chemin du coordinateur : une flèche part, les flèches entrantes sont les appareils qui passent par celui-ci. Une ligne sans flèche est un voisin de secours. C'est l'arbre de routes que construit House Plan, pas le trajet d'un paquet à cet instant : une étiquette au bout d'une flèche signifie que sa cible n'est pas sur ce plan, et l'absence de flèche que la route est inconnue. Les données proviennent du dernier chargement et vieillissent ; les liens ne sont visibles qu'à la souris.",help_aria:"Aide : liens Zigbee",admin_only:"Les données de topologie sont réservées aux administrateurs Home Assistant.",save_first:"Enregistrez ce réglage avant de charger les données de topologie.",zha:"ZHA",zha_read:"Lire les données ZHA",zha_hint:"Lit la topologie en cache de ZHA sans lancer d’analyse radio.",z2m:"Zigbee2MQTT",z2m_topics:"Topics de base (un par ligne)",z2m_update:"Actualiser la carte",z2m_warning:"L’analyse de la carte réseau peut durer de 10 secondes à 2 minutes et réduire temporairement la réactivité de Zigbee.",status_idle:"Données non chargées",status_loading:"Chargement…",status_ready:"Reçu : {time}",status_stale:"Reçu : {time} · obsolète",status_partial:"Reçu : {time} · certains nœuds sont omis",status_no_links:"Reçu : {time} · aucun lien observé trouvé",error_permission:"Les droits administrateur sont requis.",error_unsupported:"Ce fournisseur ou l’API Home Assistant n’est pas disponible.",error_timeout:"Le fournisseur n’a pas répondu à temps.",error_invalid_topic:"Vérifiez le topic de base Zigbee2MQTT.",error_invalid_payload:"Le fournisseur a renvoyé des données de topologie non prises en charge.",error_provider:"Impossible de charger les données de topologie.",remote_count:"+{n} dans d’autres espaces",route_device_not_on_plan:"appareil absent du plan",route_coordinator_not_on_plan:"coordinateur absent du plan",route_other_space:"autre espace"}};function r(e,n){const r=i[e]?.[n]??t[n];return"string"==typeof r&&r.trim().length>0}function o(n,r,o){return e(i[n]?.[r]??t[r]??r,o)}const s=3e5,a=2097152,d=6e3;function l(e){return null!==e&&"object"==typeof e?e:null}function u(e){if("string"!=typeof e&&"number"!=typeof e)return null;let n=String(e).trim().toLowerCase();return n=/^0x[0-9a-f]{16}$/.test(n)?n.slice(2):n.replace(/[:-]/g,""),/^[0-9a-f]{16}$/.test(n)?n:null}function c(e,n,t){return`${e}:${n}:${t}`}function p(e){const n=String(e||"").toLowerCase().replace(/[ _-]/g,"");return n.includes("coordinator")?"coordinator":n.includes("router")?"router":n.includes("enddevice")||"end"===n?"end":"unknown"}const h=["parent","child","sibling","none","previous_child"];function g(e){const n=l(e),t=function(e){const n=Number(e);return Number.isFinite(n)&&n>=0&&n<=255?Math.round(n):void 0}(n?.lqi??n?.linkquality??n?.link_quality),i=function(e){if("number"==typeof e)return h[e];if("string"!=typeof e)return;const n=e.trim().toLowerCase().replace(/[\s_-]+/g,"");return"previouschild"===n?"previous_child":n.slice(0,40)||void 0}(n?.relationship);return{...void 0===t?{}:{lqi:t},...i?{relationship:i}:{}}}function f(e,n){return Array.isArray(e)&&e.length<=n?e:null}function _(e){if("string"==typeof e)return e.length<=a;try{return JSON.stringify(e).length<=a}catch{return!1}}function b(e,n,t,i,r){if(t===i)return void n.push({code:"self_link",nodeKey:t});const o=t=d){t.push({code:"invalid_payload"});break}const n=l(e),i=u(n?.ieee??n?.ieee_address);if(!i){t.push({code:"invalid_payload",nodeKey:s});continue}const a=c("zha","zha",i);r.has(a)||r.set(a,{key:a,ieee:i,role:p(n?.device_type)}),b(o,t,s,a,e)}else null!=n?.neighbors&&t.push({code:"invalid_payload",nodeKey:s})}return{provider:"zha",instanceId:"zha",obtainedAt:n,freshness:"provider-cache",nodes:[...r.values()],links:[...o.values()],warnings:t}}function v(e,n){const t=l(e),i=u(t?.ieeeAddr??t?.ieee_address??t?.ieee??e);if(i)return i;for(const i of[t?.id,t?.networkAddress,t?.network_address,e])if(null!=i){const e=n.get(String(i));if(e)return e}return null}function y(e,t,i=Date.now()){const r=[],o=n(t)||"invalid",s=_(e)?function(e){let n=e;if("string"==typeof n){if(n.length>a)return null;try{n=JSON.parse(n)}catch{return null}}const t=l(n),i=l(t?.data);if(n=i?.value??t?.value??t?.data??n,"string"==typeof n){if(n.length>a)return null;try{n=JSON.parse(n)}catch{return null}}return n}(e):null,h=l(s),g=f(h?.nodes,1e3),m=f(h?.links,d);if(!g||!m)return{provider:"z2m",instanceId:o,obtainedAt:i,freshness:"fresh-scan",nodes:[],links:[],warnings:[{code:"invalid_payload"}]};const y=new Map,k=new Map;for(const e of g){const n=l(e),t=u(n?.ieeeAddr??n?.ieee_address??n?.ieee);if(!t){r.push({code:"invalid_payload"});continue}const i=c("z2m",o,t);y.set(i,{key:i,ieee:t,role:p(n?.type??n?.device_type),..."boolean"==typeof n?.failed?{available:!n.failed}:{}});for(const e of[n?.id,n?.networkAddress,n?.network_address])null!=e&&k.set(String(e),t)}const w=new Map;for(const e of m){const n=l(e),t=u(n?.sourceIeeeAddr)??v(n?.source,k),i=u(n?.targetIeeeAddr)??v(n?.target,k);if(!t||!i){r.push({code:"invalid_payload"});continue}const s=c("z2m",o,t),a=c("z2m",o,i);y.has(s)||y.set(s,{key:s,ieee:t,role:"unknown"}),y.has(a)||y.set(a,{key:a,ieee:i,role:"unknown"}),b(w,r,s,a,e)}return{provider:"z2m",instanceId:o,obtainedAt:i,freshness:"fresh-scan",nodes:[...y.values()],links:[...w.values()],warnings:r}}function k(e){if("string"!=typeof e)return null;const n=u(e);if(n)return n;const t=e.toLowerCase().match(/^zigbee2mqtt(?:_bridge)?_(.+)$/);return t?u(t[1]):null}function w(e,n){if(e.deviceId&&n.devices[e.deviceId])return[e.deviceId];const t=new Set;for(const[i,r]of Object.entries(n.devices)){const n=l(r);(Array.isArray(n?.identifiers)?n.identifiers:[]).some(n=>Array.isArray(n)&&k(n[1])===e.ieee)&&t.add(i)}if(t.size)return[...t];for(const i of Object.values(n.entities)){const n=l(i);"string"==typeof n?.device_id&&"string"==typeof n.unique_id&&(k(n.unique_id)===e.ieee&&t.add(n.device_id))}return[...t]}function z(e){return!e.hidden&&!e.virtual&&"ha_disabled"!==e.bindingStatus?.kind&&"orphaned"!==e.bindingStatus?.kind&&"unverified"!==e.bindingStatus?.kind}function A(e){const n=new Map,t=new Map,i=e.nodes.filter(e=>"coordinator"===e.role).map(e=>e.key).sort();if(1!==i.length)return{distances:n,parents:t};const r=i[0],o=function(e){const n=new Set(e.nodes.map(e=>e.key)),t=new Map;for(const e of[...n].sort())t.set(e,[]);for(const i of[...e.links].sort((e,n)=>`${e.a}\0${e.b}`.localeCompare(`${n.a}\0${n.b}`)))n.has(i.a)&&n.has(i.b)&&(t.get(i.a).push({neighborKey:i.b,observation:i.aToB}),t.get(i.b).push({neighborKey:i.a,observation:i.bToA}));for(const e of t.values())e.sort((e,n)=>e.neighborKey.localeCompare(n.neighborKey));return t}(e);if(!o.has(r))return{distances:n,parents:t};n.set(r,0);const s=[r];for(let e=0;en.get(e)===i-1).sort((e,n)=>{const t="parent"===e.observation?.relationship?1:0,i="parent"===n.observation?.relationship?1:0;if(t!==i)return i-t;const r=e.observation?.lqi??-1;return(n.observation?.lqi??-1)-r||e.neighborKey.localeCompare(n.neighborKey)});r[0]&&t.set(e,r[0].neighborKey)}return{coordinatorKey:r,distances:n,parents:t}}function Z(e,n,t){const i=new Map,r=[];for(const o of e.nodes){if(!1===o.available){r.push({code:"provider_scan_failure",nodeKey:o.key});continue}const e=w(o,t);if(1!==e.length){r.push({code:"unmatched_device",nodeKey:o.key});continue}const s=e[0];let a=n.filter(e=>z(e)&&"device"===e.bindingKind&&e.bindingRef===s);a.length||(a=n.filter(e=>z(e)&&"entity"===e.bindingKind&&!!e.bindingRef&&t.entities[e.bindingRef]?.device_id===s)),1===a.length?i.set(o.key,{markerId:a[0].id,space:a[0].space}):r.push({code:a.length>1?"ambiguous_placement":"unmatched_device",nodeKey:o.key})}return{placements:i,warnings:r}}function T(e,n,t){return e.map(e=>({topology:e,placements:Z(e,n,t).placements,routes:A(e)}))}function q(e,n,t){const i=new Map,r=new Set,o=new Map;let s=0;for(const{topology:a,placements:d,routes:l}of e){const e=new Set([...d].filter(([,e])=>e.markerId===t&&e.space===n).map(([e])=>e));if(e.size){for(const t of e){const e=l.parents.get(t);if(!e)continue;const i=d.get(e);if(i?.space===n)continue;let r;r=i?{kind:"remote-space",spaceId:i.space}:"coordinator"===a.nodes.find(n=>n.key===e)?.role?{kind:"unplaced-coordinator"}:{kind:"unplaced-device"};const s="remote-space"===r.kind?`${r.kind}:${r.spaceId}`:r.kind;o.set(s,r)}for(const o of a.links){const a=e.has(o.a),u=e.has(o.b);if(!a&&!u)continue;const c=a?o.a:o.b,p=a?o.b:o.a,h=d.get(p);if(!h||h.markerId===t){s++;continue}const g=l.parents.get(c)===p;if(h.space!==n){g||r.add(h.markerId);continue}const f=a?o.aToB:o.bToA,_=g?"toward-neighbor":l.parents.get(p)===c?"toward-origin":void 0,b=i.get(h.markerId);b?(void 0===b.line.lqi&&void 0!==f?.lqi&&(b.line.lqi=f.lqi),_&&b.directions.add(_)):i.set(h.markerId,{line:{neighborMarkerId:h.markerId,lqi:f?.lqi},directions:new Set(_?[_]:[])})}}}return{lines:[...i.values()].map(({line:e,directions:n})=>1===n.size?{...e,routeDirection:[...n][0]}:e),remoteCount:r.size,omittedCount:s,parentTargets:[...o.values()]}}export{s as T,T as a,y as b,r as h,Z as m,m as n,q as r,o as t}; diff --git a/custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js b/custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js similarity index 77% rename from custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js rename to custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js index 53ab45ac..52f87da2 100644 --- a/custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js +++ b/custom_components/houseplan/frontend/houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js @@ -1 +1 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{n as t,b as n}from"./zigbee-topology-BUFPOnoy.js";import{F as e}from"./houseplan-card-CODdCIWj.js";const o=new WeakMap;function i(t){const n=function(t){const n=t?.connection||t;return!n||"object"!=typeof n&&"function"!=typeof n?null:n}(t);if(!n)return null;let e=o.get(n);return e||(e={revision:0,topologies:[],states:{},listeners:new Set,inflight:new Map},o.set(n,e)),e}function r(t,n,e){t.states={...t.states,[n]:e},function(t){t.revision++;for(const n of t.listeners)n()}(t)}function s(t){const n=t?.code;if("permission"===n||"unsupported"===n||"timeout"===n||"invalid_topic"===n||"invalid_payload"===n)return n;const e=String(t?.message||"").toLowerCase();return e.includes("unauthor")||e.includes("permission")?"permission":e.includes("unknown_command")||e.includes("not found")?"unsupported":"provider"}function a(t){return Object.assign(new Error(t),{code:t})}function c(t,n,e){const o=t.inflight.get(n);if(o)return o;r(t,n,{phase:"loading"});const i=e().then(n=>{if(!n.nodes.length&&n.warnings.some(t=>"invalid_payload"===t.code))throw a("invalid_payload");!function(t,n){t.topologies=[...t.topologies.filter(t=>!(t.provider===n.provider&&t.instanceId===n.instanceId)),n],r(t,"zha"===n.provider?"zha":`z2m:${n.instanceId}`,{phase:"ready",obtainedAt:n.obtainedAt,partial:n.warnings.length>0})}(t,n)}).catch(e=>{r(t,n,{phase:"error",error:s(e)})}).finally(()=>t.inflight.delete(n));return t.inflight.set(n,i),i}function l(t){const n=i(t);return n?{revision:n.revision,topologies:n.topologies,states:n.states}:{revision:0,topologies:[],states:{}}}function u(t,n){const e=i(t);return e?(e.listeners.add(n),()=>e.listeners.delete(n)):()=>{}}function p(t){if(!0!==t?.user?.is_admin)throw a("permission")}function f(n){const e=i(n);return e?c(e,"zha",async()=>{if(p(n),"function"!=typeof n?.callWS)throw a("unsupported");return t(await n.callWS({type:"zha/devices"}))}):Promise.resolve()}function d(t){return null!==t&&"object"==typeof t?t:null}function h(t){const n=d(t),e=n?.payload??t;if("string"!=typeof e)return e;try{return JSON.parse(e)}catch{return null}}async function m(t,n){let e;try{return await Promise.race([t,new Promise((t,o)=>{e=globalThis.setTimeout(()=>o(a("timeout")),Math.max(1,n))})])}finally{void 0!==e&&globalThis.clearTimeout(e)}}function g(t,o,r=15e4){const s=i(t);if(!s)return Promise.resolve();const l=e(o);return c(s,`z2m:${l||String(o)}`,async()=>{if(p(t),!l)throw a("invalid_topic");const e=t.connection,o=e?.subscribeMessage;if("function"!=typeof o||"function"!=typeof t?.callService)throw a("unsupported");const i=function(){const t=globalThis.crypto;return"function"==typeof t?.randomUUID?`houseplan-${t.randomUUID()}`:`houseplan-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}(),s=Date.now()+Math.max(1,r);let c=!1,u=null,f=null,g=null;const y=new Promise(t=>{u=t}),w=new Promise((t,n)=>{f=t,g=n}),b=[];try{const r=await o.call(e,t=>{!0===d(t)?.retain&&h(t)&&u?.()},{type:"mqtt/subscribe",topic:`${l}/bridge/info`});"function"==typeof r&&b.push(r);const p=await o.call(e,t=>{if(!0===d(t)?.retain)return;const n=h(t);null!==n?n&&function(t){const n=d(t),e=n?.transaction??d(n?.data)?.transaction;return"string"==typeof e||"number"==typeof e?String(e):null}(n)===i&&f?.(n):c&&g?.(a("invalid_payload"))},{type:"mqtt/subscribe",topic:`${l}/bridge/response/networkmap`});"function"==typeof p&&b.push(p),await m(y,Math.min(4e3,Math.max(1,s-Date.now()))),c=!0,await t.callService("mqtt","publish",{topic:`${l}/bridge/request/networkmap`,payload:JSON.stringify({type:"raw",routes:!1,transaction:i}),qos:0,retain:!1});const v=await m(w,s-Date.now()),_=d(v)?.status;if(_&&"ok"!==_)throw a("provider");return n(v,l)}finally{for(const t of b)try{t()}catch{}}})}export{f as readZhaTopology,g as refreshZ2mTopology,u as subscribeZigbeeTopology,l as zigbeeTopologyRuntimeSnapshot}; +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{n as t,b as n}from"./zigbee-topology-B-C5QCCD.js";import{F as e}from"./houseplan-card-Bhpi71t0.js";const o=new WeakMap;function i(t){const n=function(t){const n=t?.connection||t;return!n||"object"!=typeof n&&"function"!=typeof n?null:n}(t);if(!n)return null;let e=o.get(n);return e||(e={revision:0,topologies:[],states:{},listeners:new Set,inflight:new Map},o.set(n,e)),e}function r(t,n,e){t.states={...t.states,[n]:e},function(t){t.revision++;for(const n of t.listeners)n()}(t)}function s(t){const n=t?.code;if("permission"===n||"unsupported"===n||"timeout"===n||"invalid_topic"===n||"invalid_payload"===n)return n;const e=String(t?.message||"").toLowerCase();return e.includes("unauthor")||e.includes("permission")?"permission":e.includes("unknown_command")||e.includes("not found")?"unsupported":"provider"}function a(t){return Object.assign(new Error(t),{code:t})}function c(t,n,e){const o=t.inflight.get(n);if(o)return o;r(t,n,{phase:"loading"});const i=e().then(n=>{if(!n.nodes.length&&n.warnings.some(t=>"invalid_payload"===t.code))throw a("invalid_payload");!function(t,n){t.topologies=[...t.topologies.filter(t=>!(t.provider===n.provider&&t.instanceId===n.instanceId)),n],r(t,"zha"===n.provider?"zha":`z2m:${n.instanceId}`,{phase:"ready",obtainedAt:n.obtainedAt,partial:n.warnings.length>0})}(t,n)}).catch(e=>{r(t,n,{phase:"error",error:s(e)})}).finally(()=>t.inflight.delete(n));return t.inflight.set(n,i),i}function l(t){const n=i(t);return n?{revision:n.revision,topologies:n.topologies,states:n.states}:{revision:0,topologies:[],states:{}}}function u(t,n){const e=i(t);return e?(e.listeners.add(n),()=>e.listeners.delete(n)):()=>{}}function f(t){if(!0!==t?.user?.is_admin)throw a("permission")}function p(n){const e=i(n);return e?c(e,"zha",async()=>{if(f(n),"function"!=typeof n?.callWS)throw a("unsupported");return t(await n.callWS({type:"zha/devices"}))}):Promise.resolve()}function d(t){return null!==t&&"object"==typeof t?t:null}function h(t){const n=d(t),e=n?.payload??t;if("string"!=typeof e)return e;try{return JSON.parse(e)}catch{return null}}async function m(t,n){let e;try{return await Promise.race([t,new Promise((t,o)=>{e=globalThis.setTimeout(()=>o(a("timeout")),Math.max(1,n))})])}finally{void 0!==e&&globalThis.clearTimeout(e)}}function g(t,o,r=15e4){const s=i(t);if(!s)return Promise.resolve();const l=e(o);return c(s,`z2m:${l||String(o)}`,async()=>{if(f(t),!l)throw a("invalid_topic");const e=t.connection,o=e?.subscribeMessage;if("function"!=typeof o||"function"!=typeof t?.callService)throw a("unsupported");const i=function(){const t=globalThis.crypto;return"function"==typeof t?.randomUUID?`houseplan-${t.randomUUID()}`:`houseplan-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}(),s=Date.now()+Math.max(1,r);let c=!1,u=null,p=null,g=null;const y=new Promise(t=>{u=t}),w=new Promise((t,n)=>{p=t,g=n}),b=[];try{const r=await o.call(e,t=>{!0===d(t)?.retain&&h(t)&&u?.()},{type:"mqtt/subscribe",topic:`${l}/bridge/info`});"function"==typeof r&&b.push(r);const f=await o.call(e,t=>{if(!0===d(t)?.retain)return;const n=h(t);null!==n?n&&function(t){const n=d(t),e=n?.transaction??d(n?.data)?.transaction;return"string"==typeof e||"number"==typeof e?String(e):null}(n)===i&&p?.(n):c&&g?.(a("invalid_payload"))},{type:"mqtt/subscribe",topic:`${l}/bridge/response/networkmap`});"function"==typeof f&&b.push(f),await m(y,Math.min(4e3,Math.max(1,s-Date.now()))),c=!0,await t.callService("mqtt","publish",{topic:`${l}/bridge/request/networkmap`,payload:JSON.stringify({type:"raw",routes:!1,transaction:i}),qos:0,retain:!1});const v=await m(w,s-Date.now()),_=d(v)?.status;if(_&&"ok"!==_)throw a("provider");return n(v,l)}finally{for(const t of b)try{t()}catch{}}})}export{p as readZhaTopology,g as refreshZ2mTopology,u as subscribeZigbeeTopology,l as zigbeeTopologyRuntimeSnapshot}; diff --git a/custom_components/houseplan/frontend/houseplan-card.js b/custom_components/houseplan/frontend/houseplan-card.js index 2b6b8632..e29c9329 100644 --- a/custom_components/houseplan/frontend/houseplan-card.js +++ b/custom_components/houseplan/frontend/houseplan-card.js @@ -1 +1 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";try{await import("./houseplan-assets/houseplan-card-CODdCIWj.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)} +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";try{await import("./houseplan-assets/houseplan-card-Bhpi71t0.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)} diff --git a/demo/golden/harness.mjs b/demo/golden/harness.mjs index 5aed8580..c72783f6 100644 --- a/demo/golden/harness.mjs +++ b/demo/golden/harness.mjs @@ -896,6 +896,20 @@ export async function prepareGoldenScenario(page, scenario) { const expectedDevices = Object.keys(fixture.devices || {}).length; if (expectedDevices) await until(() => card._devices?.length >= expectedDevices); await until(() => card._booting === false); + // #474: designer furniture artwork is a lazy chunk. The boot gate holds + // the veil until it settles, so by now every piece of the active space + // must be drawn; a fallback here is red, not a silently empty frame + // (the same rule as ensureIsoRuntime: golden never accepts a degraded + // surface as the baseline). + const activeDecor = fixture.config.spaces.find((space) => space.id === card._space)?.decor || []; + const expectedFurniture = activeDecor.filter((shape) => shape.kind === 'furniture').length; + if (expectedFurniture) { + await card.updateComplete; + const drawn = (card.shadowRoot || card.renderRoot).querySelectorAll('[data-kind="furniture"]').length; + if (drawn < expectedFurniture) { + throw new Error(`golden furniture artwork missing: ${scenario.id} (${drawn}/${expectedFurniture})`); + } + } if (scenario.alpha && (window.__hpAlpha !== true || JSON.stringify(window.__hpLabs) !== '["iso"]')) { throw new Error(`alpha contract did not activate isometric capability: ${scenario.id}`); diff --git a/demo/smoke_furniture_lazy_art.mjs b/demo/smoke_furniture_lazy_art.mjs new file mode 100755 index 00000000..fb69b9c5 --- /dev/null +++ b/demo/smoke_furniture_lazy_art.mjs @@ -0,0 +1,156 @@ +// #474: designer furniture artwork lives in a lazy chunk. +// AC2 a plan WITH furniture: the boot veil holds until the artwork lands, +// so the first revealed frame already draws every piece — even when +// the chunk is artificially slow (600 ms, inside BOOT_MAX_MS); +// AC3 a plan WITHOUT furniture never requests the chunk at all; +// AC4 the chunk failing twice (network) settles into fallback: the veil +// lifts, the plan and devices are alive, pieces render as nothing, +// exactly one toast is shown; +// AC5 a chunk from another build is terminal: one import, no retry; +// AC11 two cards on one page share one request. +// The production bundle is served from demo/srv/assets with the demo page's +// CFG patched to carry furniture; the chunk itself is routed per scenario. +import { existsSync, readFileSync } from 'node:fs'; +import { chromium } from 'playwright'; +import { checkAll, finish, watchPage } from './serve.mjs'; + +const manifest = JSON.parse(readFileSync('dist/houseplan-assets.json', 'utf8')); +const artPath = manifest.lazyFurnitureArtFiles?.[0]; +if (!artPath) throw new Error('furniture artwork chunk is absent from the bundle manifest'); +const artName = artPath.split('/').at(-1); +const SRV = new URL('./srv', import.meta.url).pathname; +const CT = { '.html': 'text/html', '.js': 'text/javascript', '.svg': 'image/svg+xml', '.json': 'application/json' }; + +const FURNITURE = `decor:[ + {id:'lazy-sofa', kind:'furniture', symbol:'sofa', x:0.10, y:0.20, w:0.18, h:0.09, rot:0}, + {id:'lazy-fridge', kind:'furniture', symbol:'fridge', x:0.60, y:0.20, w:0.06, h:0.065, rot:0}, + {id:'lazy-bed', kind:'furniture', symbol:'bed_double', x:0.60, y:0.55, w:0.16, h:0.20, rot:0} +], `; + +const demoHtml = (withFurniture, twoCards) => { + let html = readFileSync(`${SRV}/demo.html`, 'utf8'); + if (withFurniture) { + const anchor = "{ id:'f1', title:'Ground floor',"; + if (!html.includes(anchor)) throw new Error('demo.html fixture anchor moved'); + html = html.replace(anchor, `{ id:'f1', title:'Ground floor', ${FURNITURE}`); + } + if (twoCards) { + // A second card with the same config: the page runtime must load the + // artwork once for both. + const anchor = 'window.__card=card;'; + if (!html.includes(anchor)) throw new Error('demo.html card anchor moved'); + html = html.replace(anchor, anchor + + 'const card2=document.createElement("houseplan-card");' + + "card2.setConfig({type:'custom:houseplan-card', title:'Second', icon_size:3.4});" + + 'document.getElementById("host").appendChild(card2);card2.hass=mkHass();window.__card2=card2;'); + } + return html; +}; + +const run = async ({ furniture, twoCards = false, chunk = 'serve', delayMs = 0 }) => { + const browser = await chromium.launch({ args: ['--no-sandbox'] }); + const page = await (await browser.newContext({ viewport: { width: 820, height: 760 } })).newPage(); + watchPage(page); + const requests = []; + let artRequests = 0; + await page.route('**/*', async (route) => { + const url = new URL(route.request().url()); + let p = decodeURIComponent(url.pathname); + if (p === '/') p = '/demo.html'; + requests.push(p); + if (p === '/demo.html') { + return route.fulfill({ status: 200, contentType: 'text/html', body: demoHtml(furniture, twoCards) }); + } + if (p.endsWith(`/${artName}`)) { + artRequests++; + if (chunk === 'abort') return route.abort('failed'); + if (chunk === 'foreign') { + const body = readFileSync(`${SRV}${p}`, 'utf8').replaceAll(manifest.fingerprint, 'another-build'); + return route.fulfill({ status: 200, contentType: 'text/javascript', body }); + } + if (delayMs) await new Promise((resolve) => setTimeout(resolve, delayMs)); + } + const file = `${SRV}${p}`; + return existsSync(file) + ? route.fulfill({ status: 200, headers: { 'content-type': CT[p.slice(p.lastIndexOf('.'))] || 'application/octet-stream' }, body: readFileSync(file) }) + : route.fulfill({ status: 404, body: 'nf' }); + }); + await page.goto('http://demo.local/demo.html', { waitUntil: 'domcontentloaded' }); + await page.waitForFunction(() => window.__card?._model?.length > 0, { timeout: 9000 }); + // The first REVEALED frame: capture what the stage holds the moment the + // veil lifts, before any later re-render could paint the pieces in. + const revealed = await page.evaluate(() => new Promise((resolve) => { + const card = window.__card; + const root = () => card.shadowRoot || card.renderRoot; + const snapshot = () => ({ + furniture: root().querySelectorAll('[data-kind="furniture"]').length, + devices: card._devices?.length ?? 0, + booting: card._booting, + }); + const tick = () => { + if (card._booting === false) return resolve(snapshot()); + setTimeout(tick, 5); + }; + tick(); + })); + await page.waitForFunction(() => window.__card._booting === false, { timeout: 9000 }); + await page.evaluate(() => { const c = window.__card; c.hass = { ...c.hass }; }); + await page.waitForFunction(() => window.__card._devices.length > 0, { timeout: 9000 }); + // Let a possible fallback/toast settle. + await page.waitForTimeout(300); + const after = await page.evaluate(() => { + const card = window.__card; + const root = card.shadowRoot || card.renderRoot; + return { + furniture: root.querySelectorAll('[data-kind="furniture"]').length, + toasts: root.querySelectorAll('.toast').length, + toastText: root.querySelector('.toast')?.textContent?.trim() ?? '', + booting: card._booting, + devices: card._devices.length, + secondCardFurniture: window.__card2 + ? (window.__card2.shadowRoot || window.__card2.renderRoot)?.querySelectorAll('[data-kind="furniture"]').length ?? -1 + : null, + }; + }); + await browser.close(); + return { revealed, after, artRequests, requests }; +}; + +const out = {}; + +// AC2 — furniture in the first revealed frame, chunk slowed by 600 ms. +const slow = await run({ furniture: true, delayMs: 600 }); +out.slowChunkStillDrawnInFirstRevealedFrame = slow.revealed.furniture === 3; +out.slowChunkRequestedExactlyOnce = slow.artRequests === 1; +out.legacyPieceNeedsNoChunk = slow.revealed.furniture >= 1; // fridge is primitive art + +// AC3 — no furniture, no request. +const plain = await run({ furniture: false }); +out.planWithoutFurnitureNeverRequestsArtwork = plain.artRequests === 0 + && !plain.requests.some((p) => p.endsWith(`/${artName}`)); +out.planWithoutFurnitureBootsNormally = plain.after.booting === false && plain.after.devices > 0; + +// AC4 — the chunk fails twice: fallback, veil lifted, plan alive, one toast. +const broken = await run({ furniture: true, chunk: 'abort' }); +out.failedChunkLiftsTheVeil = broken.after.booting === false; +out.failedChunkKeepsPlanAndDevicesAlive = broken.after.devices > 0; +out.failedChunkRetriedExactlyOnce = broken.artRequests === 2; +// Designer pieces (sofa, bed) render as nothing; the legacy fridge still draws. +out.failedChunkDrawsOnlyLegacyPieces = broken.after.furniture === 1; +out.failedChunkShowsOneToast = broken.after.toasts === 1 + && /furniture|мебел/i.test(broken.after.toastText); + +// AC5 — foreign build: terminal, one import, no retry, same fallback. +const foreign = await run({ furniture: true, chunk: 'foreign' }); +out.foreignBuildIsTerminalWithoutRetry = foreign.artRequests === 1; +out.foreignBuildFallsBackLikeNetworkFailure = foreign.after.booting === false + && foreign.after.furniture === 1 && foreign.after.toasts === 1; + +// AC11 — two cards, one request. +const pair = await run({ furniture: true, twoCards: true }); +out.twoCardsShareOneArtworkRequest = pair.artRequests === 1; +out.twoCardsBothDrawFurniture = pair.after.furniture === 3 + && (pair.after.secondCardFurniture === 3 || pair.after.secondCardFurniture === null); + +checkAll(out); +await finish(undefined, out); diff --git a/dist/houseplan-assets.json b/dist/houseplan-assets.json index bd14f84e..85519d88 100644 --- a/dist/houseplan-assets.json +++ b/dist/houseplan-assets.json @@ -1,215 +1,232 @@ { "schema": 1, - "fingerprint": "884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87", + "fingerprint": "0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64", "entry": "houseplan-card.js", "initialViewFiles": [ - "houseplan-assets/houseplan-card-CODdCIWj.js", + "houseplan-assets/houseplan-card-Bhpi71t0.js", "houseplan-card.js" ], - "initialViewGzipBytes": 299595, + "initialViewGzipBytes": 289760, "lazyFiles": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/de-3MG52yOu.js", - "houseplan-assets/editor-BWu14hMI.js", - "houseplan-assets/fr-w8JLXMgW.js", - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js", - "houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js", - "houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js", - "houseplan-assets/iso-scene-render-DXu89PMK.js", - "houseplan-assets/live-interaction-runtime-D5KHv4hp.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js", - "houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/de-D9kcw9QI.js", + "houseplan-assets/editor-CT75Pe-x.js", + "houseplan-assets/fr-D7aFj5IX.js", + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js", + "houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js", + "houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js", + "houseplan-assets/iso-scene-render-DQnNhHBF.js", + "houseplan-assets/live-interaction-runtime-DNx7W_iY.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js", + "houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js" ], - "lazyGzipBytes": 264984, + "lazyGzipBytes": 275381, "lazyEditorFiles": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/editor-BWu14hMI.js", - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/editor-CT75Pe-x.js", + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js" ], - "lazyEditorGzipBytes": 187115, + "lazyEditorGzipBytes": 197465, "lazyOnboardingFiles": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js" ], - "lazyOnboardingGzipBytes": 14328, + "lazyOnboardingGzipBytes": 14323, "lazyLocaleFiles": [ - "houseplan-assets/de-3MG52yOu.js", - "houseplan-assets/fr-w8JLXMgW.js" + "houseplan-assets/de-D9kcw9QI.js", + "houseplan-assets/fr-D7aFj5IX.js" ], - "lazyLocaleGzipBytes": 50178, + "lazyLocaleGzipBytes": 50237, "lazyIsometricFiles": [ - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/iso-scene-render-DXu89PMK.js" + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/iso-scene-render-DQnNhHBF.js" ], - "lazyIsometricGzipBytes": 13467, + "lazyIsometricGzipBytes": 13463, + "lazyFurnitureArtFiles": [ + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js" + ], + "lazyFurnitureArtGzipBytes": 10254, "files": [ { - "path": "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "sha256": "a1a1925a3567418f9f3e3b6541987ecf947ab98d672476a7ecd24468180ed8c7", + "path": "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "sha256": "4fea377a7c8633abf3a619c1fe8218df648376fa7effbd59a51f6102be3d01af", "rawBytes": 21592, - "gzipBytes": 7359, + "gzipBytes": 7357, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/de-3MG52yOu.js", - "sha256": "d85a610248c36842c44cc0b851c62f8aeb8e9431cd71c12b9900d8372b17f8dd", - "rawBytes": 84260, - "gzipBytes": 25368, + "path": "houseplan-assets/de-D9kcw9QI.js", + "sha256": "7371299fa8b9eeb09138acec33d1bf89a1ab890df042ed57b0bd2921c4c6fe29", + "rawBytes": 84392, + "gzipBytes": 25401, "isEntry": false, "imports": [], "dynamicImports": [] }, { - "path": "houseplan-assets/editor-BWu14hMI.js", - "sha256": "e793d2607239b96cbf314e36e4dd1c03017b5c9c7ae47b9d710dd7f47423011d", + "path": "houseplan-assets/editor-CT75Pe-x.js", + "sha256": "ab5edd25d3cd65ad5b312f897ed1a74e6a15331d99d531bf6c1165f6606cc5a3", "rawBytes": 3837, - "gzipBytes": 1589, + "gzipBytes": 1586, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/fr-w8JLXMgW.js", - "sha256": "78da22924a9d38e19e0787ce4c171bfba7df6c18f5460ccd4a2726bc1c415d8e", - "rawBytes": 86301, - "gzipBytes": 24810, + "path": "houseplan-assets/fr-D7aFj5IX.js", + "sha256": "2b946e58a3bee760c5e9cb67a1882456227345d4c091bb2452a0d5c2994e4120", + "rawBytes": 86420, + "gzipBytes": 24836, "isEntry": false, "imports": [], "dynamicImports": [] }, { - "path": "houseplan-assets/guard-BR4mAQsM.js", - "sha256": "31e7c009b3f724ca776293fef20b8ccc3d9f58d6afecb7d1d20be169e827d0a0", + "path": "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "sha256": "b939f374bee1fa1629e6be4bf9cb8d80051b1d13d03990f296dcc77d199a63e7", + "rawBytes": 33655, + "gzipBytes": 10254, + "isEntry": false, + "imports": [], + "dynamicImports": [] + }, + { + "path": "houseplan-assets/guard-BgTQLSGB.js", + "sha256": "dc0c81d0a7167dd708b220e776cab0ad48ec6a1b462918ff984acd347e7beae4", "rawBytes": 518, - "gzipBytes": 371, + "gzipBytes": 369, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/houseplan-card-CODdCIWj.js", - "sha256": "6011cb913b94cd0bb918c28928886a514af39a2162214423e467faf4b8ac31fe", - "rawBytes": 1072122, - "gzipBytes": 298799, + "path": "houseplan-assets/houseplan-card-Bhpi71t0.js", + "sha256": "5e21b20e0a8a762637f9d4360db79ae24d214e3c0ca1dbd59cca4d98116657a7", + "rawBytes": 1041955, + "gzipBytes": 288965, "isEntry": false, "imports": [], "dynamicImports": [ - "houseplan-assets/de-3MG52yOu.js", - "houseplan-assets/editor-BWu14hMI.js", - "houseplan-assets/fr-w8JLXMgW.js", - "houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js", - "houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js", - "houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js", - "houseplan-assets/iso-scene-render-DXu89PMK.js", - "houseplan-assets/live-interaction-runtime-D5KHv4hp.js" + "houseplan-assets/de-D9kcw9QI.js", + "houseplan-assets/editor-CT75Pe-x.js", + "houseplan-assets/fr-D7aFj5IX.js", + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js", + "houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js", + "houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js", + "houseplan-assets/iso-scene-render-DQnNhHBF.js", + "houseplan-assets/live-interaction-runtime-DNx7W_iY.js" ] }, { - "path": "houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js", - "sha256": "f124de9f93faf2aac6f6dcc8d7dfc5d40e7f4d887274843446f6aadb19dae52a", - "rawBytes": 640495, - "gzipBytes": 170365, + "path": "houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js", + "sha256": "06105a4f3e351baeea2b1dac6ec266c0f9bbf53cba6ff6516ec14ae424239f4c", + "rawBytes": 640655, + "gzipBytes": 170475, "isEntry": false, "imports": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/houseplan-card-CODdCIWj.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/furniture-plan-art.generated-Bs3YknKY.js", + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/houseplan-card-Bhpi71t0.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js" ], "dynamicImports": [ - "houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js" + "houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js" ] }, { - "path": "houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js", - "sha256": "7c7a9304466c21ec27ec027f5b3947e0c307538a016f20f4a407e9a43a81a18c", + "path": "houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js", + "sha256": "568a4fd971e96b124d91fae6f250e196cc6da4458e079bbbef0f27a76865fd81", "rawBytes": 28071, - "gzipBytes": 6969, + "gzipBytes": 6966, "isEntry": false, "imports": [ - "houseplan-assets/backdrop-pick-BnsHKWaS.js", - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/backdrop-pick-CV_as5Xh.js", + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js", - "sha256": "e6be2493d605f81e321c5ccd18cfba70dd86ed1816ea54deefa77be48c5e40dd", + "path": "houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js", + "sha256": "55c0f380d7812d8a5dd2cda810d7938eb3b7e2871c23d2d48efe965099b72ba7", "rawBytes": 11034, - "gzipBytes": 3732, + "gzipBytes": 3730, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js", - "houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js", + "houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/iso-scene-render-DXu89PMK.js", - "sha256": "96f20eb2404fd8f6c116de5bfff6a2b109bcd0a250e918eecdf0968df3c6ed9c", + "path": "houseplan-assets/iso-scene-render-DQnNhHBF.js", + "sha256": "49dc2cb9a2866fa2ed4a0cdd7acb5324efff7ddaac932c137bab2907b3f405e0", "rawBytes": 38593, - "gzipBytes": 13096, + "gzipBytes": 13094, "isEntry": false, "imports": [ - "houseplan-assets/guard-BR4mAQsM.js", - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/guard-BgTQLSGB.js", + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/live-interaction-runtime-D5KHv4hp.js", - "sha256": "da0e12640b26ae3ebe05677db6238847813d5c8a7ec0dc7c7149922bc7deac66", + "path": "houseplan-assets/live-interaction-runtime-DNx7W_iY.js", + "sha256": "f6bc3e6f1d8e8528f93c10927e0f81f2cf8d08a3cdc364253cb436ccbc768cc5", "rawBytes": 5196, - "gzipBytes": 2129, + "gzipBytes": 2126, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/zigbee-topology-BUFPOnoy.js", - "sha256": "b497afdec2059b962c9f1a329e7f417650bfa5b28e684544c1ae415340fd208f", + "path": "houseplan-assets/zigbee-topology-B-C5QCCD.js", + "sha256": "f6ba19da3cacff0d88bddf98cf1ee260706ebe3c25c34cfbb24fc8b81c05528e", "rawBytes": 18961, - "gzipBytes": 7431, + "gzipBytes": 7424, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] }, { - "path": "houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js", - "sha256": "ba8f56e776f1d47bea1c211a262154c31c4e13483857e3397ad9f951a8d7f8ce", + "path": "houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js", + "sha256": "71762abfaa68282eba7d584d945c9a9343775143161e8fe9f63bdc90dca1e883", "rawBytes": 3941, - "gzipBytes": 1765, + "gzipBytes": 1763, "isEntry": false, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js", - "houseplan-assets/zigbee-topology-BUFPOnoy.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js", + "houseplan-assets/zigbee-topology-B-C5QCCD.js" ], "dynamicImports": [] }, { "path": "houseplan-card.js", - "sha256": "6e4f5e3ebbe429b4d330f3aff542aa4867fd87f0f249a5185c7429a00670b6d5", + "sha256": "76b219cf7fbba29d64cea0af6400a2ad9d07ab0e08dd46bcd00e4e0856350f0f", "rawBytes": 1183, - "gzipBytes": 796, + "gzipBytes": 795, "isEntry": true, "imports": [ - "houseplan-assets/houseplan-card-CODdCIWj.js" + "houseplan-assets/houseplan-card-Bhpi71t0.js" ], "dynamicImports": [] } diff --git a/dist/houseplan-assets/backdrop-pick-BnsHKWaS.js b/dist/houseplan-assets/backdrop-pick-CV_as5Xh.js similarity index 99% rename from dist/houseplan-assets/backdrop-pick-BnsHKWaS.js rename to dist/houseplan-assets/backdrop-pick-CV_as5Xh.js index 19c56567..ba125214 100644 --- a/dist/houseplan-assets/backdrop-pick-BnsHKWaS.js +++ b/dist/houseplan-assets/backdrop-pick-CV_as5Xh.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{D as e,b as t,A as i,q as o,t as n,dp as r}from"./houseplan-card-CODdCIWj.js";function s(e){const t=e.visualViewport;return t&&Number.isFinite(t.width)&&Number.isFinite(t.height)?{left:Number(t.offsetLeft)||0,top:Number(t.offsetTop)||0,width:Math.max(0,Number(t.width)||0),height:Math.max(0,Number(t.height)||0)}:{left:0,top:0,width:e.innerWidth,height:e.innerHeight}}function a(e,t,i,o=7,n=8){const r=i.left+n,s=i.top+n,a=Math.max(r,i.left+i.width-n),l=Math.max(s,i.top+i.height-n),h=Math.max(0,a-r),d=Math.max(0,l-s),c=Math.min(Math.max(0,t.width),h),u=Math.min(Math.max(0,t.height),d);let p=e.left;p+c>a&&(p=e.right-c),p=Math.min(Math.max(r,p),Math.max(r,a-c));const g=e.bottom+o,_=e.top-o-u;let m="bottom",f=g;return g+u>l&&_>=s?(m="top",f=Math.min(Math.max(s,_),Math.max(s,l-u))):f=Math.min(Math.max(s,g),Math.max(s,l-u)),{left:Math.round(p),top:Math.round(f),side:m,maxWidth:Math.round(h),maxHeight:Math.round(d)}}class l{constructor(e,t,i){this.owner=e,this.name=t,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(e=!1){const t=this.window();return!e&&!!t&&function(e){const t=e.HTMLElement?.prototype;return"function"==typeof t?.showPopover&&"function"==typeof t?.hidePopover}(t)}get hasFallback(){return!!this.host}containsPath(e){return e.includes(this.owner)||!!this.host&&e.includes(this.host)}ownsActiveElement(){let e=this.owner.ownerDocument.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return!(!e||e!==this.owner&&!this.owner.shadowRoot?.contains(e)&&!this.root?.contains(e))}renderFallback(i,o){const n=this.ensureFallback();return n?(e(t`${i}`,n),n):null}surface(e,t){return t?this.owner.shadowRoot?.querySelector(e)||null:this.root?.querySelector(e)||null}destroy(){this.root&&e(i,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const e=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!e)return null;const t=this.owner.ownerDocument.createElement("div");return t.dataset.hpOverlay=this.name,t.style.display="contents",this.keydown&&t.addEventListener("keydown",this.keydown,!0),e.append(t),this.host=t,this.root=t.attachShadow({mode:"open"}),this.root}}let h=0;class d extends n{constructor(){super(...arguments),this.text="",this.ariaLabel="",this.pointerHover=!1,this._open=!1,this._openTimer=0,this._closeTimer=0,this._positionRaf=0,this._forceFallback=!1,this._hoverOwned=!1,this._overlayDispose=null,this._scrollDialog=null,this._descriptionId="hp-help-description-"+ ++h,this._surfacePointerEnter=()=>{const e=this._window();this._closeTimer&&e?.clearTimeout(this._closeTimer),this._closeTimer=0},this._surfacePointerLeave=()=>{this._scheduleClose()},this._outsidePointerDown=e=>{if(!this._open)return;const t=e.composedPath();this._floating.containsPath(t)||this._closeHelp(!1,"outside")},this._dialogScroll=e=>{const t=this._floating.containsPath(e.composedPath()),i=e.target,o=this._dialog(),n=i instanceof Node&&(i===o||i instanceof Element&&i.contains(this));var r;this._open&&(r=n,!t&&r)&&this._closeHelp(!1,"scroll")},this._keyDown=e=>{if(!this._open||e.defaultPrevented)return;if("Escape"===e.key)return e.preventDefault(),e.stopImmediatePropagation(),void this._closeHelp(this._floating.ownsActiveElement(),"escape");const t=this.renderRoot.querySelector(".trigger");if(!t||!e.composedPath().includes(t))return;const i=this._surface();if(!i||i.scrollHeight<=i.clientHeight)return;const o=Math.max(40,.8*i.clientHeight),n={ArrowDown:40,ArrowUp:-40,PageDown:o,PageUp:-o};if("Home"===e.key)i.scrollTop=0;else if("End"===e.key)i.scrollTop=i.scrollHeight;else{if(!(e.key in n))return;i.scrollBy({top:n[e.key],behavior:"auto"})}e.preventDefault(),e.stopImmediatePropagation()},this._floating=new l(this,"help",this._keyDown),this._queuePosition=()=>{if(!this._open||this._positionRaf)return;const e=this._window();e&&(this._positionRaf=e.requestAnimationFrame(()=>{this._positionRaf=0,this._position()||this._closeHelp()}))}}connectedCallback(){super.connectedCallback(),this.addEventListener("keydown",this._keyDown,!0)}willUpdate(){this.toggleAttribute("data-has-content",this._hasContent())}disconnectedCallback(){const e=this.ownerDocument.defaultView;this._unsubscribeOpenListeners(),this.removeEventListener("keydown",this._keyDown,!0),this._clearTimers(),this._positionRaf&&e?.cancelAnimationFrame(this._positionRaf),this._positionRaf=0,this._closeHelp(!1,"disconnect"),super.disconnectedCallback()}updated(e){if(e.has("pointerHover")&&!this.pointerHover){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._openTimer=0,this._hoverOwned&&this._closeHelp(!1,"outside")}this._hasContent()||!this._open?this._open&&e.has("text")&&(this._usesPopover()||this._renderFallback(),this._queuePosition()):this._closeHelp()}_window(){return this._floating.window()}_dialog(){return this._floating.dialog()}_usesPopover(){return this._floating.usesPopover(this._forceFallback)}_hasContent(){return e=this.text,t=this.ariaLabel,"string"==typeof e&&e.trim().length>0&&"string"==typeof t&&t.trim().length>0;var e,t}_clearTimers(){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._closeTimer&&e?.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=0}_scheduleOpen(){const e=this._window();this.pointerHover&&e&&!this._open&&!this._openTimer&&(this._closeTimer&&e.clearTimeout(this._closeTimer),this._closeTimer=0,this._openTimer=e.setTimeout(()=>{this._openTimer=0,this.isConnected&&(this._hoverOwned=!0,this._openHelp())},300))}_scheduleClose(){const e=this._window(),t=this.renderRoot.querySelector(".trigger");e&&!t?.matches(":focus-visible")&&(this._openTimer&&e.clearTimeout(this._openTimer),this._closeTimer&&e.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=e.setTimeout(()=>{this._closeTimer=0,this.isConnected&&this._closeHelp()},150))}_triggerPointerEnter(e){this.pointerHover&&"mouse"===e.pointerType&&this._scheduleOpen()}_triggerPointerLeave(e){"mouse"===e.pointerType&&this._scheduleClose()}_triggerFocus(){queueMicrotask(()=>{const e=this.renderRoot.querySelector(".trigger");e?.matches(":focus-visible")&&(this._hoverOwned=!1,this._openHelp())})}_triggerBlur(){this._scheduleClose()}_triggerClick(){this._open?this._closeHelp():(this._hoverOwned=!1,this._openHelp())}_subscribeOpenListeners(){this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("keydown",this._keyDown,!0);const e=this._window();e?.addEventListener("resize",this._queuePosition),e?.addEventListener("orientationchange",this._queuePosition),e?.visualViewport?.addEventListener("resize",this._queuePosition),e?.visualViewport?.addEventListener("scroll",this._queuePosition),this._scrollDialog=this._dialog(),this._scrollDialog?.addEventListener("scroll",this._dialogScroll,!0)}_unsubscribeOpenListeners(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("keydown",this._keyDown,!0);const e=this._window();e?.removeEventListener("resize",this._queuePosition),e?.removeEventListener("orientationchange",this._queuePosition),e?.visualViewport?.removeEventListener("resize",this._queuePosition),e?.visualViewport?.removeEventListener("scroll",this._queuePosition),this._scrollDialog?.removeEventListener("scroll",this._dialogScroll,!0),this._scrollDialog=null}async _openHelp(){!this._open&&this._hasContent()&&(this._clearTimers(),this._forceFallback=!1,this._open=!0,this._subscribeOpenListeners(),await this.updateComplete,this._open&&(this._usesPopover()||this._renderFallback(),this._position()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:e=>this._closeHelp("escape"===e&&this._floating.ownsActiveElement(),e)})||null:this._closeHelp()))}_closeHelp(e=!1,t="exclusive"){if(!this._open&&!this._floating.hasFallback)return;this._clearTimers();const i=this._overlayDispose;this._overlayDispose=null,i?.();const o=this.renderRoot.querySelector(".tooltip");if(o?.hidePopover)try{o.matches(":popover-open")&&o.hidePopover()}catch{}this._open=!1,this._hoverOwned=!1,this._unsubscribeOpenListeners(),this._floating.destroy(),e&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_tooltipTemplate(e){return t`
    a&&(p=e.right-c),p=Math.min(Math.max(r,p),Math.max(r,a-c));const g=e.bottom+o,_=e.top-o-u;let m="bottom",f=g;return g+u>l&&_>=s?(m="top",f=Math.min(Math.max(s,_),Math.max(s,l-u))):f=Math.min(Math.max(s,g),Math.max(s,l-u)),{left:Math.round(p),top:Math.round(f),side:m,maxWidth:Math.round(h),maxHeight:Math.round(d)}}class l{constructor(e,t,i){this.owner=e,this.name=t,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(e=!1){const t=this.window();return!e&&!!t&&function(e){const t=e.HTMLElement?.prototype;return"function"==typeof t?.showPopover&&"function"==typeof t?.hidePopover}(t)}get hasFallback(){return!!this.host}containsPath(e){return e.includes(this.owner)||!!this.host&&e.includes(this.host)}ownsActiveElement(){let e=this.owner.ownerDocument.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return!(!e||e!==this.owner&&!this.owner.shadowRoot?.contains(e)&&!this.root?.contains(e))}renderFallback(i,o){const n=this.ensureFallback();return n?(e(t`${i}`,n),n):null}surface(e,t){return t?this.owner.shadowRoot?.querySelector(e)||null:this.root?.querySelector(e)||null}destroy(){this.root&&e(i,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const e=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!e)return null;const t=this.owner.ownerDocument.createElement("div");return t.dataset.hpOverlay=this.name,t.style.display="contents",this.keydown&&t.addEventListener("keydown",this.keydown,!0),e.append(t),this.host=t,this.root=t.attachShadow({mode:"open"}),this.root}}let h=0;class d extends n{constructor(){super(...arguments),this.text="",this.ariaLabel="",this.pointerHover=!1,this._open=!1,this._openTimer=0,this._closeTimer=0,this._positionRaf=0,this._forceFallback=!1,this._hoverOwned=!1,this._overlayDispose=null,this._scrollDialog=null,this._descriptionId="hp-help-description-"+ ++h,this._surfacePointerEnter=()=>{const e=this._window();this._closeTimer&&e?.clearTimeout(this._closeTimer),this._closeTimer=0},this._surfacePointerLeave=()=>{this._scheduleClose()},this._outsidePointerDown=e=>{if(!this._open)return;const t=e.composedPath();this._floating.containsPath(t)||this._closeHelp(!1,"outside")},this._dialogScroll=e=>{const t=this._floating.containsPath(e.composedPath()),i=e.target,o=this._dialog(),n=i instanceof Node&&(i===o||i instanceof Element&&i.contains(this));var r;this._open&&(r=n,!t&&r)&&this._closeHelp(!1,"scroll")},this._keyDown=e=>{if(!this._open||e.defaultPrevented)return;if("Escape"===e.key)return e.preventDefault(),e.stopImmediatePropagation(),void this._closeHelp(this._floating.ownsActiveElement(),"escape");const t=this.renderRoot.querySelector(".trigger");if(!t||!e.composedPath().includes(t))return;const i=this._surface();if(!i||i.scrollHeight<=i.clientHeight)return;const o=Math.max(40,.8*i.clientHeight),n={ArrowDown:40,ArrowUp:-40,PageDown:o,PageUp:-o};if("Home"===e.key)i.scrollTop=0;else if("End"===e.key)i.scrollTop=i.scrollHeight;else{if(!(e.key in n))return;i.scrollBy({top:n[e.key],behavior:"auto"})}e.preventDefault(),e.stopImmediatePropagation()},this._floating=new l(this,"help",this._keyDown),this._queuePosition=()=>{if(!this._open||this._positionRaf)return;const e=this._window();e&&(this._positionRaf=e.requestAnimationFrame(()=>{this._positionRaf=0,this._position()||this._closeHelp()}))}}connectedCallback(){super.connectedCallback(),this.addEventListener("keydown",this._keyDown,!0)}willUpdate(){this.toggleAttribute("data-has-content",this._hasContent())}disconnectedCallback(){const e=this.ownerDocument.defaultView;this._unsubscribeOpenListeners(),this.removeEventListener("keydown",this._keyDown,!0),this._clearTimers(),this._positionRaf&&e?.cancelAnimationFrame(this._positionRaf),this._positionRaf=0,this._closeHelp(!1,"disconnect"),super.disconnectedCallback()}updated(e){if(e.has("pointerHover")&&!this.pointerHover){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._openTimer=0,this._hoverOwned&&this._closeHelp(!1,"outside")}this._hasContent()||!this._open?this._open&&e.has("text")&&(this._usesPopover()||this._renderFallback(),this._queuePosition()):this._closeHelp()}_window(){return this._floating.window()}_dialog(){return this._floating.dialog()}_usesPopover(){return this._floating.usesPopover(this._forceFallback)}_hasContent(){return e=this.text,t=this.ariaLabel,"string"==typeof e&&e.trim().length>0&&"string"==typeof t&&t.trim().length>0;var e,t}_clearTimers(){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._closeTimer&&e?.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=0}_scheduleOpen(){const e=this._window();this.pointerHover&&e&&!this._open&&!this._openTimer&&(this._closeTimer&&e.clearTimeout(this._closeTimer),this._closeTimer=0,this._openTimer=e.setTimeout(()=>{this._openTimer=0,this.isConnected&&(this._hoverOwned=!0,this._openHelp())},300))}_scheduleClose(){const e=this._window(),t=this.renderRoot.querySelector(".trigger");e&&!t?.matches(":focus-visible")&&(this._openTimer&&e.clearTimeout(this._openTimer),this._closeTimer&&e.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=e.setTimeout(()=>{this._closeTimer=0,this.isConnected&&this._closeHelp()},150))}_triggerPointerEnter(e){this.pointerHover&&"mouse"===e.pointerType&&this._scheduleOpen()}_triggerPointerLeave(e){"mouse"===e.pointerType&&this._scheduleClose()}_triggerFocus(){queueMicrotask(()=>{const e=this.renderRoot.querySelector(".trigger");e?.matches(":focus-visible")&&(this._hoverOwned=!1,this._openHelp())})}_triggerBlur(){this._scheduleClose()}_triggerClick(){this._open?this._closeHelp():(this._hoverOwned=!1,this._openHelp())}_subscribeOpenListeners(){this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("keydown",this._keyDown,!0);const e=this._window();e?.addEventListener("resize",this._queuePosition),e?.addEventListener("orientationchange",this._queuePosition),e?.visualViewport?.addEventListener("resize",this._queuePosition),e?.visualViewport?.addEventListener("scroll",this._queuePosition),this._scrollDialog=this._dialog(),this._scrollDialog?.addEventListener("scroll",this._dialogScroll,!0)}_unsubscribeOpenListeners(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("keydown",this._keyDown,!0);const e=this._window();e?.removeEventListener("resize",this._queuePosition),e?.removeEventListener("orientationchange",this._queuePosition),e?.visualViewport?.removeEventListener("resize",this._queuePosition),e?.visualViewport?.removeEventListener("scroll",this._queuePosition),this._scrollDialog?.removeEventListener("scroll",this._dialogScroll,!0),this._scrollDialog=null}async _openHelp(){!this._open&&this._hasContent()&&(this._clearTimers(),this._forceFallback=!1,this._open=!0,this._subscribeOpenListeners(),await this.updateComplete,this._open&&(this._usesPopover()||this._renderFallback(),this._position()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:e=>this._closeHelp("escape"===e&&this._floating.ownsActiveElement(),e)})||null:this._closeHelp()))}_closeHelp(e=!1,t="exclusive"){if(!this._open&&!this._floating.hasFallback)return;this._clearTimers();const i=this._overlayDispose;this._overlayDispose=null,i?.();const o=this.renderRoot.querySelector(".tooltip");if(o?.hidePopover)try{o.matches(":popover-open")&&o.hidePopover()}catch{}this._open=!1,this._hoverOwned=!1,this._unsubscribeOpenListeners(),this._floating.destroy(),e&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_tooltipTemplate(e){return t``}_renderFallback(){const e=d.styles.cssText;this._floating.renderFallback(this._tooltipTemplate(!1),e)}_surface(){return this._floating.surface(".tooltip",this._usesPopover())}_position(){if(!this._open)return!1;const e=this._window(),t=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!e||!t?.isConnected||!i?.isConnected)return!1;const o=s(e);if(i.style.maxWidth=`${Math.max(0,Math.min(320,o.width-16))}px`,i.style.maxHeight=`${Math.max(0,o.height-16)}px`,i.style.visibility="hidden",this._usesPopover()&&i.showPopover)try{i.matches(":popover-open")||i.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),i=this._surface(),!i?.isConnected)return!1;i.style.visibility="hidden"}const n=t.getBoundingClientRect(),r=i.getBoundingClientRect();if(!(n.width&&n.height&&r.width&&r.height))return!1;const l=a(n,r,o);return i.style.left=`${l.left}px`,i.style.top=`${l.top}px`,i.dataset.side=l.side,i.style.visibility="",!0}render(){if(!this._hasContent())return i;const e=this.ariaLabel.trim();return t` ({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`r===this.ot[t]))return e}else if(this.ot===t)return e;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,s)}});export{a as i}; diff --git a/dist/houseplan-assets/guard-BgTQLSGB.js b/dist/houseplan-assets/guard-BgTQLSGB.js new file mode 100644 index 00000000..512a5480 --- /dev/null +++ b/dist/houseplan-assets/guard-BgTQLSGB.js @@ -0,0 +1 @@ +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{dJ as r,dK as t,dL as s}from"./houseplan-card-Bhpi71t0.js";const a={},e=r(class extends t{constructor(){super(...arguments),this.ot=a}render(r,t){return t()}update(r,[t,a]){if(Array.isArray(t)){if(Array.isArray(this.ot)&&this.ot.length===t.length&&t.every((r,t)=>r===this.ot[t]))return s}else if(this.ot===t)return s;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,a)}});export{e as i}; diff --git a/dist/houseplan-assets/houseplan-card-CODdCIWj.js b/dist/houseplan-assets/houseplan-card-Bhpi71t0.js similarity index 60% rename from dist/houseplan-assets/houseplan-card-CODdCIWj.js rename to dist/houseplan-assets/houseplan-card-Bhpi71t0.js index ccdb8d1a..4248bacc 100644 --- a/dist/houseplan-assets/houseplan-card-CODdCIWj.js +++ b/dist/houseplan-assets/houseplan-card-Bhpi71t0.js @@ -1,7 +1,7 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),n=new WeakMap;let r=class{constructor(e,t,n){if(this._$cssResult$=!0,n!==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=n.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&n.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const n=1===e.length?e[0]:t.reduce((t,i,n)=>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[n+1],e[0]);return new r(n,e,i)},s=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new r("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:u}=Object,p=globalThis,_=p.trustedTypes,m=_?_.emptyScript:"",g=p.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}},y=(e,t)=>!a(e,t),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.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=b){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(),n=this.getPropertyDescriptor(e,i,t);void 0!==n&&l(this.prototype,e,n)}}static getPropertyDescriptor(e,t,i){const{get:n,set:r}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:n,set(t){const o=n?.call(this);r?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=u(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(s(e))}else void 0!==e&&t.push(s(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,n)=>{if(t)i.adoptedStyleSheets=n.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of n){const n=document.createElement("style"),r=e.litNonce;void 0!==r&&n.setAttribute("nonce",r),n.textContent=t.cssText,i.appendChild(n)}})(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),n=this.constructor._$Eu(e,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(e,t){const i=this.constructor,n=i._$Eh.get(e);if(void 0!==n&&this._$Em!==n){const e=i.getPropertyOptions(n),r="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=n;const o=r.fromAttribute(t,e.type);this[n]=o??this._$Ej?.get(n)??o,this._$Em=null}}requestUpdate(e,t,i,n=!1,r){if(void 0!==e){const o=this.constructor;if(!1===n&&(r=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??y)(r,t)||i.useDefault&&i.reflect&&r===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:n,wrapped:r},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==r||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===n&&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,n=this[t];!0!==e||this._$AL.has(t)||void 0===n||this.C(t,void 0,i,n)}}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}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,S=k.trustedTypes,$=S?S.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",R=`lit$${Math.random().toFixed(9).slice(2)}$`,C="?"+R,T=`<${C}>`,D=document,z=()=>D.createComment(""),A=e=>null===e||"object"!=typeof e&&"function"!=typeof e,P=Array.isArray,F="[ \t\n\f\r]",I=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,O=/-->/g,E=/>/g,H=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),N=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),W=q(1),j=q(2),U=Symbol.for("lit-noChange"),V=Symbol.for("lit-nothing"),G=new WeakMap,K=D.createTreeWalker(D,129);function Y(e,t){if(!P(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==$?$.createHTML(t):t}const X=(e,t)=>{const i=e.length-1,n=[];let r,o=2===t?"":3===t?"":"",s=I;for(let t=0;t"===l[0]?(s=r??I,c=-1):void 0===l[1]?c=-2:(c=s.lastIndex-l[2].length,a=l[1],s=void 0===l[3]?H:'"'===l[3]?L:N):s===L||s===N?s=H:s===O||s===E?s=I:(s=H,r=void 0);const d=s===H&&e[t+1].startsWith("/>")?" ":"";o+=s===I?i+T:c>=0?(n.push(a),i.slice(0,c)+M+i.slice(c)+R+d):i+R+(-2===c?t:d)}return[Y(e,o+(e[i]||"")+(2===t?"":3===t?"":"")),n]};class Z{constructor({strings:e,_$litType$:t},i){let n;this.parts=[];let r=0,o=0;const s=e.length-1,a=this.parts,[l,c]=X(e,t);if(this.el=Z.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(n=K.nextNode())&&a.length0){n.textContent=S?S.emptyScript:"";for(let i=0;iP(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!==V&&A(this._$AH)?this._$AA.nextSibling.data=e:this.T(D.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,n="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=Z.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(t);else{const e=new Q(n,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=G.get(e.strings);return void 0===t&&G.set(e.strings,t=new Z(e)),t}k(e){P(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,n=0;for(const r of e)n===t.length?t.push(i=new ee(this.O(z()),this.O(z()),this,this.options)):i=t[n],i._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=V}_$AI(e,t=this,i,n){const r=this.strings;let o=!1;if(void 0===r)e=J(this,e,t,0),o=!A(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const n=e;let s,a;for(e=r[0],s=0;s{const n=i?.renderBefore??t;let r=n._$litPart$;if(void 0===r){const e=i?.renderBefore??null;n._$litPart$=r=new ee(t.insertBefore(z(),e),e,void 0,i??{})}return r._$AI(e),r},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 ue=2,pe=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{I:me}=se,ge=e=>e,fe=(e,t)=>void 0!==e?._$litType$,ve=()=>document.createComment(""),ye=(e,t,i)=>{const n=e._$AA.parentNode,r=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=n.insertBefore(ve(),r),o=n.insertBefore(ve(),r);i=new me(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,s=o!==e;if(s){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==r||s){let e=i._$AA;for(;e!==t;){const t=ge(e).nextSibling;ge(n).insertBefore(e,r),e=t}}}return i},be=(e,t,i=e)=>(e._$AI(t,i),e),we={},ke=(e,t=we)=>e._$AH=t,xe=e=>e._$AH,Se=e=>{e._$AR(),e._$AA.remove()},$e=e=>(e=>null!=e?._$litType$?.h)(e)?e._$litType$.h:e.strings,Me=pe(class extends _e{constructor(e){super(e),this.et=new WeakMap}render(e){return[e]}update(e,[t]){const i=fe(this.it)?$e(this.it):null,n=fe(t)?$e(t):null;if(null!==i&&(null===n||i!==n)){const t=xe(e).pop();let n=this.et.get(i);if(void 0===n){const e=document.createDocumentFragment();n=le(V,e),n.setConnected(!1),this.et.set(i,n)}ke(n,[t]),ye(n,void 0,t)}if(null!==n){if(null===i||i!==n){const t=this.et.get(n);if(void 0!==t){const i=xe(t).pop();(e=>{e._$AR()})(e),ye(e,void 0,i),ke(e,[i])}}this.it=t}else this.it=void 0;return this.render(t)}}),Re=new WeakMap;let Ce=0;class Te extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=null,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Ce,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._usesHaDialog()?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._usesHaDialog())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 n=this._deepActiveElement(),r=i[0],o=i[i.length-1];!e.shiftKey||n!==r&&i.includes(n)?e.shiftKey||n!==o||(e.preventDefault(),r.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}_usesHaDialog(){return!0===this._useHaDialog&&!this.alert}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Re.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Re.set(e,t),null===this._useHaDialog&&(this._useHaDialog=!!customElements.get("ha-dialog")),this.addEventListener("keydown",this._onKeyDown,!0),queueMicrotask(()=>{this._ensureNativeModal()&&this._focusInitial()})}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 n=t?Re.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=Re.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Re.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){super.firstUpdated(e),this._ensureNativeModal(),queueMicrotask(()=>this._focusInitial())}updated(e){super.updated(e),this._ensureNativeModal()}_ensureNativeModal(){if(this._usesHaDialog()||!this.isConnected)return!1;const e=this.renderRoot.querySelector("dialog");if(!e?.isConnected)return!1;try{return!e.matches(":modal")&&(e.open&&e.close(),e.showModal(),!0)}catch{return!1}}_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,n=r=>{if(!i.has(r)){if(i.add(r),r instanceof HTMLElement){if(r.matches(e)&&t.push(r),r instanceof HTMLSlotElement){for(const e of r.assignedNodes({flatten:!0}))n(e);return}if(r.shadowRoot){for(const e of r.shadowRoot.childNodes)n(e);return}}for(const e of r.childNodes)n(e)}};for(const e of this.childNodes)n(e);const r=this.overlayPortal();return r&&n(r),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})}rejectClose(){this._closing=!1,this.requestUpdate()}_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 n={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(n);let r=!1;return()=>{if(r)return;r=!0;const e=this._overlays.findIndex(e=>e.token===n.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=W` - ${this.icon?W``:V} +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),n=new WeakMap;let r=class{constructor(e,t,n){if(this._$cssResult$=!0,n!==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=n.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&n.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const n=1===e.length?e[0]:t.reduce((t,i,n)=>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[n+1],e[0]);return new r(n,e,i)},s=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new r("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:u}=Object,p=globalThis,_=p.trustedTypes,m=_?_.emptyScript:"",g=p.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}},y=(e,t)=>!a(e,t),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.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=b){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(),n=this.getPropertyDescriptor(e,i,t);void 0!==n&&l(this.prototype,e,n)}}static getPropertyDescriptor(e,t,i){const{get:n,set:r}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:n,set(t){const o=n?.call(this);r?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=u(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(s(e))}else void 0!==e&&t.push(s(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,n)=>{if(t)i.adoptedStyleSheets=n.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of n){const n=document.createElement("style"),r=e.litNonce;void 0!==r&&n.setAttribute("nonce",r),n.textContent=t.cssText,i.appendChild(n)}})(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),n=this.constructor._$Eu(e,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(e,t){const i=this.constructor,n=i._$Eh.get(e);if(void 0!==n&&this._$Em!==n){const e=i.getPropertyOptions(n),r="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=n;const o=r.fromAttribute(t,e.type);this[n]=o??this._$Ej?.get(n)??o,this._$Em=null}}requestUpdate(e,t,i,n=!1,r){if(void 0!==e){const o=this.constructor;if(!1===n&&(r=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??y)(r,t)||i.useDefault&&i.reflect&&r===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:n,wrapped:r},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==r||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===n&&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,n=this[t];!0!==e||this._$AL.has(t)||void 0===n||this.C(t,void 0,i,n)}}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}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,S=k.trustedTypes,$=S?S.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",R=`lit$${Math.random().toFixed(9).slice(2)}$`,C="?"+R,T=`<${C}>`,D=document,A=()=>D.createComment(""),P=e=>null===e||"object"!=typeof e&&"function"!=typeof e,F=Array.isArray,z="[ \t\n\f\r]",I=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,O=/-->/g,E=/>/g,N=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),j=q(1),W=q(2),U=Symbol.for("lit-noChange"),V=Symbol.for("lit-nothing"),G=new WeakMap,K=D.createTreeWalker(D,129);function Y(e,t){if(!F(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==$?$.createHTML(t):t}const X=(e,t)=>{const i=e.length-1,n=[];let r,o=2===t?"":3===t?"":"",s=I;for(let t=0;t"===l[0]?(s=r??I,c=-1):void 0===l[1]?c=-2:(c=s.lastIndex-l[2].length,a=l[1],s=void 0===l[3]?N:'"'===l[3]?L:H):s===L||s===H?s=N:s===O||s===E?s=I:(s=N,r=void 0);const d=s===N&&e[t+1].startsWith("/>")?" ":"";o+=s===I?i+T:c>=0?(n.push(a),i.slice(0,c)+M+i.slice(c)+R+d):i+R+(-2===c?t:d)}return[Y(e,o+(e[i]||"")+(2===t?"":3===t?"":"")),n]};class Z{constructor({strings:e,_$litType$:t},i){let n;this.parts=[];let r=0,o=0;const s=e.length-1,a=this.parts,[l,c]=X(e,t);if(this.el=Z.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(n=K.nextNode())&&a.length0){n.textContent=S?S.emptyScript:"";for(let i=0;iF(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!==V&&P(this._$AH)?this._$AA.nextSibling.data=e:this.T(D.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,n="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=Z.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(t);else{const e=new Q(n,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=G.get(e.strings);return void 0===t&&G.set(e.strings,t=new Z(e)),t}k(e){F(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,n=0;for(const r of e)n===t.length?t.push(i=new ee(this.O(A()),this.O(A()),this,this.options)):i=t[n],i._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=V}_$AI(e,t=this,i,n){const r=this.strings;let o=!1;if(void 0===r)e=J(this,e,t,0),o=!P(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const n=e;let s,a;for(e=r[0],s=0;s{const n=i?.renderBefore??t;let r=n._$litPart$;if(void 0===r){const e=i?.renderBefore??null;n._$litPart$=r=new ee(t.insertBefore(A(),e),e,void 0,i??{})}return r._$AI(e),r},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 ue=2,pe=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{I:me}=se,ge=e=>e,fe=(e,t)=>void 0!==e?._$litType$,ve=()=>document.createComment(""),ye=(e,t,i)=>{const n=e._$AA.parentNode,r=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=n.insertBefore(ve(),r),o=n.insertBefore(ve(),r);i=new me(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,s=o!==e;if(s){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==r||s){let e=i._$AA;for(;e!==t;){const t=ge(e).nextSibling;ge(n).insertBefore(e,r),e=t}}}return i},be=(e,t,i=e)=>(e._$AI(t,i),e),we={},ke=(e,t=we)=>e._$AH=t,xe=e=>e._$AH,Se=e=>{e._$AR(),e._$AA.remove()},$e=e=>(e=>null!=e?._$litType$?.h)(e)?e._$litType$.h:e.strings,Me=pe(class extends _e{constructor(e){super(e),this.et=new WeakMap}render(e){return[e]}update(e,[t]){const i=fe(this.it)?$e(this.it):null,n=fe(t)?$e(t):null;if(null!==i&&(null===n||i!==n)){const t=xe(e).pop();let n=this.et.get(i);if(void 0===n){const e=document.createDocumentFragment();n=le(V,e),n.setConnected(!1),this.et.set(i,n)}ke(n,[t]),ye(n,void 0,t)}if(null!==n){if(null===i||i!==n){const t=this.et.get(n);if(void 0!==t){const i=xe(t).pop();(e=>{e._$AR()})(e),ye(e,void 0,i),ke(e,[i])}}this.it=t}else this.it=void 0;return this.render(t)}}),Re=new WeakMap;let Ce=0;class Te extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=null,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Ce,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._usesHaDialog()?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._usesHaDialog())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 n=this._deepActiveElement(),r=i[0],o=i[i.length-1];!e.shiftKey||n!==r&&i.includes(n)?e.shiftKey||n!==o||(e.preventDefault(),r.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}_usesHaDialog(){return!0===this._useHaDialog&&!this.alert}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Re.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Re.set(e,t),null===this._useHaDialog&&(this._useHaDialog=!!customElements.get("ha-dialog")),this.addEventListener("keydown",this._onKeyDown,!0),queueMicrotask(()=>{this._ensureNativeModal()&&this._focusInitial()})}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 n=t?Re.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=Re.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Re.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){super.firstUpdated(e),this._ensureNativeModal(),queueMicrotask(()=>this._focusInitial())}updated(e){super.updated(e),this._ensureNativeModal()}_ensureNativeModal(){if(this._usesHaDialog()||!this.isConnected)return!1;const e=this.renderRoot.querySelector("dialog");if(!e?.isConnected)return!1;try{return!e.matches(":modal")&&(e.open&&e.close(),e.showModal(),!0)}catch{return!1}}_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,n=r=>{if(!i.has(r)){if(i.add(r),r instanceof HTMLElement){if(r.matches(e)&&t.push(r),r instanceof HTMLSlotElement){for(const e of r.assignedNodes({flatten:!0}))n(e);return}if(r.shadowRoot){for(const e of r.shadowRoot.childNodes)n(e);return}}for(const e of r.childNodes)n(e)}};for(const e of this.childNodes)n(e);const r=this.overlayPortal();return r&&n(r),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})}rejectClose(){this._closing=!1,this.requestUpdate()}_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 n={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(n);let r=!1;return()=>{if(r)return;r=!0;const e=this._overlays.findIndex(e=>e.token===n.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=j` + ${this.icon?j``:V} ${this.title} - `;return this._usesHaDialog()?this.describedBy?W``;return this._usesHaDialog()?this.describedBy?j`${e} -
    `:W`
    `:j`${e}
    -
    `:W`
    `:j` - ${e.objectName?W`${e.objectName}`:null} + ${e.objectName?j`${e.objectName}`:null}

    ${e.message}

    - `}}De.properties={hass:{attribute:!1},request:{attribute:!1},token:{type:Number}},customElements.get("hp-confirm")||customElements.define("hp-confirm",De);class ze{constructor(e){this._changed=e,this._sequence=0,this._active=null}get state(){return this._active?{token:this._active.token,request:this._active.request}:null}confirm(e){this.cancel();const t={token:++this._sequence,request:Object.freeze({...e})};return new Promise(e=>{this._active={...t,resolve:e},this._changed(t)})}resolve(e,t){const i=this._active;return!(!i||i.token!==e)&&(this._active=null,this._changed(null),i.resolve(t),!0)}cancel(){const e=this._active;return!!e&&this.resolve(e.token,!1)}}const Ae=new Set(["hacs","sun","backup","hassio","met","telegram_bot","mobile_app","systemmonitor","better_thermostat","adaptive_lighting","yandex_pogoda","upnp_serial_number"]),Pe=[{pattern:"протечк|leak|water sensor",icon:"mdi:water-alert"},{pattern:"клапан|valve",icon:"mdi:pipe-valve"},{pattern:"дым|smoke",icon:"mdi:smoke-detector"},{pattern:"термоголов|trv|radiator",icon:"mdi:radiator"},{pattern:"чайник|kettle|термопот",icon:"mdi:kettle"},{pattern:"сауна|sauna|harvia|парная|парилк",icon:"mdi:hot-tub"},{pattern:"температ|temperature|thermometer|climate sensor",icon:"mdi:thermometer"},{pattern:"qingping|air monitor|молекул|air quality",icon:"mdi:air-filter"},{pattern:"штор|curtain|blind|shade",icon:"mdi:roller-shade"},{pattern:"розетк|plug|socket|outlet",icon:"mdi:power-socket-de"},{pattern:"выключат|switch",icon:"mdi:light-switch"},{pattern:"лампа|лампочк|bulb|gx53|светильник|rgb|lamp|light strip",icon:"mdi:lightbulb"},{pattern:"камер|camera",icon:"mdi:cctv"},{pattern:"замок|ttlock|lock|sn609|sn9161",icon:"mdi:lock"},{pattern:"ворота|garage|gate",icon:"mdi:garage-variant"},{pattern:"калитк|door|открыт|contact",icon:"mdi:door"},{pattern:"счётчик|счетчик|kws|meter",icon:"mdi:meter-electric"},{pattern:"вводный автомат|breaker|wifimcbn",icon:"mdi:electric-switch"},{pattern:"myheat|котёл|котел|boiler|отоплен|heating",icon:"mdi:water-boiler"},{pattern:"холодильник|fridge",icon:"mdi:fridge"},{pattern:"стиральн|washer|washing",icon:"mdi:washing-machine"},{pattern:"сушилк|dryer",icon:"mdi:tumble-dryer"},{pattern:"пылесос|vacuum|dreame|roborock",icon:"mdi:robot-vacuum"},{pattern:"soundbar",icon:"mdi:soundbar"},{pattern:"колонк|станц|speaker|яндекс|yandex|алиса|alice",icon:"mdi:speaker"},{pattern:"tv|телевизор|hyundaitv|mitv|television",icon:"mdi:television"},{pattern:"keenetic|роутер|router|mesh|access point",icon:"mdi:router-wireless"},{pattern:"ибп|ups|kirpich",icon:"mdi:battery-charging-high"},{pattern:"slzb|координат|zigbee|coordinator",icon:"mdi:zigbee"},{pattern:"motion|движен|presence|присутств",icon:"mdi:motion-sensor"},{pattern:"humidity|влажн",icon:"mdi:water-percent"}];function Fe(e){const t=[];for(const i of e)if(i&&"string"==typeof i.pattern&&i.icon)try{t.push({re:new RegExp(i.pattern,"i"),icon:i.icon})}catch{}return t}function Ie(e){try{return new RegExp(e,"i"),!0}catch{return!1}}const Oe=Fe(Pe),Ee={temperature:"mdi:thermometer",humidity:"mdi:water-percent",motion:"mdi:motion-sensor",occupancy:"mdi:motion-sensor",presence:"mdi:motion-sensor",door:"mdi:door",window:"mdi:window-closed",garage_door:"mdi:garage-variant",smoke:"mdi:smoke-detector",moisture:"mdi:water-alert",gas:"mdi:gas-cylinder",power:"mdi:meter-electric",energy:"mdi:meter-electric",illuminance:"mdi:brightness-5",co2:"mdi:molecule-co2",pm25:"mdi:air-filter",battery:"mdi:battery"},He="mdi:chip";function Ne(e,t,i){const n=((e||"")+" "+(t||"")).toLowerCase();for(const{re:e,icon:t}of i??Oe)if(e.test(n))return t;return He}const Le=["light","switch","cover","valve","lock","climate","fan","media_player","camera","vacuum","humidifier","water_heater","alarm_control_panel","sensor","binary_sensor","event","button","number","select","update"];var Be=/^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i,qe=Math.ceil,We=Math.floor,je="[BigNumber Error] ",Ue=je+"Number primitive has more than 15 significant digits: ",Ve=1e14,Ge=14,Ke=9007199254740991,Ye=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],Xe=1e7,Ze=1e9;function Je(e){var t=0|e;return e>0||e===t?t:t-1}function Qe(e){for(var t,i,n=1,r=e.length,o=e[0]+"";nc^i?1:-1;for(a=(l=r.length)<(c=o.length)?l:c,s=0;so[s]^i?1:-1;return l==c?0:l>c^i?1:-1}function tt(e,t,i,n){if(ei||e!==We(e))throw Error(je+(n||"Argument")+("number"==typeof e?ei?" out of range: ":" not an integer: ":" not a primitive number: ")+String(e))}function it(e){var t=e.c.length-1;return Je(e.e/Ge)==t&&e.c[t]%2!=0}function nt(e,t){return(e.length>1?e.charAt(0)+"."+e.slice(1):e)+(t<0?"e":"e+")+t}function rt(e,t,i){var n,r;if(t<0){for(r=i+".";++t;r+=i);e=r+e}else if(++t>(n=e.length)){for(r=i,t-=n;--t;r+=i);e+=r}else ty?u.c=u.e=null:e.e=10;l/=10,a++);return void(a>y?u.c=u.e=null:(u.e=a,u.c=[e]))}d=String(e)}else{if(!Be.test(d=String(e)))return r(u,d,c);u.s=45==d.charCodeAt(0)?(d=d.slice(1),-1):1}(a=d.indexOf("."))>-1&&(d=d.replace(".","")),(l=d.search(/e/i))>0?(a<0&&(a=l),a+=+d.slice(l+1),d=d.substring(0,l)):a<0&&(a=d.length)}else{if(tt(t,2,S.length,"Base"),10==t&&$)return D(u=new M(e),_+u.e+1,m);if(d=String(e),c="number"==typeof e){if(0*e!=0)return r(u,d,c,t);if(u.s=1/e<0?(d=d.slice(1),-1):1,M.DEBUG&&d.replace(/^0\.0*|\./,"").length>15)throw Error(Ue+e)}else u.s=45===d.charCodeAt(0)?(d=d.slice(1),-1):1;for(i=S.slice(0,t),a=l=0,h=d.length;la){a=h;continue}}else if(!s&&(d==d.toUpperCase()&&(d=d.toLowerCase())||d==d.toLowerCase()&&(d=d.toUpperCase()))){s=!0,l=-1,a=0;continue}return r(u,String(e),c,t)}c=!1,(a=(d=n(d,t,10,u.s)).indexOf("."))>-1?d=d.replace(".",""):a=d.length}for(l=0;48===d.charCodeAt(l);l++);for(h=d.length;48===d.charCodeAt(--h););if(d=d.slice(l,++h)){if(h-=l,c&&M.DEBUG&&h>15&&(e>Ke||e!==We(e)))throw Error(Ue+u.s*e);if((a=a-l-1)>y)u.c=u.e=null;else if(a=f)?nt(l,s):rt(l,s,"0");else if(o=(e=D(new M(e),t,i)).e,a=(l=Qe(e.c)).length,1==n||2==n&&(t<=o||o<=g)){for(;as),l=rt(l,o,"0"),o+1>a){if(--t>0)for(l+=".";t--;l+="0");}else if((t+=o-a)>0)for(o+1==a&&(l+=".");t--;l+="0");return e.s<0&&r?"-"+l:l}function C(e,t){for(var i,n,r=1,o=new M(e[0]);r=10;r/=10,n++);return(i=n+i*Ge-1)>y?e.c=e.e=null:i=10;a/=10,r++);if((o=t-r)<0)o+=Ge,s=t,l=d[c=0],h=We(l/u[r-s-1]%10);else if((c=qe((o+1)/Ge))>=d.length){if(!n)break e;for(;d.length<=c;d.push(0));l=h=0,r=1,s=(o%=Ge)-Ge+1}else{for(l=a=d[c],r=1;a>=10;a/=10,r++);h=(s=(o%=Ge)-Ge+r)<0?0:We(l/u[r-s-1]%10)}if(n=n||t<0||null!=d[c+1]||(s<0?l:l%u[r-s-1]),n=i<4?(h||n)&&(0==i||i==(e.s<0?3:2)):h>5||5==h&&(4==i||n||6==i&&(o>0?s>0?l/u[r-s]:0:d[c-1])%10&1||i==(e.s<0?8:7)),t<1||!d[0])return d.length=0,n?(t-=e.e+1,d[0]=u[(Ge-t%Ge)%Ge],e.e=-t||0):d[0]=e.e=0,e;if(0==o?(d.length=c,a=1,c--):(d.length=c+1,a=u[Ge-o],d[c]=s>0?We(l/u[r-s]%u[s])*a:0),n)for(;;){if(0==c){for(o=1,s=d[0];s>=10;s/=10,o++);for(s=d[0]+=a,a=1;s>=10;s/=10,a++);o!=a&&(e.e++,d[0]==Ve&&(d[0]=1));break}if(d[c]+=a,d[c]!=Ve)break;d[c--]=0,a=1}for(o=d.length;0===d[--o];d.pop());}e.e>y?e.c=e.e=null:e.e=f?nt(t,i):rt(t,i,"0"),e.s<0?"-"+t:t)}return M.clone=e,M.ROUND_UP=0,M.ROUND_DOWN=1,M.ROUND_CEIL=2,M.ROUND_FLOOR=3,M.ROUND_HALF_UP=4,M.ROUND_HALF_DOWN=5,M.ROUND_HALF_EVEN=6,M.ROUND_HALF_CEIL=7,M.ROUND_HALF_FLOOR=8,M.EUCLID=9,M.config=M.set=function(e){var t,i;if(null!=e){if("object"!=typeof e)throw Error(je+"Object expected: "+e);if(e.hasOwnProperty(t="DECIMAL_PLACES")&&(tt(i=e[t],0,Ze,t),_=i),e.hasOwnProperty(t="ROUNDING_MODE")&&(tt(i=e[t],0,8,t),m=i),e.hasOwnProperty(t="EXPONENTIAL_AT")&&((i=e[t])&&i.pop?(tt(i[0],-Ze,0,t),tt(i[1],0,Ze,t),g=i[0],f=i[1]):(tt(i,-Ze,Ze,t),g=-(f=i<0?-i:i))),e.hasOwnProperty(t="RANGE"))if((i=e[t])&&i.pop)tt(i[0],-Ze,-1,t),tt(i[1],1,Ze,t),v=i[0],y=i[1];else{if(tt(i,-Ze,Ze,t),!i)throw Error(je+t+" cannot be zero: "+i);v=-(y=i<0?-i:i)}if(e.hasOwnProperty(t="CRYPTO")){if((i=e[t])!==!!i)throw Error(je+t+" not true or false: "+i);if(i){if("undefined"==typeof crypto||!crypto||!crypto.getRandomValues&&!crypto.randomBytes)throw b=!i,Error(je+"crypto unavailable");b=i}else b=i}if(e.hasOwnProperty(t="MODULO_MODE")&&(tt(i=e[t],0,9,t),w=i),e.hasOwnProperty(t="POW_PRECISION")&&(tt(i=e[t],0,Ze,t),k=i),e.hasOwnProperty(t="FORMAT")){if("object"!=typeof(i=e[t]))throw Error(je+t+" not an object: "+i);x=i}if(e.hasOwnProperty(t="ALPHABET")){if("string"!=typeof(i=e[t])||/^.?$|[+\-.\s]|(.).*\1/.test(i))throw Error(je+t+" invalid: "+i);$="0123456789"==i.slice(0,10),S=i}}return{DECIMAL_PLACES:_,ROUNDING_MODE:m,EXPONENTIAL_AT:[g,f],RANGE:[v,y],CRYPTO:b,MODULO_MODE:w,POW_PRECISION:k,FORMAT:x,ALPHABET:S}},M.isBigNumber=function(e){if(!e||!0!==e._isBigNumber)return!1;if(!M.DEBUG)return!0;var t,i,n=e.c,r=e.e,o=e.s;e:if("[object Array]"=={}.toString.call(n)){if((1===o||-1===o)&&r>=-Ze&&r<=Ze&&r===We(r)){if(0===n[0]){if(0===r&&1===n.length)return!0;break e}if((t=(r+1)%Ge)<1&&(t+=Ge),String(n[0]).length==t){for(t=0;t=Ve||i!==We(i))break e;if(0!==i)return!0}}}else if(null===n&&null===r&&(null===o||1===o||-1===o))return!0;throw Error(je+"Invalid BigNumber: "+e)},M.maximum=M.max=function(){return C(arguments,-1)},M.minimum=M.min=function(){return C(arguments,1)},M.random=(o=9007199254740992,s=Math.random()*o&2097151?function(){return We(Math.random()*o)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)},function(e){var t,i,n,r,o,a=0,l=[],c=new M(p);if(null==e?e=_:tt(e,0,Ze),r=qe(e/Ge),b)if(crypto.getRandomValues){for(t=crypto.getRandomValues(new Uint32Array(r*=2));a>>11))>=9e15?(i=crypto.getRandomValues(new Uint32Array(2)),t[a]=i[0],t[a+1]=i[1]):(l.push(o%1e14),a+=2);a=r/2}else{if(!crypto.randomBytes)throw b=!1,Error(je+"crypto unavailable");for(t=crypto.randomBytes(r*=7);a=9e15?crypto.randomBytes(7).copy(t,a):(l.push(o%1e14),a+=7);a=r/7}if(!b)for(;a=10;o/=10,a++);ai-1&&(null==s[r+1]&&(s[r+1]=0),s[r+1]+=s[r]/i|0,s[r]%=i)}return s.reverse()}return function(n,r,o,s,a){var l,c,h,d,u,p,g,f,v=n.indexOf("."),y=_,b=m;for(v>=0&&(d=k,k=0,n=n.replace(".",""),p=(f=new M(r)).pow(n.length-v),k=d,f.c=t(rt(Qe(p.c),p.e,"0"),10,o,e),f.e=f.c.length),h=d=(g=t(n,r,o,a?(l=S,e):(l=e,S))).length;0==g[--d];g.pop());if(!g[0])return l.charAt(0);if(v<0?--h:(p.c=g,p.e=h,p.s=s,g=(p=i(p,f,y,b,o)).c,u=p.r,h=p.e),v=g[c=h+y+1],d=o/2,u=u||c<0||null!=g[c+1],u=b<4?(null!=v||u)&&(0==b||b==(p.s<0?3:2)):v>d||v==d&&(4==b||u||6==b&&1&g[c-1]||b==(p.s<0?8:7)),c<1||!g[0])n=u?rt(l.charAt(1),-y,l.charAt(0)):l.charAt(0);else{if(g.length=c,u)for(--o;++g[--c]>o;)g[c]=0,c||(++h,g=[1].concat(g));for(d=g.length;!g[--d];);for(v=0,n="";v<=d;n+=l.charAt(g[v++]));n=rt(n,h,l.charAt(0))}return n}}(),i=function(){function e(e,t,i){var n,r,o,s,a=0,l=e.length,c=t%Xe,h=t/Xe|0;for(e=e.slice();l--;)a=((r=c*(o=e[l]%Xe)+(n=h*o+(s=e[l]/Xe|0)*c)%Xe*Xe+a)/i|0)+(n/Xe|0)+h*s,e[l]=r%i;return a&&(e=[a].concat(e)),e}function t(e,t,i,n){var r,o;if(i!=n)o=i>n?1:-1;else for(r=o=0;rt[r]?1:-1;break}return o}function i(e,t,i,n){for(var r=0;i--;)e[i]-=r,r=e[i]1;e.splice(0,1));}return function(n,r,o,s,a){var l,c,h,d,u,p,_,m,g,f,v,y,b,w,k,x,S,$=n.s==r.s?1:-1,R=n.c,C=r.c;if(!(R&&R[0]&&C&&C[0]))return new M(n.s&&r.s&&(R?!C||R[0]!=C[0]:C)?R&&0==R[0]||!C?0*$:$/0:NaN);for(g=(m=new M($)).c=[],$=o+(c=n.e-r.e)+1,a||(a=Ve,c=Je(n.e/Ge)-Je(r.e/Ge),$=$/Ge|0),h=0;C[h]==(R[h]||0);h++);if(C[h]>(R[h]||0)&&c--,$<0)g.push(1),d=!0;else{for(w=R.length,x=C.length,h=0,$+=2,(u=We(a/(C[0]+1)))>1&&(C=e(C,u,a),R=e(R,u,a),x=C.length,w=R.length),b=x,v=(f=R.slice(0,x)).length;v=a/2&&k++;do{if(u=0,(l=t(C,f,x,v))<0){if(y=f[0],x!=v&&(y=y*a+(f[1]||0)),(u=We(y/k))>1)for(u>=a&&(u=a-1),_=(p=e(C,u,a)).length,v=f.length;1==t(p,f,_,v);)u--,i(p,x<_?S:C,_,a),_=p.length,l=1;else 0==u&&(l=u=1),_=(p=C.slice()).length;if(_=10;$/=10,h++);D(m,o+(m.e=h+c*Ge-1)+1,s,d)}else m.e=c,m.r=+d;return m}}(),a=/^(-?)0([xbo])(?=\w[\w.]*$)/i,l=/^([^.]+)\.$/,c=/^\.([^.]+)$/,h=/^-?(Infinity|NaN)$/,d=/^\s*\+(?=[\w.])|^\s+|\s+$/g,r=function(e,t,i,n){var r,o=i?t:t.replace(d,"");if(h.test(o))e.s=isNaN(o)?null:o<0?-1:1;else{if(!i&&(o=o.replace(a,function(e,t,i){return r="x"==(i=i.toLowerCase())?16:"b"==i?2:8,n&&n!=r?e:t}),n&&(r=n,o=o.replace(l,"$1").replace(c,"0.$1")),t!=o))return new M(o,r);if(M.DEBUG)throw Error(je+"Not a"+(n?" base "+n:"")+" number: "+t);e.s=null}e.c=e.e=null},u.absoluteValue=u.abs=function(){var e=new M(this);return e.s<0&&(e.s=1),e},u.comparedTo=function(e,t){return et(this,new M(e,t))},u.decimalPlaces=u.dp=function(e,t){var i,n,r,o=this;if(null!=e)return tt(e,0,Ze),null==t?t=m:tt(t,0,8),D(new M(o),e+o.e+1,t);if(!(i=o.c))return null;if(n=((r=i.length-1)-Je(this.e/Ge))*Ge,r=i[r])for(;r%10==0;r/=10,n--);return n<0&&(n=0),n},u.dividedBy=u.div=function(e,t){return i(this,new M(e,t),_,m)},u.dividedToIntegerBy=u.idiv=function(e,t){return i(this,new M(e,t),0,1)},u.exponentiatedBy=u.pow=function(e,t){var i,n,r,o,s,a,l,c,h=this;if((e=new M(e)).c&&!e.isInteger())throw Error(je+"Exponent not an integer: "+z(e));if(null!=t&&(t=new M(t)),s=e.e>14,!h.c||!h.c[0]||1==h.c[0]&&!h.e&&1==h.c.length||!e.c||!e.c[0])return c=new M(Math.pow(+z(h),s?e.s*(2-it(e)):+z(e))),t?c.mod(t):c;if(a=e.s<0,t){if(t.c?!t.c[0]:!t.s)return new M(NaN);(n=!a&&h.isInteger()&&t.isInteger())&&(h=h.mod(t))}else{if(e.e>9&&(h.e>0||h.e<-1||(0==h.e?h.c[0]>1||s&&h.c[1]>=24e7:h.c[0]<8e13||s&&h.c[0]<=9999975e7)))return o=h.s<0&&it(e)?-0:0,h.e>-1&&(o=1/o),new M(a?1/o:o);k&&(o=qe(k/Ge+2))}for(s?(i=new M(.5),a&&(e.s=1),l=it(e)):l=(r=Math.abs(+z(e)))%2,c=new M(p);;){if(l){if(!(c=c.times(h)).c)break;o?c.c.length>o&&(c.c.length=o):n&&(c=c.mod(t))}if(r){if(0===(r=We(r/2)))break;l=r%2}else if(D(e=e.times(i),e.e+1,1),e.e>14)l=it(e);else{if(0===(r=+z(e)))break;l=r%2}h=h.times(h),o?h.c&&h.c.length>o&&(h.c.length=o):n&&(h=h.mod(t))}return n?c:(a&&(c=p.div(c)),t?c.mod(t):o?D(c,k,m,void 0):c)},u.integerValue=function(e){var t=new M(this);return null==e?e=m:tt(e,0,8),D(t,t.e+1,e)},u.isEqualTo=u.eq=function(e,t){return 0===et(this,new M(e,t))},u.isFinite=function(){return!!this.c},u.isGreaterThan=u.gt=function(e,t){return et(this,new M(e,t))>0},u.isGreaterThanOrEqualTo=u.gte=function(e,t){return 1===(t=et(this,new M(e,t)))||0===t},u.isInteger=function(){return!!this.c&&Je(this.e/Ge)>this.c.length-2},u.isLessThan=u.lt=function(e,t){return et(this,new M(e,t))<0},u.isLessThanOrEqualTo=u.lte=function(e,t){return-1===(t=et(this,new M(e,t)))||0===t},u.isNaN=function(){return!this.s},u.isNegative=function(){return this.s<0},u.isPositive=function(){return this.s>0},u.isZero=function(){return!!this.c&&0==this.c[0]},u.minus=function(e,t){var i,n,r,o,s=this,a=s.s;if(t=(e=new M(e,t)).s,!a||!t)return new M(NaN);if(a!=t)return e.s=-t,s.plus(e);var l=s.e/Ge,c=e.e/Ge,h=s.c,d=e.c;if(!l||!c){if(!h||!d)return h?(e.s=-t,e):new M(d?s:NaN);if(!h[0]||!d[0])return d[0]?(e.s=-t,e):new M(h[0]?s:3==m?-0:0)}if(l=Je(l),c=Je(c),h=h.slice(),a=l-c){for((o=a<0)?(a=-a,r=h):(c=l,r=d),r.reverse(),t=a;t--;r.push(0));r.reverse()}else for(n=(o=(a=h.length)<(t=d.length))?a:t,a=t=0;t0)for(;t--;h[i++]=0);for(t=Ve-1;n>a;){if(h[--n]=0;){for(i=0,u=y[r]%g,p=y[r]/g|0,o=r+(s=l);o>r;)i=((c=u*(c=v[--s]%g)+(a=p*c+(h=v[s]/g|0)*u)%g*g+_[o]+i)/m|0)+(a/g|0)+p*h,_[o--]=c%m;_[o]=i}return i?++n:_.splice(0,1),T(e,_,n)},u.negated=function(){var e=new M(this);return e.s=-e.s||null,e},u.plus=function(e,t){var i,n=this,r=n.s;if(t=(e=new M(e,t)).s,!r||!t)return new M(NaN);if(r!=t)return e.s=-t,n.minus(e);var o=n.e/Ge,s=e.e/Ge,a=n.c,l=e.c;if(!o||!s){if(!a||!l)return new M(r/0);if(!a[0]||!l[0])return l[0]?e:new M(a[0]?n:0*r)}if(o=Je(o),s=Je(s),a=a.slice(),r=o-s){for(r>0?(s=o,i=l):(r=-r,i=a),i.reverse();r--;i.push(0));i.reverse()}for((r=a.length)-(t=l.length)<0&&(i=l,l=a,a=i,t=r),r=0;t;)r=(a[--t]=a[t]+l[t]+r)/Ve|0,a[t]=Ve===a[t]?0:a[t]%Ve;return r&&(a=[r].concat(a),++s),T(e,a,s)},u.precision=u.sd=function(e,t){var i,n,r,o=this;if(null!=e&&e!==!!e)return tt(e,1,Ze),null==t?t=m:tt(t,0,8),D(new M(o),e,t);if(!(i=o.c))return null;if(n=(r=i.length-1)*Ge+1,r=i[r]){for(;r%10==0;r/=10,n--);for(r=i[0];r>=10;r/=10,n++);}return e&&o.e+1>n&&(n=o.e+1),n},u.shiftedBy=function(e){return tt(e,-9007199254740991,Ke),this.times("1e"+e)},u.squareRoot=u.sqrt=function(){var e,t,n,r,o,s=this,a=s.c,l=s.s,c=s.e,h=_+4,d=new M("0.5");if(1!==l||!a||!a[0])return new M(!l||l<0&&(!a||a[0])?NaN:a?s:1/0);if(0==(l=Math.sqrt(+z(s)))||l==1/0?(((t=Qe(a)).length+c)%2==0&&(t+="0"),l=Math.sqrt(+t),c=Je((c+1)/2)-(c<0||c%2),n=new M(t=l==1/0?"5e"+c:(t=l.toExponential()).slice(0,t.indexOf("e")+1)+c)):n=new M(l+""),n.c[0])for((l=(c=n.e)+h)<3&&(l=0);;)if(o=n,n=d.times(o.plus(i(s,o,h,1))),Qe(o.c).slice(0,l)===(t=Qe(n.c)).slice(0,l)){if(n.e0&&_>0){for(o=_%a||a,h=p.substr(0,o);o<_;o+=a)h+=c+p.substr(o,a);l>0&&(h+=c+p.slice(o)),u&&(h="-"+h)}n=d?h+(i.decimalSeparator||"")+((l=+i.fractionGroupSize)?d.replace(new RegExp("\\d{"+l+"}\\B","g"),"$&"+(i.fractionGroupSeparator||"")):d):h}return(i.prefix||"")+n+(i.suffix||"")},u.toFraction=function(e){var t,n,r,o,s,a,l,c,h,d,u,_,g=this,f=g.c;if(null!=e&&(!(l=new M(e)).isInteger()&&(l.c||1!==l.s)||l.lt(p)))throw Error(je+"Argument "+(l.isInteger()?"out of range: ":"not an integer: ")+z(l));if(!f)return new M(g);for(t=new M(p),h=n=new M(p),r=c=new M(p),_=Qe(f),s=t.e=_.length-g.e-1,t.c[0]=Ye[(a=s%Ge)<0?Ge+a:a],e=!e||l.comparedTo(t)>0?s>0?t:h:l,a=y,y=1/0,l=new M(_),c.c[0]=0;d=i(l,t,0,1),1!=(o=n.plus(d.times(r))).comparedTo(e);)n=r,r=o,h=c.plus(d.times(o=h)),c=o,t=l.minus(d.times(o=t)),l=o;return o=i(e.minus(n),r,0,1),c=c.plus(o.times(h)),n=n.plus(o.times(r)),c.s=h.s=g.s,u=i(h,r,s*=2,m).minus(g).abs().comparedTo(i(c,n,s,m).minus(g).abs())<1?[h,r]:[c,n],y=a,u},u.toNumber=function(){return+z(this)},u.toPrecision=function(e,t){return null!=e&&tt(e,1,Ze),R(this,e,t,2)},u.toString=function(e){var t,i=this,r=i.s,o=i.e;return null===o?r?(t="Infinity",r<0&&(t="-"+t)):t="NaN":(null==e?t=o<=g||o>=f?nt(Qe(i.c),o):rt(Qe(i.c),o,"0"):10===e&&$?t=rt(Qe((i=D(new M(i),_+o+1,m)).c),i.e,"0"):(tt(e,2,S.length,"Base"),t=n(rt(Qe(i.c),o,"0"),10,e,r,!0)),r<0&&i.c[0]&&(t="-"+t)),t},u.valueOf=u.toJSON=function(){return z(this)},u._isBigNumber=!0,u[Symbol.toStringTag]="BigNumber",u[Symbol.for("nodejs.util.inspect.custom")]=u.valueOf,null!=t&&M.set(t),M}(),st=class{key;left=null;right=null;constructor(e){this.key=e}},at=class extends st{constructor(e){super(e)}},lt=class{size=0;modificationCount=0;splayCount=0;splay(e){const t=this.root;if(null==t)return this.compare(e,e),-1;let i=null,n=null,r=null,o=null,s=t;const a=this.compare;let l;for(;;)if(l=a(s.key,e),l>0){let t=s.left;if(null==t)break;if(l=a(t.key,e),l>0&&(s.left=t.right,t.right=s,s=t,t=s.left,null==t))break;null==i?n=s:i.left=s,i=s,s=t}else{if(!(l<0))break;{let t=s.right;if(null==t)break;if(l=a(t.key,e),l<0&&(s.right=t.left,t.left=s,s=t,t=s.right,null==t))break;null==r?o=s:r.right=s,r=s,s=t}}return null!=r&&(r.right=s.left,s.left=o),null!=i&&(i.left=s.right,s.right=n),this.root!==s&&(this.root=s,this.splayCount++),l}splayMin(e){let t=e,i=t.left;for(;null!=i;){const e=i;t.left=e.right,e.right=t,t=e,i=t.left}return t}splayMax(e){let t=e,i=t.right;for(;null!=i;){const e=i;t.right=e.left,e.left=t,t=e,i=t.right}return t}_delete(e){if(null==this.root)return null;if(0!=this.splay(e))return null;let t=this.root;const i=t,n=t.left;if(this.size--,null==n)this.root=t.right;else{const e=t.right;t=this.splayMax(n),t.right=e,this.root=t}return this.modificationCount++,i}addNewRoot(e,t){this.size++,this.modificationCount++;const i=this.root;null!=i?(t<0?(e.left=i,e.right=i.right,i.right=null):(e.right=i,e.left=i.left,i.left=null),this.root=e):this.root=e}_first(){const e=this.root;return null==e?null:(this.root=this.splayMin(e),this.root)}_last(){const e=this.root;return null==e?null:(this.root=this.splayMax(e),this.root)}clear(){this.root=null,this.size=0,this.modificationCount++}has(e){return this.validKey(e)&&0==this.splay(e)}defaultCompare(){return(e,t)=>et?1:0}wrap(){return{getRoot:()=>this.root,setRoot:e=>{this.root=e},getSize:()=>this.size,getModificationCount:()=>this.modificationCount,getSplayCount:()=>this.splayCount,setSplayCount:e=>{this.splayCount=e},splay:e=>this.splay(e),has:e=>this.has(e)}}},ct=class e extends lt{root=null;compare;validKey;constructor(e,t){super(),this.compare=e??this.defaultCompare(),this.validKey=t??(e=>null!=e&&null!=e)}delete(e){return!!this.validKey(e)&&null!=this._delete(e)}deleteAll(e){for(const t of e)this.delete(t)}forEach(e){const t=this[Symbol.iterator]();let i;for(;i=t.next(),!i.done;)e(i.value,i.value,this)}add(e){const t=this.splay(e);return 0!=t&&this.addNewRoot(new at(e),t),this}addAndReturn(e){const t=this.splay(e);return 0!=t&&this.addNewRoot(new at(e),t),this.root.key}addAll(e){for(const t of e)this.add(t)}isEmpty(){return null==this.root}isNotEmpty(){return null!=this.root}single(){if(0==this.size)throw"Bad state: No element";if(this.size>1)throw"Bad state: Too many element";return this.root.key}first(){if(0==this.size)throw"Bad state: No element";return this._first().key}last(){if(0==this.size)throw"Bad state: No element";return this._last().key}lastBefore(e){if(null==e)throw"Invalid arguments(s)";if(null==this.root)return null;if(this.splay(e)<0)return this.root.key;let t=this.root.left;if(null==t)return null;let i=t.right;for(;null!=i;)t=i,i=t.right;return t.key}firstAfter(e){if(null==e)throw"Invalid arguments(s)";if(null==this.root)return null;if(this.splay(e)>0)return this.root.key;let t=this.root.right;if(null==t)return null;let i=t.left;for(;null!=i;)t=i,i=t.left;return t.key}retainAll(t){const i=new e(this.compare,this.validKey),n=this.modificationCount;for(const e of t){if(n!=this.modificationCount)throw"Concurrent modification during iteration.";this.validKey(e)&&0==this.splay(e)&&i.add(this.root.key)}i.size!=this.size&&(this.root=i.root,this.size=i.size,this.modificationCount++)}lookup(e){if(!this.validKey(e))return null;return 0!=this.splay(e)?null:this.root.key}intersection(t){const i=new e(this.compare,this.validKey);for(const e of this)t.has(e)&&i.add(e);return i}difference(t){const i=new e(this.compare,this.validKey);for(const e of this)t.has(e)||i.add(e);return i}union(e){const t=this.clone();return t.addAll(e),t}clone(){const t=new e(this.compare,this.validKey);return t.size=this.size,t.root=this.copyNode(this.root),t}copyNode(e){if(null==e)return null;const t=new at(e.key);return function e(t,i){let n,r;do{if(n=t.left,r=t.right,null!=n){const t=new at(n.key);i.left=t,e(n,t)}if(null!=r){const e=new at(r.key);i.right=e,t=r,i=e}}while(null!=r)}(e,t),t}toSet(){return this.clone()}entries(){return new ut(this.wrap())}keys(){return this[Symbol.iterator]()}values(){return this[Symbol.iterator]()}[Symbol.iterator](){return new dt(this.wrap())}[Symbol.toStringTag]="[object Set]"},ht=class{tree;path=new Array;modificationCount=null;splayCount;constructor(e){this.tree=e,this.splayCount=e.getSplayCount()}[Symbol.iterator](){return this}next(){return this.moveNext()?{done:!1,value:this.current()}:{done:!0,value:null}}current(){if(!this.path.length)return null;const e=this.path[this.path.length-1];return this.getValue(e)}rebuildPath(e){this.path.splice(0,this.path.length),this.tree.splay(e),this.path.push(this.tree.getRoot()),this.splayCount=this.tree.getSplayCount()}findLeftMostDescendent(e){for(;null!=e;)this.path.push(e),e=e.left}moveNext(){if(this.modificationCount!=this.tree.getModificationCount()){if(null==this.modificationCount){this.modificationCount=this.tree.getModificationCount();let e=this.tree.getRoot();for(;null!=e;)this.path.push(e),e=e.left;return this.path.length>0}throw"Concurrent modification during iteration."}if(!this.path.length)return!1;this.splayCount!=this.tree.getSplayCount()&&this.rebuildPath(this.path[this.path.length-1].key);let e=this.path[this.path.length-1],t=e.right;if(null!=t){for(;null!=t;)this.path.push(t),t=t.left;return!0}for(this.path.pop();this.path.length&&this.path[this.path.length-1].right===e;)e=this.path.pop();return this.path.length>0}},dt=class extends ht{getValue(e){return e.key}},ut=class extends ht{getValue(e){return[e.key,e.key]}},pt=e=>()=>e,_t=e=>{const t=e?(t,i)=>i.minus(t).abs().isLessThanOrEqualTo(e):pt(!1);return(e,i)=>t(e,i)?0:e.comparedTo(i)};function mt(e){const t=e?(t,i,n,r,o)=>t.exponentiatedBy(2).isLessThanOrEqualTo(r.minus(i).exponentiatedBy(2).plus(o.minus(n).exponentiatedBy(2)).times(e)):pt(!1);return(e,i,n)=>{const r=e.x,o=e.y,s=n.x,a=n.y,l=o.minus(a).times(i.x.minus(s)).minus(r.minus(s).times(i.y.minus(a)));return t(l,r,o,s,a)?0:l.comparedTo(0)}}var gt=e=>e,ft=e=>{if(e){const t=new ct(_t(e)),i=new ct(_t(e)),n=(e,t)=>t.addAndReturn(e),r=e=>({x:n(e.x,t),y:n(e.y,i)});return r({x:new ot(0),y:new ot(0)}),r}return gt},vt=e=>({set:e=>{yt=vt(e)},reset:()=>vt(e),compare:_t(e),snap:ft(e),orient:mt(e)}),yt=vt(),bt=(e,t)=>e.ll.x.isLessThanOrEqualTo(t.x)&&t.x.isLessThanOrEqualTo(e.ur.x)&&e.ll.y.isLessThanOrEqualTo(t.y)&&t.y.isLessThanOrEqualTo(e.ur.y),wt=(e,t)=>{if(t.ur.x.isLessThan(e.ll.x)||e.ur.x.isLessThan(t.ll.x)||t.ur.y.isLessThan(e.ll.y)||e.ur.y.isLessThan(t.ll.y))return null;const i=e.ll.x.isLessThan(t.ll.x)?t.ll.x:e.ll.x,n=e.ur.x.isLessThan(t.ur.x)?e.ur.x:t.ur.x;return{ll:{x:i,y:e.ll.y.isLessThan(t.ll.y)?t.ll.y:e.ll.y},ur:{x:n,y:e.ur.y.isLessThan(t.ur.y)?e.ur.y:t.ur.y}}},kt=(e,t)=>e.x.times(t.y).minus(e.y.times(t.x)),xt=(e,t)=>e.x.times(t.x).plus(e.y.times(t.y)),St=e=>xt(e,e).sqrt(),$t=(e,t,i)=>{const n={x:t.x.minus(e.x),y:t.y.minus(e.y)},r={x:i.x.minus(e.x),y:i.y.minus(e.y)};return kt(r,n).div(St(r)).div(St(n))},Mt=(e,t,i)=>{const n={x:t.x.minus(e.x),y:t.y.minus(e.y)},r={x:i.x.minus(e.x),y:i.y.minus(e.y)};return xt(r,n).div(St(r)).div(St(n))},Rt=(e,t,i)=>t.y.isZero()?null:{x:e.x.plus(t.x.div(t.y).times(i.minus(e.y))),y:i},Ct=(e,t,i)=>t.x.isZero()?null:{x:i,y:e.y.plus(t.y.div(t.x).times(i.minus(e.x)))},Tt=class e{point;isLeft;segment;otherSE;consumedBy;static compare(t,i){const n=e.comparePoints(t.point,i.point);return 0!==n?n:(t.point!==i.point&&t.link(i),t.isLeft!==i.isLeft?t.isLeft?1:-1:Et.compare(t.segment,i.segment))}static comparePoints(e,t){return e.x.isLessThan(t.x)?-1:e.x.isGreaterThan(t.x)?1:e.y.isLessThan(t.y)?-1:e.y.isGreaterThan(t.y)?1:0}constructor(e,t){void 0===e.events?e.events=[this]:e.events.push(this),this.point=e,this.isLeft=t}link(e){if(e.point===this.point)throw new Error("Tried to link already linked events");const t=e.point.events;for(let e=0,i=t.length;e{const n=i.otherSE;t.set(i,{sine:$t(this.point,e.point,n.point),cosine:Mt(this.point,e.point,n.point)})};return(e,n)=>{t.has(e)||i(e),t.has(n)||i(n);const{sine:r,cosine:o}=t.get(e),{sine:s,cosine:a}=t.get(n);return r.isGreaterThanOrEqualTo(0)&&s.isGreaterThanOrEqualTo(0)?o.isLessThan(a)?1:o.isGreaterThan(a)?-1:0:r.isLessThan(0)&&s.isLessThan(0)?o.isLessThan(a)?-1:o.isGreaterThan(a)?1:0:s.isLessThan(r)?-1:s.isGreaterThan(r)?1:0}}},Dt=class e{events;poly;_isExteriorRing;_enclosingRing;static factory(t){const i=[];for(let n=0,r=t.length;n0&&(e=i)}let t=e.segment.prevInResult(),i=t?t.prevInResult():null;for(;;){if(!t)return null;if(!i)return t.ringOut;if(i.ringOut!==t.ringOut)return i.ringOut?.enclosingRing()!==t.ringOut?t.ringOut:t.ringOut?.enclosingRing();t=i.prevInResult(),i=t?t.prevInResult():null}}},zt=class{exteriorRing;interiorRings;constructor(e){this.exteriorRing=e,e.poly=this,this.interiorRings=[]}addInterior(e){this.interiorRings.push(e),e.poly=this}getGeom(){const e=this.exteriorRing.getGeom();if(null===e)return null;const t=[e];for(let e=0,i=this.interiorRings.length;e0?(this.tree.delete(t),i.push(e)):(this.segments.push(t),t.prev=n)}else{if(n&&r){const e=n.getIntersection(r);if(null!==e){if(!n.isAnEndpoint(e)){const t=this._splitSafely(n,e);for(let e=0,n=t.length;e0)return-1;const n=t.comparePoint(e.rightSE.point);return 0!==n?n:-1}if(i.isGreaterThan(n)){if(s.isLessThan(a)&&s.isLessThan(c))return-1;if(s.isGreaterThan(a)&&s.isGreaterThan(c))return 1;const i=t.comparePoint(e.leftSE.point);if(0!==i)return i;const n=e.comparePoint(t.rightSE.point);return n<0?1:n>0?-1:1}if(s.isLessThan(a))return-1;if(s.isGreaterThan(a))return 1;if(r.isLessThan(o)){const i=t.comparePoint(e.rightSE.point);if(0!==i)return i}if(r.isGreaterThan(o)){const i=e.comparePoint(t.rightSE.point);if(i<0)return 1;if(i>0)return-1}if(!r.eq(o)){const e=l.minus(s),t=r.minus(i),h=c.minus(a),d=o.minus(n);if(e.isGreaterThan(t)&&h.isLessThan(d))return 1;if(e.isLessThan(t)&&h.isGreaterThan(d))return-1}return r.isGreaterThan(o)?1:r.isLessThan(o)||l.isLessThan(c)?-1:l.isGreaterThan(c)?1:e.idt.id?1:0}constructor(e,t,i,n){this.id=++Ot,this.leftSE=e,e.segment=this,e.otherSE=t,this.rightSE=t,t.segment=this,t.otherSE=e,this.rings=i,this.windings=n}static fromRing(t,i,n){let r,o,s;const a=Tt.comparePoints(t,i);if(a<0)r=t,o=i,s=1;else{if(!(a>0))throw new Error(`Tried to create degenerate segment at [${t.x}, ${t.y}]`);r=i,o=t,s=-1}const l=new Tt(r,!0),c=new Tt(o,!1);return new e(l,c,[n],[s])}replaceRightSE(e){this.rightSE=e,this.rightSE.segment=this,this.rightSE.otherSE=this.leftSE,this.leftSE.otherSE=this.rightSE}bbox(){const e=this.leftSE.point.y,t=this.rightSE.point.y;return{ll:{x:this.leftSE.point.x,y:e.isLessThan(t)?e:t},ur:{x:this.rightSE.point.x,y:e.isGreaterThan(t)?e:t}}}vector(){return{x:this.rightSE.point.x.minus(this.leftSE.point.x),y:this.rightSE.point.y.minus(this.leftSE.point.y)}}isAnEndpoint(e){return e.x.eq(this.leftSE.point.x)&&e.y.eq(this.leftSE.point.y)||e.x.eq(this.rightSE.point.x)&&e.y.eq(this.rightSE.point.y)}comparePoint(e){return yt.orient(this.leftSE.point,e,this.rightSE.point)}getIntersection(e){const t=this.bbox(),i=e.bbox(),n=wt(t,i);if(null===n)return null;const r=this.leftSE.point,o=this.rightSE.point,s=e.leftSE.point,a=e.rightSE.point,l=bt(t,s)&&0===this.comparePoint(s),c=bt(i,r)&&0===e.comparePoint(r),h=bt(t,a)&&0===this.comparePoint(a),d=bt(i,o)&&0===e.comparePoint(o);if(c&&l)return d&&!h?o:!d&&h?a:null;if(c)return h&&r.x.eq(a.x)&&r.y.eq(a.y)?null:r;if(l)return d&&o.x.eq(s.x)&&o.y.eq(s.y)?null:s;if(d&&h)return null;if(d)return o;if(h)return a;const u=((e,t,i,n)=>{if(t.x.isZero())return Ct(i,n,e.x);if(n.x.isZero())return Ct(e,t,i.x);if(t.y.isZero())return Rt(i,n,e.y);if(n.y.isZero())return Rt(e,t,i.y);const r=kt(t,n);if(r.isZero())return null;const o={x:i.x.minus(e.x),y:i.y.minus(e.y)},s=kt(o,t).div(r),a=kt(o,n).div(r),l=e.x.plus(a.times(t.x)),c=i.x.plus(s.times(n.x)),h=e.y.plus(a.times(t.y)),d=i.y.plus(s.times(n.y));return{x:l.plus(c).div(2),y:h.plus(d).div(2)}})(r,this.vector(),s,e.vector());return null===u?null:bt(n,u)?yt.snap(u):null}split(t){const i=[],n=void 0!==t.events,r=new Tt(t,!0),o=new Tt(t,!1),s=this.rightSE;this.replaceRightSE(o),i.push(o),i.push(r);const a=new e(r,s,this.rings.slice(),this.windings.slice());return Tt.comparePoints(a.leftSE.point,a.rightSE.point)>0&&a.swapEvents(),Tt.comparePoints(this.leftSE.point,this.rightSE.point)>0&&this.swapEvents(),n&&(r.checkForConsuming(),o.checkForConsuming()),i}swapEvents(){const e=this.rightSE;this.rightSE=this.leftSE,this.leftSE=e,this.leftSE.isLeft=!0,this.rightSE.isLeft=!1;for(let e=0,t=this.windings.length;e0){const e=i;i=n,n=e}if(i.prev===n){const e=i;i=n,n=e}for(let e=0,t=n.rings.length;e1===e.length&&e[0].isSubject;this._isInResult=i(e)!==i(t);break}}return this._isInResult}},Ht=class{poly;isExterior;segments;bbox;constructor(e,t,i){if(!Array.isArray(e)||0===e.length)throw new Error("Input geometry is not a valid Polygon or MultiPolygon");if(this.poly=t,this.isExterior=i,this.segments=[],"number"!=typeof e[0][0]||"number"!=typeof e[0][1])throw new Error("Input geometry is not a valid Polygon or MultiPolygon");const n=yt.snap({x:new ot(e[0][0]),y:new ot(e[0][1])});this.bbox={ll:{x:n.x,y:n.y},ur:{x:n.x,y:n.y}};let r=n;for(let t=1,i=e.length;tIt.run("union",e,t),qt=(e,...t)=>It.run("intersection",e,t),Wt=(e,...t)=>It.run("difference",e,t);yt.set;const jt=/^#[0-9a-fA-F]{6}$/;function Ut(e,t){return"string"==typeof e&&jt.test(e)?e:t}const Vt="(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])",Gt=new RegExp(`^rgb\\(${Vt}, ${Vt}, ${Vt}\\)$`);function Kt(e){if(!Array.isArray(e)||e.length<3)return null;const t=e.slice(0,3);if(!t.every(e=>"number"==typeof e&&Number.isFinite(e)))return null;const[i,n,r]=t.map(e=>Math.round(Math.min(255,Math.max(0,e))));return`rgb(${i}, ${n}, ${r})`}function Yt(e){const t=Math.max(0,Math.min(120,(e-40)/140*120));return`hsl(${Math.round(t)}, 85%, 55%)`}function Xt(e,t){if(!(Number.isFinite(e)&&t>0))return e;const i=Math.round(e/t)*t;return Math.abs(i-e)<=1e-9*t?e:i}function Zt(e,t,i,n=1/0){if(!(i>0&&e?.every(Number.isFinite)&&t?.every(Number.isFinite)))return[t[0],t[1]];const r=t[0]-e[0],o=t[1]-e[1];if(Math.abs(r)+Math.abs(o)<=1e-12)return[e[0],e[1]];const s=Math.PI/4;let a=Math.atan2(o,r);a<0&&(a+=2*Math.PI);const l=Math.floor(a/s+.5)%8,[c,h]=[[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]][l],d=c*c+h*h;let u=Math.max(0,Math.round((r*c+o*h)/(i*d)));if(Number.isFinite(n)&&n>=0){const t=(e,t)=>{if(!t)return 1/0;const r=t>0?n-e:e+n;return Math.max(0,Math.floor((r+1e-9*i)/i))};u=Math.min(u,t(e[0],c),t(e[1],h))}return[e[0]+c*u*i,e[1]+h*u*i]}function Jt(e,t){if(t){const t=e/2.54;let i=Math.floor(t/12),n=Math.round(t-12*i);return 12===n&&(i+=1,n=0),`${i}′ ${n}″`}return`${(e/100).toFixed(2)} m`}function Qt(e,t,i=1){const n=e[0].toFixed(i),r=e[1].toFixed(i),o=t[0].toFixed(i),s=t[1].toFixed(i),a=n=3?e.poly:e&&null!=e.x&&null!=e.y&&null!=e.w&&null!=e.h?[[e.x,e.y],[e.x+e.w,e.y],[e.x+e.w,e.y+e.h],[e.x,e.y+e.h]]:null}function ti(e){const t=[];for(const i of e||[])i?.poly?.length>=3?t.push({poly:i.poly.map(e=>e.join(",")).join(" ")}):i&&null!=i.x&&null!=i.y&&null!=i.w&&null!=i.h&&t.push({rect:{x:i.x,y:i.y,w:i.w,h:i.h,rx:.03*Math.min(i.w,i.h)}});return t}function ii(e){const t=[],i=new Set;for(const n of e||[]){const e=ei(n);if(e)for(let n=0;n=90?e-=180:e<-90&&(e+=180),n.step&&n.step>0){const i=Math.sqrt(d),o=Math.min(Math.max(n.length||0,0)/2,i/2);let a=Math.round(u*i/n.step)*n.step;Math.abs(u*i-i/2)<=n.step/2&&(a=i/2),a=Math.max(o,Math.min(i-o,a));const l=a/i;r={x:t+l*c,y:s+l*h,angle:e}}else r={x:p[0],y:p[1],angle:e}}}return r}function ri(e,t,i){let n=null,r=1/0;for(let o=0;o=r)continue;r=_;const m=Math.sqrt(u),g=(i>0?Math.max(0,Math.min(m,Math.round(p*m/i)*i)):p*m)/m;n=[s+g*h,a+g*d]}return n}function oi(e,t,i,n,r,o=1){const s=t*Math.PI/180,a=[Math.cos(s),Math.sin(s)];let l=null,c=o;for(const t of ii(n)){const i=[[t[0],t[1]],[t[2],t[3]]],n=t=>Math.abs(a[0]*(t[1]-e[1])-a[1]*(t[0]-e[0]));if(n(i[0])>o||n(i[1])>o)continue;const r=(i[0][0]-e[0])*a[0]+(i[0][1]-e[1])*a[1],s=(i[1][0]-e[0])*a[0]+(i[1][1]-e[1])*a[1],h=Math.min(r,s),d=Math.max(r,s),u=h>0?h:d<0?-d:0;u[e[0]+a[0]*t,e[1]+a[1]*t],g=(h+d)/2;return{wallA:m(h),wallB:m(d),sideA:p,sideB:_,midA:m((h-u)/2),midB:m((u+d)/2),wallCenter:m(g),centered:Math.abs(g)<=r}}function si(e,t,i=!1,n){if("passage"===e)return 1;if(null==t||"unavailable"===t||"unknown"===t)return"window"===e?0:1;const r="string"==typeof n?n.trim()?Number(n):NaN:Number(n),o=null!=n&&Number.isFinite(r)?Math.max(0,Math.min(1,r/100)):function(e){return["on","open","home","detected","playing","cleaning"].includes(String(e))}(t)?1:0;return i?1-o:o}function ai(e){const t=Number.isFinite(e)?Math.max(0,Math.min(1,e)):0;return Math.min(1,Math.max(0,.05*Math.round(t/.05)))}function li(e,t){return(Number.isFinite(e)&&e>0?e:0)*(Number.isFinite(t)?Math.max(0,Math.min(1,t)):0)}function ci(e){return"passage"===e.type?[]:[e.contact,e.lock].filter(e=>"string"==typeof e&&e.length>0)}function hi(e,t,i=200){const n=t.trim().toLowerCase();return(n?e.filter(e=>e.label.toLowerCase().includes(n)||e.value.toLowerCase().includes(n)):e).slice(0,Math.max(0,i))}function di(e,t,i=.001){return Math.abs(e[0]-t[0])e[1]!=l>e[1]&&e[0]<(a-o)*(e[1]-s)/(l-s)+o&&(i=!i)}return i}function pi(e,t,i){const n=i[0]-t[0],r=i[1]-t[1],o=n*n+r*r;let s=o?((e[0]-t[0])*n+(e[1]-t[1])*r)/o:0;return s=Math.max(0,Math.min(1,s)),Math.hypot(e[0]-(t[0]+s*n),e[1]-(t[1]+s*r))}function _i(e,t){if(!t||t.length<2)return null;let i=null,n=1/0;for(let r=0;rr&&s<-r||o<-r&&s>r)&&(a>r&&l<-r||a<-r&&l>r)}function yi(e,t=24){const i=e.map(e=>e[0]),n=e.map(e=>e[1]),r=Math.min(...i),o=Math.max(...i),s=Math.min(...n),a=Math.max(...n),l=Math.max(o-r,a-s)||1;let c=0,h=0,d=0;for(let t=0;t1e-9?[h/(3*c),d/(3*c)]:[(r+o)/2,(s+a)/2],p=(t,i)=>{const n=((t,i)=>{if(!ui([t,i],e))return-1/0;let n=1/0;for(let r=0;rm&&(m=c,_=[n,l])}if(_){const[e,i]=_,n=(o-r)/t,l=(a-s)/t;for(let t=-4;t<=4;t++)for(let r=-4;r<=4;r++){const o=e+n*t/4,s=i+l*r/4,a=p(o,s);a>m&&(m=a,_=[o,s])}}return _||bi(e)||e[0]}function bi(e,t=1e-6){if(!e||e.length<3)return null;const i=e.length,n=[e.reduce((e,t)=>e+t[0],0)/i,e.reduce((e,t)=>e+t[1],0)/i];if(gi(n,e,t))return n;for(let n=0;nki(e,t,i));return n.filter(e=>!n.some(t=>t!==e&&ki(t,e,i)))}function $i(e){if(!e||e.length<3)return 0;let t=0;for(let i=0;i[e[0],e[1]]),[e[0][0],e[0][1]]]]}function Ri(e,t){if(!e||!t||e.length<3||t.length<3)return null;const i=Bt(Mi(e),Mi(t));if(1!==i.length)return null;if(1!==i[0].length)return null;const n=i[0][0].slice(0,-1).map(e=>[e[0],e[1]]);return n.length>=3?n:null}function Ci(e,t,i){for(let n=0;n1&&di(i[0],i[i.length-1],t)&&i.pop(),i}function Di(e,t,i=1e-6){if(!e||e.length<3||!t||t.length<2)return null;const n=t[0],r=t[t.length-1];if(di(n,r,i))return null;const o=Ci(e,n,i),s=Ci(e,r,i);if(o<0||s<0)return null;const a=t.slice(1,-1);for(const t of a)if(!gi(t,e,i))return null;for(let i=0;i{const s=[t];let a=(n+1)%e.length;for(let t=0;t<=e.length&&(s.push(e[a]),a!==o);t++)a=(a+1)%e.length;return s.push(r),Ti(s,i)};let c,h;if(o===s){const s=Ti([...t],i);if(s.length<3||$i(s)<=i)return null;const a=[];for(let i=0;i=0?t:[...t].reverse();for(const e of i)a.push(e)}c=Ti(a,i),h=s}else c=Ti([...l(n,o,r,s),...[...a].reverse()],i),h=Ti([...l(r,s,n,o),...a],i);return c.length<3||h.length<3||$i(c)<=i||$i(h)<=i||Math.abs($i(c)+$i(h)-$i(e))>Math.max(i,1e-6*$i(e))?null:[c,h]}function zi(e,t,i){const[n,r]=e.split(":");return"device"===n?r:"entity"===n?"lg_"+r:t&&t.startsWith("v_")?t:i()}function Ai(e){return e.length?Math.round(e.reduce((e,t)=>e+t,0)/e.length):null}function Pi(e,t){if(t>e[2]/e[3]){const i=e[3],n=e[3]*t;return{x:e[0]-(n-e[2])/2,y:e[1],w:n,h:i}}const i=e[2],n=e[2]/t;return{x:e[0],y:e[1]-(n-e[3])/2,w:i,h:n}}function Fi(e,t,i,n){if(e.length<2)return;const r=t.x+n,o=t.x+t.w-n,s=t.y+n,a=t.y+t.h-n;for(let t=0;t<60;t++){let t=!1;for(let n=0;n=0)i=t.slice(0,r).trim(),n=t.slice(r+1).trim();else{const e=t.split(".");e.length>2&&(i=e.slice(0,2).join("."),n=e.slice(2).join("."))}return/^[a-z0-9_]+\.[a-z0-9_]+$/.test(i)?r>=0&&!n||n&&!/^[a-zA-Z0-9_.-]+$/.test(n)?null:n?{entity:i,attr:n}:{entity:i}:null}function Vi(e,t){const i=String(e??"").trim(),n=String(t??"").trim(),r=Ui(n?`${i}:${n}`:i);return r?`{${r.entity}${r.attr?`:${r.attr}`:""}}`:""}function Gi(e,t,i){const n=String(t??"").trim();if(!n)return null;const r=e?.states?.[n];if(!r)return null;const o=String(i??"").trim(),s=e=>e.slice(0,60);if(o){const t=function(e){if(null==e)return null;if(Array.isArray(e)){const t=e.map(e=>null==e?"":String(e)).join(", ");return t?t.slice(0,60):null}if("object"==typeof e)return null;const t=String(e);return""===t?null:t.slice(0,60)}(r.attributes?.[o]);if(null===t)return null;const i=e?.formatEntityAttributeValue;if("function"==typeof i)try{const t=i.call(e,r,o);if("string"==typeof t&&""!==t)return{text:s(t),formatted:!0}}catch{}return{text:t,formatted:!1}}const a=r.state;if(null==a||""===a)return null;const l=e?.formatEntityState;if("function"==typeof l)try{const t=l.call(e,r);if("string"==typeof t&&""!==t)return{text:s(t),formatted:!0}}catch{}return{text:s(String(a)),formatted:!1}}function Ki(e,t,i){const n=String(t??"").trim(),r=String(i??"").trim()||n;if(!r)return e.text;const o=e.formatted&&n?function(e,t){if(!t)return e;const i=e.replace(/\s+$/,"");return i.endsWith(t)?i.slice(0,i.length-t.length).replace(/\s+$/,""):e}(e.text,n):e.text;return`${o} ${r}`}function Yi(e,t){const i=(t?.entity||"").trim();if(!i)return"";const n=e?.states?.[i],r=n?.state;if(!n||null==r||""===r||"unavailable"===r||"unknown"===r)return Wi;const o=(t?.attr||"").trim(),s=Gi(e,i,o||null);if(null===s)return Wi;return Ki(s,o?"":String(n.attributes?.unit_of_measurement??"").trim(),t?.unit)}function Xi(e,t,i,n=()=>!0){const r=e??"";let o=!1;const s=r.replace(/\{([^{}\r\n]+)\}/g,(e,t)=>{const r=Ui(t);return r?(o=!0,n(r.entity||"")?Yi(i,r):Wi):e});if(o)return s;const a=(t?.entity||"").trim();if(!a)return r;if(!n(a)){const e=r.indexOf(ji);return e>=0?r.slice(0,e)+Wi+r.slice(e+2):r?`${r} ${Wi}`:Wi}const l=Yi(i,t),c=r.indexOf(ji);return c>=0?r.slice(0,c)+l+r.slice(c+2):r?`${r} ${l}`:l}const Zi=20;function Ji(e){const t=Number(e?.scale);if(Number.isFinite(t)&&t>0)return Math.min(20,Math.max(.15,t));return{s:.7,m:1,l:1.5}[String(e?.size??"")]??1}function Qi(e,t){if(!t)return e;let i=e;for(const[e,n]of Object.entries(t))i=i.split("{"+e+"}").join(String(n));return i}const en="#55606c",tn=.55,nn=20,rn=25,on={c:"#607d8b",a:.18};function sn(e,t=on){const i=e&&"object"==typeof e?e:null,n=i?.a;return{c:Ut(i?.c,t.c),a:"number"==typeof n&&Number.isFinite(n)?Math.min(1,Math.max(0,n)):t.a}}function an(e,t){const i=sn(e),n=t?.settings?.custom_fill;return n&&"object"==typeof n?sn(n,i):i}function ln(e){const t=e?.settings||{},i=!e?.plan_url,n="glow"===t.fill_mode;return{showBorders:t.show_borders??i,showNames:t.show_names??i,color:Ut(t.room_color,en),opacity:"number"==typeof t.room_opacity?Math.min(1,Math.max(0,t.room_opacity)):.55,fill:["lqi","light","temp","custom"].includes(t.fill_mode)?t.fill_mode:"none",customFill:sn(t.custom_fill),glow:"boolean"==typeof t.glow_enabled?t.glow_enabled:n,tempMin:"number"==typeof t.temp_min?t.temp_min:20,tempMax:"number"==typeof t.temp_max?t.temp_max:25,showLqi:"boolean"==typeof t.show_lqi?t.show_lqi:null,cardFontScale:"number"==typeof t.card_font_scale&&t.card_font_scale>0?Math.min(3,Math.max(.5,t.card_font_scale)):1,labelTemp:!0===t.label_temp,labelHum:!0===t.label_hum,labelLqi:!0===t.label_lqi,labelLight:!0===t.label_light,bgColor:Ut(t.bg_color,null),hideDecor:!0===t.hide_decor,hideOpenings:!0===t.hide_openings}}function cn(e,t){if(t.bgColor)return t.bgColor;const i=e?.bg_color;return Ut(i,"")}function hn(e){return!1!==e?.show_room_tooltip}const dn={light_on:{c:"#ffd45c",a:.18},light_off:{c:"#9aa0a6",a:.14},light_none:{c:"#6b7480",a:0},temp_cold:{c:"#4fc3f7",a:.18},temp_ok:{c:"#66d17a",a:.18},temp_hot:{c:"#ffd45c",a:.18},lqi_low:{c:"#f25a4a",a:.18},lqi_high:{c:"#4bd28f",a:.18},glow_base:{c:"#0d1b2a",a:.5},glow_light:{c:"#ffd9a0",a:.85},wall_fill:{c:"#ffffff",a:1}};function un(e){const t={},i=e?.fill_colors||{};for(const e of Object.keys(dn)){const n=dn[e],r=i[e];t[e]={c:Ut(r?.c,n.c),a:r&&"number"==typeof r.a?Math.min(1,Math.max(0,r.a)):n.a}}return t}function pn(e,t,i){const n=Math.min(1,Math.max(0,i)),r=[1,3,5].map(t=>parseInt(e.slice(t,t+2),16)),o=[1,3,5].map(e=>parseInt(t.slice(e,e+2),16)),s=r.map((e,t)=>Math.round(e+(o[t]-e)*n));return"#"+s.map(e=>e.toString(16).padStart(2,"0")).join("")}function _n(e,t,i,n,r,o,s,a=on){const l=function(e,t,i,n,r,o,s,a=on){if("custom"===e)return sn(a);if("lqi"===e){if(null==t)return null;const e=(t-40)/140;return{c:pn(s.lqi_low.c,s.lqi_high.c,e),a:s.lqi_low.a+(s.lqi_high.a-s.lqi_low.a)*Math.min(1,Math.max(0,e))}}if("light"===e)return"none"===i?s.light_none.a>0?s.light_none:null:"on"===i?s.light_on:s.light_off;if("temp"===e){if(null==n)return null;const e=Math.min(r,o),t=Math.max(r,o);return nt?s.temp_hot:s.temp_ok}return null}(e,t,i,n,r,o,s,a);return l?{color:l.c,opacity:l.a,mode:e}:null}const mn={blind:["mdi:blinds","mdi:blinds-open"],shade:["mdi:blinds","mdi:blinds-open"],shutter:["mdi:window-shutter","mdi:window-shutter-open"],curtain:["mdi:curtains-closed","mdi:curtains"],window:["mdi:window-closed","mdi:window-open"],awning:["mdi:awning-outline","mdi:awning"],door:["mdi:door-closed","mdi:door-open"],garage:["mdi:garage","mdi:garage-open"],gate:["mdi:gate","mdi:gate-open"],damper:["mdi:circle-slice-8","mdi:circle-outline"]},gn=[["mdi:roller-shade-closed","mdi:roller-shade"],["mdi:blinds-horizontal-closed","mdi:blinds-horizontal"],["mdi:garage-variant","mdi:garage-open-variant"],["mdi:door","mdi:door-open"]];function fn(e){for(const t of[...Object.values(mn),...gn])if(e===t[0]||e===t[1])return t;return null}function vn(e,t,i,n,r){if(!n||"unavailable"===n||"unknown"===n)return e;if(r){const i="cover"===t?fn(e):null;return i?"closed"===n?i[0]:i[1]:e}if("binary_sensor"===t){if("door"===i)return"on"===n?"mdi:door-open":"mdi:door-closed";if("window"===i)return"on"===n?"mdi:window-open":"mdi:window-closed";if("garage_door"===i)return"on"===n?"mdi:garage-open-variant":"mdi:garage-variant"}if("cover"===t){const t=mn[String(i||"")];if(t)return"closed"===n?t[0]:t[1];const r=fn(e);return r?"closed"===n?r[0]:r[1]:e}return"lock"===t?"locked"===n?"mdi:lock":"mdi:lock-open-variant":"light"===t&&"mdi:lightbulb"===e&&"on"===n?"mdi:lightbulb-on":e}function yn(e){const t=Math.min(4e4,Math.max(1e3,e))/100,i=t<=66?255:329.698727446*Math.pow(t-60,-.1332047592),n=t<=66?99.4708025861*Math.log(t)-161.1195681661:288.1221695283*Math.pow(t-60,-.0755148492),r=t>=66?255:t<=19?0:138.5177312231*Math.log(t-10)-305.0447927307,o=e=>Math.round(Math.min(255,Math.max(0,e)));return[o(i),o(n),o(r)]}const bn=1/2.2;function wn(e){const t=/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/.exec(e);return t?"#"+t.slice(1).map(e=>Math.min(255,Number(e)).toString(16).padStart(2,"0")).join(""):null}function kn(e){if(!e||"object"!=typeof e||Array.isArray(e))return null;const t=e;if(Object.keys(t).some(e=>"c"!==e&&"bri"!==e))return null;const i=Ut(t.c,null);return i?void 0===t.bri||null===t.bri?{c:i}:"number"!=typeof t.bri||!Number.isFinite(t.bri)||t.bri<.01||t.bri>1?null:{c:i,bri:t.bri}:null}function xn(e,t,i){const n=kn(t),r=e?.attributes||{},o=n?.bri??function(e){const t=e?.attributes?.brightness,i="number"==typeof t?t:"string"==typeof t&&""!==t.trim()?Number(t):Number.NaN;return Number.isFinite(i)?Math.max(0,Math.min(1,i/255)):1}(e);if(n)return{c:n.c,bri:o};const s=Kt(r.rgb_color);if(s)return{c:wn(s)||Ut(i,"#ffd9a0"),bri:o};const a=Number(r.color_temp_kelvin)||(Number(r.color_temp)>0?1e6/Number(r.color_temp):NaN);return Number.isFinite(a)&&a>0?{c:(l=yn(a),"#"+l.slice(0,3).map(e=>Math.min(255,Math.max(0,Math.round(Number(e)||0))).toString(16).padStart(2,"0")).join("")),bri:o}:{c:Ut(i,"#ffd9a0"),bri:o};var l}function Sn(e,t,i){return"on"===e?.state?xn(e,t,i):null}function $n(e,t=1){const i=Math.max(0,Math.min(1,Number.isFinite(e)?e:1)),n=.7*Math.max(0,Math.min(1,Number.isFinite(t)?t:1))*(.4+.6*Math.pow(i,bn));return Math.max(0,Math.min(1,n))}function Mn(e){return e.startsWith("light.")||e.startsWith("switch.")}function Rn(e,t,i=1e-6){const n=[];if(!e||!t||e.length<3||t.length<3)return n;for(let r=0;ru||l>u)continue;const p=(r[0]-o[0])*h+(r[1]-o[1])*d,_=(s[0]-o[0])*h+(s[1]-o[1])*d,m=Math.max(0,Math.min(p,_)),g=Math.min(c,Math.max(p,_));g-m>i&&n.push([o[0]+h*m,o[1]+d*m,o[0]+h*g,o[1]+d*g])}}return n}function Cn(e,t,i=1e-6){const n=[];for(const r of e){const e=[r[0],r[1]],o=[r[2],r[3]],s=o[0]-e[0],a=o[1]-e[1],l=Math.hypot(s,a);if(lo||r>o)continue;const s=(n[0]-e[0])*c+(n[1]-e[1])*h,a=(n[2]-e[0])*c+(n[3]-e[1])*h,u=Math.max(0,Math.min(s,a)),p=Math.min(l,Math.max(s,a));p-u>i&&d.push([u,p])}if(!d.length){n.push([e[0],e[1],o[0],o[1]]);continue}d.sort((e,t)=>e[0]-t[0]);let u=0;for(const[t,r]of d)t-u>i&&n.push([e[0]+c*u,e[1]+h*u,e[0]+c*t,e[1]+h*t]),u=Math.max(u,r);l-u>i&&n.push([e[0]+c*u,e[1]+h*u,o[0],o[1]])}return n}function Tn(e,t,i=1e-6){const n=[];for(let t=0;t{if("string"!=typeof e||!e)return;const i=Pn(e);i.startsWith("/api/houseplan/content/")&&t.add(i)};for(const t of e?.spaces||[]){i(t?.plan_url);for(const e of t?.markers||[])for(const t of e?.pdfs||[])i(t?.url)}for(const t of e?.markers||[])for(const e of t?.pdfs||[])i(e?.url);return t}function Pn(e){return e?e.startsWith("/houseplan_files/plans/")?"/api/houseplan/content/plans/_/"+e.slice(23):e.startsWith("/houseplan_files/files/")?"/api/houseplan/content/files/"+e.slice(23):e:""}function Fn(e,t){const i=t?.settings?.fill_mode;return"none"===i||"lqi"===i||"light"===i||"temp"===i||"custom"===i?i:e}function In(e,t){const i=t?.settings;return"boolean"==typeof i?.glow?i.glow:"glow"===i?.fill_mode||e}function On(e,t,i,n){if(!t||!i||t===i)return e;const r="/files/"+t+"/",o="/files/"+i+"/";return e.map(e=>{if(!e.url.includes(r))return e;const t=e.url.split(r)[1]||"",[i,s]=[t.split("?")[0],t.includes("?")?"?"+t.split("?")[1]:""];if(n){const t=n[decodeURIComponent(i)]??n[i];return t?{...e,url:e.url.split(r+i)[0]+o+encodeURIComponent(t)+s}:e}return{...e,url:e.url.split(r).join(o)}})}function En(e,t=1){const i=Number(e);return Number.isFinite(i)&&i>0?Math.min(3,Math.max(.5,i)):t}function Hn(e,t,i){let n=null,r=null;for(const o of t){if(!(Math.abs(o[0]-e[0])<1e-6&&Math.abs(o[1]-e[1])<1e-6)){if(Math.abs(o[0]-e[0])<=i){const t=Math.abs(o[1]-e[1]);t>1e-6&&(!n||t1e-6&&(!r||t"number"==typeof e&&Number.isFinite(e),Zn=(e,t,i)=>Math.min(i,Math.max(t,e));function Jn(e){return e.elevation<=-6?"night":e.elevation>=6?"day":e.rising?"dawn":"dusk"}function Qn(e){const t=(Math.floor(Number(e)||0)%1440+1440)%1440;return t>=300&&t<480?"dawn":t>=480&&t<1080?"day":t>=1080&&t<1260?"dusk":"night"}function er(e){const t=Jn(e),i=e.azimuth*Math.PI/180;return{sunX:50-42*Math.sin(i),sunY:78-Zn(e.elevation,0,90)/90*64,sunOpacity:"night"===t?0:Zn((e.elevation+6)/12,0,1)}}function tr(e){const t=(Math.floor(Number(e)||0)%1440+1440)%1440;if(t<300||t>=1260)return{sunX:50,sunY:78,sunOpacity:0};const i=(t-300)/960,n=(t-300)/120,r=(1260-t)/120;return{sunX:8+84*i,sunY:78-64*Math.sin(i*Math.PI),sunOpacity:Math.max(.18,Math.min(n,r,1))}}function ir(e,t=new Date){const i=function(e){const t=e?.states?.["sun.sun"]?.attributes;return t&&Xn(t.azimuth)&&Xn(t.elevation)&&"boolean"==typeof t.rising?{azimuth:Gn(t.azimuth),elevation:t.elevation,rising:t.rising}:null}(e);if(i)return{phase:Jn(i),source:"sun",...er(i)};const n="number"==typeof t?t:function(e=new Date){return 60*e.getHours()+e.getMinutes()}(t);return{phase:Qn(n),source:"clock",...tr(n)}}function nr(e){return`${e.source}|${e.phase}|${e.sunX.toFixed(2)}|${e.sunY.toFixed(2)}|`+e.sunOpacity.toFixed(3)}const rr=[[-90,"#070c14"],[-12,"#070c14"],[-4,"#131a28"],[0,"#4a3527"],[10,"#e8ddcf"],[30,"#ffffff"],[90,"#ffffff"]],or=e=>Math.min(1,Math.max(0,e));function sr(e,t,i=6){const n=e.angle*Math.PI/180,r=[Math.sin(n),-Math.cos(n)],o=n=>{const o=[e.x+r[0]*i*n,e.y+r[1]*i*n];return t.find(e=>e.poly.length>=3&&ui(o,e.poly))||null},s=o(1),a=o(-1);return s&&a?null:s||a?s?{normal:[-r[0],-r[1]],roomId:s.id}:{normal:r,roomId:a.id}:null}function ar(e,t,i){return i>0&&e[0]*t[0]+e[1]*t[1]>.05}function lr(e,t,i,n){return[[e[0],e[1]],[t[0],t[1]],[t[0]+i[0]*n,t[1]+i[1]*n],[e[0]+i[0]*n,e[1]+i[1]*n]]}function cr(e,t){try{const i=qt([[...e.map(e=>[e[0],e[1]]),[e[0][0],e[0][1]]]],[[...t.map(e=>[e[0],e[1]]),[t[0][0],t[0][1]]]]),n=[];for(const e of i){const t=e?.[0];!Array.isArray(t)||t.length<4||n.push(t.slice(0,t.length-1).map(e=>[e[0],e[1]]))}return n}catch{return[]}}function hr(e,t,i,n,r,o,s){if(!(n>0))return[];const a=Kn(i,r),l=[-a[0],-a[1]],c=function(e){const t=Math.min(90,Math.max(0,e));return.7*(.8+1.7*Math.pow(1-t/90,1.6))}(n),h=[];for(const i of t){if(!(i.length>0))continue;const t=sr(i,e);if(!t||!ar(t.normal,a,n))continue;const r=e.find(e=>e.id===t.roomId);if(!r)continue;const d=o&&o[t.roomId]||r.poly,u=i.angle*Math.PI/180,p=i.length/2,_=[-t.normal[0],-t.normal[1]],m=Math.max(0,s?.[i.id]||0),g=i.x+_[0]*m/2,f=i.y+_[1]*m/2,v=Math.cos(u)*p,y=Math.sin(u)*p,b=[g-v,f-y],w=[g+v,f+y],k=c*i.length,x=cr(lr(b,w,l,k),d);if(!x.length)continue;const S=l[0]*_[0]+l[1]*_[1];h.push({openingId:i.id,roomId:t.roomId,polys:x,a:b,b:w,dir:l,len:k,normal:_,depth:k*S})}return h}const dr=e=>"number"==typeof e&&Number.isInteger(e)&&e>=0&&e<=359?e:null;function ur(e,t){const i=dr(t?.north_deg);return null!==i?i:dr(e?.north_deg)}function pr(e,t){const i=e=>"static"===e||"daynight"===e?e:null;return i(t?.bg_mode)??i(e?.bg_mode)??"static"}function _r(e,t){const i=t?.sun_rays;return"boolean"==typeof i?i:!0===e?.sun_rays}function mr(e){const t=e?.states?.["sun.sun"]?.attributes,i=Number(t?.azimuth),n=Number(t?.elevation);return Number.isFinite(i)&&Number.isFinite(n)?{azimuth:i,elevation:n}:null}const gr=["dawn","day","dusk","night"];function fr(e){if(!e)return"";const t=Yn[e.phase];return[`--hp-day-cycle-outline-near:${t.outlineNear}`,`--hp-day-cycle-outline-mid:${t.outlineMid}`,`--hp-day-cycle-outline-far:${t.outlineFar}`].join(";")}function vr(e,t=1){if(!e)return V;const i=[`--hp-day-cycle-sun-x:${e.sunX.toFixed(2)}%`,`--hp-day-cycle-sun-y:${e.sunY.toFixed(2)}%`,`--hp-day-cycle-sun-opacity:${e.sunOpacity.toFixed(3)}`,`opacity:${Math.min(1,Math.max(0,t)).toFixed(4)}`].join(";");return W` - ${this._canEdit&&!this._kiosk?W`
    + style=${z?`opacity:${z.toolbarContentOpacity}`:V}> ${this._editorRuntime?"plan"===D?this._renderMarkupBar():"devices"===D?this._renderDevicesBar():this._renderDecorBar():V}
    `:V}
    -
    this._markupClick(e)} @wheel=${e=>this._onWheel(e)} @pointerdown=${e=>{this._notePointer(e),this._stagePointerDown(e)}} @@ -5484,7 +5484,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    - ${d&&M?.structural?j` - ${Me(d&&M?.structural?j`
    - ${this._wallDialog?W`
    ${this._renderWallThickDialog()}
    `:V} + ${this._wallDialog?j`
    ${this._renderWallThickDialog()}
    `:V}
    ${this._renderFarHint()} ${this._renderHomeArrow(this._baseVb(h,x))} ${this._renderEditorRuntimeLoading()} ${this._renderRecoveryOverlay()} - ${this._booting||this._bootFading?W` @@ -5627,7 +5627,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e ${this._deviceInbox&&this._editorRuntime?this._renderDeviceInbox():V} ${this._markerDialog&&this._editorRuntime?this._renderMarkerDialog():V} ${this._backdropGuard?this._editorRuntime?this._editorRuntime._renderBackdropGuard():this._onboardingRuntime?._renderBackdropGuard()??V:V} - ${this._vacCalConfirm&&this._editorRuntime?W`{this._vacCalConfirm?.busy||(this._vacCalConfirm=null)}}> @@ -5655,11 +5655,11 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e ${this._backupImportDialog&&this._editorRuntime?this._renderBackupImportDialog():V} ${this._importDialog&&this._onboardingRuntime?this._renderImportDialog():V} - ${this._kiosk&&!this._hasFixedFloor&&this._kioskDots&&this._model.length>1?W`
    - ${this._model.map(e=>W``)} + ${this._kiosk&&!this._hasFixedFloor&&this._kioskDots&&this._model.length>1?j`
    + ${this._model.map(e=>j``)}
    `:V} ${this._kioskDialog?this._renderKioskDialog():V} - ${this._vacFit?W`
    + ${this._vacFit?j`
    ${this._t("vac.fit_hint")} @@ -5670,12 +5670,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    `:V} - ${this._tapConfirm?W`this._tapConfirm=null}>
    - ${"run"===this._tapConfirm.kind?W`

    ${this._tapConfirm.text}

    `:this._tapConfirm.lines.map((e,t)=>W` + ${"run"===this._tapConfirm.kind?j`

    ${this._tapConfirm.text}

    `:this._tapConfirm.lines.map((e,t)=>j`

    ${e}

    `)}
    @@ -5686,18 +5686,18 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    `:V} - ${this._toast?W``:V} + ${this._toast?j``:V} - `;var B}_vacCandidateStatus(e,t,i=this._planHass){const n=this._bindingStatus("entity:"+e);if("ha_disabled"===n.kind)return"disabled";if("orphaned"===n.kind)return"missing";if("unverified"===n.kind)return"unverified";const r=i?.states?.[e];return"unavailable"===r?.state?"unavailable":t?.hasPosition?"ok":"unsupported"}_vacOpenAllCameras(e){const t=this._haRegistry.entities||{},i=[];for(const[e,n]of Object.entries(this.hass?.states||{})){if(!e.startsWith("camera."))continue;const r=vc(e,n,t[e]);r&&i.push(r)}this._vacAllCameraCache={devId:e.id,candidates:i},this._vacAllCamerasFor=e.id}_vacSourceResolution(e,t=!1,i=this._planHass){const n=e.marker?.vacuum,r="string"==typeof n?.source&&!!n.source,o=new Set(e.entities||[]),s=new Set(o);r&&s.add(n.source);const a=i?.entities||{},l=[];for(const e of s){const t=i?.states?.[e],o=vc(e,t,a[e]);o?l.push(o):r&&e===n.source&&l.push({entityId:e,name:String(t?.attributes?.friendly_name||e),platform:a[e]?.platform?String(a[e].platform):null,category:e.startsWith("camera.")?"camera":"partial",hasPosition:!1,hasRooms:!1,hasPath:!1,hasMapId:!1,score:0})}if(t&&this._vacAllCameraCache?.devId===e.id){const e=new Set(l.map(e=>e.entityId));for(const t of this._vacAllCameraCache.candidates)e.has(t.entityId)||l.push(t)}const c={};for(const e of l)c[e.entityId]=this._vacCandidateStatus(e.entityId,e,i);return function(e,t,i,n){const r="string"==typeof e&&e.length>0,o=new Set(t),s=Array.from(i).sort((t,i)=>r&&t.entityId===e?-1:r&&i.entityId===e?1:i.score-t.score||t.entityId.localeCompare(i.entityId));if(r){const t=s.find(t=>t.entityId===e);return{entityId:e,status:n[e]||(t?.hasPosition?"ok":"unverified"),pinned:!0,candidates:s}}const a=s.find(e=>o.has(e.entityId)&&e.hasPosition&&"ok"===n[e.entityId]);return a?{entityId:a.entityId,status:"ok",pinned:!1,candidates:s}:{entityId:null,status:"none",pinned:!1,candidates:s}}(n?.source,o,l,c)}_vacSource(e,t=this._planHass){if(!1===e.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(e,!1,t);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(e){return e.primary?.startsWith("vacuum.")?e.primary:(e.entities||[]).find(e=>e.startsWith("vacuum."))||null}_isVacDev(e){return!!this._vacEntity(e)}_activitySourceKey(e){return this._activitySnapshot(e).sourceKey}_activitySnapshot(e,t=cd(this._planHass,this._devices,null,this._virtualLights)){const i=xp(this._planHass,e,this._devices,t,this._fullRegistryHass);return{samples:i.samples,sourceKey:Mp(this._planHass,e,i)}}_stampActivity(e,t,i){let n=this._activityRt.get(e);n||(n=vm(i||"",[]),this._activityRt.set(e,n)),null!=i&&(n.sources=i),bm(n,t,Date.now(),window.clearTimeout.bind(window),e=>window.setTimeout(()=>this.requestUpdate(),e))}_syncActivityRuntime(){const e=new Map;if(!this.hass)return e;if(!1===this._config?.live_states){for(const e of this._activityRt.values())clearTimeout(e.timer);return this._activityRt.clear(),e}const t=new Set,i=cd(this._planHass,this._devices,null,this._virtualLights);for(const n of this._devices){if(n.hidden)continue;if("icon_ripple"!==Ei(n.marker?.display))continue;t.add(n.id);const r=this._activitySnapshot(n,i);e.set(n.id,r);const{samples:o,sourceKey:s}=r;let a=this._activityRt.get(n.id);a?a.sources!==s&&ym(a,s,o,window.clearTimeout.bind(window)):(a=vm(s,o),this._activityRt.set(n.id,a))}for(const[e,i]of this._activityRt)t.has(e)||(clearTimeout(i.timer),this._activityRt.delete(e));return e}_activityTick(){if(!this.hass)return;const e=this._syncActivityRuntime();for(const t of this._devices){if(t.hidden)continue;if("icon_ripple"!==Ei(t.marker?.display))continue;const i=e.get(t.id)||this._activitySnapshot(t),{samples:n,sourceKey:r}=i,o=this._activityRt.get(t.id);if(!o||o.sources!==r)continue;const s=wm(o,n,window.clearTimeout.bind(window));s&&this._stampActivity(t.id,s,r)}}_vacTick(){if(this.hass)for(const e of this._devices){if(e.hidden||!this._isVacDev(e))continue;if("static_icon"===Ei(e.marker?.display)){this._vacRt.delete(e.id);continue}const t=this._vacSource(e);if(!t)continue;const i=this._vacEntity(e),n=xc(this.hass.states[i||""]?.state),r=mc(this.hass.states[t]?.attributes);let o=this._vacRt.get(e.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(e.id,o)),n&&!o.moving&&(o.trail=[],o.lastPos=null);const s="never"!==Tc(e.marker?.vacuum)&&!r?.path.length;!n&&o.moving&&(o.endedTs=Date.now(),s&&o.lastPos&&(o.trail=kc(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=n;const a=r?.pos;if(n&&a){const e=a.x+":"+a.y;if(e!==o.lastKey){const t=Date.now();o.jump=o.lastTs>0&&t-o.lastTs>1e4,o.lastKey=e,o.lastTs=t,s&&o.lastPos&&(o.trail=kc(o.trail,o.lastPos,40)),o.lastPos=[a.x,a.y]}}}}_vacEnsureMarker(e){const t=this._serverCfg;if(!t)return null;t.markers=t.markers||[];const i=t.markers.find(t=>t.id===e.id);if(i)return i;if("device"!==e.bindingKind&&"entity"!==e.bindingKind||!e.bindingRef)return null;const n={id:e.id,binding:e.bindingKind+":"+e.bindingRef,space:e.space||null,area:e.area||null,hidden:!!e.hidden};return t.markers.push(n),n}_renderVacSection(e){return this._editorRuntimeOrThrow()._renderVacSection(e)}_vacMapId(e,t,i=this._planHass){const n=this._vacEntity(e),r=n?i?.states?.[n]?.attributes?.selected_map:null;return o=t.mapId,s=r,"default"!==o?o:null!=s?String(s):"default";var o,s}_vacObservedMapId(e,t,i=this._planHass){const n=mc(i?.states?.[t]?.attributes);return n?this._vacMapId(e,n,i):void 0}_vacSaveMatrix(e,t,i,n,r=""){return this._editorRuntimeOrThrow()._vacSaveMatrix(e,t,i,n,r)}_vacPlanRoomAnchors(e){return this._editorRuntimeOrThrow()._vacPlanRoomAnchors(e)}_vacAutoCalibrate(e){return this._editorRuntimeOrThrow()._vacAutoCalibrate(e)}_vacApplyCalibrationProposal(e){return this._editorRuntimeOrThrow()._vacApplyCalibrationProposal(e)}_vacStartFit(e){return this._editorRuntimeOrThrow()._vacStartFit(e)}_vacFitSave(){return this._editorRuntimeOrThrow()._vacFitSave()}_vacFitTurn(e){return this._editorRuntimeOrThrow()._vacFitTurn(e)}_vacGhostCentre(e){return this._editorRuntimeOrThrow()._vacGhostCentre(e)}_vacDelta(e,t,i){return this._editorRuntimeOrThrow()._vacDelta(e,t,i)}_vacFitPointer(e,t){return this._editorRuntimeOrThrow()._vacFitPointer(e,t)}_renderVacFit(e){return this._editorRuntime?this._editorRuntimeOrThrow()._renderVacFit(e):V}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const e=this.renderRoot,t=this._stageEl,i=this._vacLastView,n=e?.querySelectorAll?.(".vacpuck")||[];if(!t||!i||!n.length)return void(this._vacRaf=0);const r=t.getBoundingClientRect();for(const t of n){const n=t.getAttribute("data-mid"),o=t.getBoundingClientRect(),s=i.x+(o.left+o.width/2-r.left)/r.width*i.w,a=i.y+(o.top+o.height/2-r.top)/r.height*i.h;for(const t of e.querySelectorAll(`line.tip[data-mid="${n}"]`))t.setAttribute("x2",s.toFixed(1)),t.setAttribute("y2",a.toFixed(1))}this._vacRafLoop()})}_vacTrailPathD(e,t){const i=e.map(e=>e.map(([e,i])=>rc(t,e,i))),n=function(e,t,i=console.warn){if(!Number.isFinite(t)||t<=0)return[];const n=[];let r=0;for(const i of e){if(!i.every(pc)){r++;continue}const e=i.filter((e,t)=>0===t||!_c(e,i[t-1]));if(e.length<2)continue;const o=[{kind:"move",point:e[0]}];if(2!==e.length){for(let i=1;i0&&i(`[houseplan] vacuum trail: ${r} segment(s) dropped — non-finite point (check map calibration)`),n}(i,this._cmToUnits(17.5)),r=e=>{const t=this._scenePoint(e);return`${t[0].toFixed(1)} ${t[1].toFixed(1)}`};return n.map(e=>e.map(e=>"move"===e.kind?`M ${r(e.point)}`:"line"===e.kind?`L ${r(e.point)}`:`Q ${r(e.control)} ${r(e.point)}`).join(" ")).join(" ")}_renderVacuums(e,t,i){if(this._markup||"decor"===this._mode)return V;const n=this._space+"|"+t.x+"|"+t.y+"|"+t.w+"|"+t.h,r=this._vacJumpOnce||n!==this._vacViewKey;this._vacViewKey=n,this._vacJumpOnce=!1;const o=[],s=[];for(const n of e){if(n.hidden||!this._isVacDev(n))continue;if("static_icon"===Ei(n.marker?.display))continue;const e=this._renderDeviceSnapshot?.facts.get(`vacuum:${n.id}`),a=e?.source??this._vacSource(n,this._renderPlanHass);if(!a)continue;const l=e?.telemetry??mc(this._renderPlanHass?.states[a]?.attributes);if(!l)continue;const c=e?.routes??Pc(n.id,n.marker?.vacuum??null,n.space,a),h=e?.resolution??Ic({routes:c,observed:Oc(c,[a],e=>this._vacObservedMapId(n,e)),spaceIds:new Set(this._model.map(e=>e.id))}),d=e?.server??this._vacSrvTrails[n.id],u=Hc({resolution:h,routes:c,renderSpace:i,rootSource:n.marker?.vacuum?.source??null,serverCurrent:d?.current??null,serverPrevious:d?.previous??null,explicitRoutes:Array.isArray(n.marker?.vacuum?.map_routes)});if(!u.live&&!u.previous)continue;const p=u.live,_=e?.runtime??this._vacRt.get(n.id),m=_?.moving??!1,g=Tc(n.marker?.vacuum),f="always"===g||"cleaning"===g&&m,v=d,y=u.currentRunMatches&&Array.isArray(v?.current?.points)?v.current:null,b=u.previous&&Array.isArray(v?.previous?.points)?v.previous:null;if("always"===g&&b&&u.previous){const e=hc(b.points),t=this._vacTrailPathD(e,u.previous);t&&s.push(j``)}if(f&&p){const e=dc(l,y,_?.trail||[]),t=!m||"integration"!==e.source&&"server"!==e.source?e.path:uc(e.path);if(t.length){const e=this._vacTrailPathD(t,p);e&&s.push(j``);const i=t[t.length-1];if(m&&i?.length>=2){const e=i[i.length-1],[t,r]=rc(p,e[0],e[1]),o=this._scenePoint([t,r]),a=o[0].toFixed(1),l=o[1].toFixed(1);s.push(j``)}}}if(!m||!l.pos||!p)continue;const[w,k]=rc(p,l.pos.x,l.pos.y),x=this._scenePoint([w,k]),S=(x[0]-t.x)/t.w*100,$=(x[1]-t.y)/t.h*100,M=_&&_.lastTs>0&&Date.now()-_.lastTs>6e4,R=n.marker?.icon||n.icon||"mdi:robot-vacuum";o.push(W`
    e.entityId));for(const t of this._vacAllCameraCache.candidates)e.has(t.entityId)||l.push(t)}const c={};for(const e of l)c[e.entityId]=this._vacCandidateStatus(e.entityId,e,i);return function(e,t,i,n){const r="string"==typeof e&&e.length>0,o=new Set(t),s=Array.from(i).sort((t,i)=>r&&t.entityId===e?-1:r&&i.entityId===e?1:i.score-t.score||t.entityId.localeCompare(i.entityId));if(r){const t=s.find(t=>t.entityId===e);return{entityId:e,status:n[e]||(t?.hasPosition?"ok":"unverified"),pinned:!0,candidates:s}}const a=s.find(e=>o.has(e.entityId)&&e.hasPosition&&"ok"===n[e.entityId]);return a?{entityId:a.entityId,status:"ok",pinned:!1,candidates:s}:{entityId:null,status:"none",pinned:!1,candidates:s}}(n?.source,o,l,c)}_vacSource(e,t=this._planHass){if(!1===e.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(e,!1,t);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(e){return e.primary?.startsWith("vacuum.")?e.primary:(e.entities||[]).find(e=>e.startsWith("vacuum."))||null}_isVacDev(e){return!!this._vacEntity(e)}_activitySourceKey(e){return this._activitySnapshot(e).sourceKey}_activitySnapshot(e,t=_d(this._planHass,this._devices,null,this._virtualLights)){const i=Cp(this._planHass,e,this._devices,t,this._fullRegistryHass);return{samples:i.samples,sourceKey:Ap(this._planHass,e,i)}}_stampActivity(e,t,i){let n=this._activityRt.get(e);n||(n=xm(i||"",[]),this._activityRt.set(e,n)),null!=i&&(n.sources=i),$m(n,t,Date.now(),window.clearTimeout.bind(window),e=>window.setTimeout(()=>this.requestUpdate(),e))}_syncActivityRuntime(){const e=new Map;if(!this.hass)return e;if(!1===this._config?.live_states){for(const e of this._activityRt.values())clearTimeout(e.timer);return this._activityRt.clear(),e}const t=new Set,i=_d(this._planHass,this._devices,null,this._virtualLights);for(const n of this._devices){if(n.hidden)continue;if("icon_ripple"!==Ei(n.marker?.display))continue;t.add(n.id);const r=this._activitySnapshot(n,i);e.set(n.id,r);const{samples:o,sourceKey:s}=r;let a=this._activityRt.get(n.id);a?a.sources!==s&&Sm(a,s,o,window.clearTimeout.bind(window)):(a=xm(s,o),this._activityRt.set(n.id,a))}for(const[e,i]of this._activityRt)t.has(e)||(clearTimeout(i.timer),this._activityRt.delete(e));return e}_activityTick(){if(!this.hass)return;const e=this._syncActivityRuntime();for(const t of this._devices){if(t.hidden)continue;if("icon_ripple"!==Ei(t.marker?.display))continue;const i=e.get(t.id)||this._activitySnapshot(t),{samples:n,sourceKey:r}=i,o=this._activityRt.get(t.id);if(!o||o.sources!==r)continue;const s=Mm(o,n,window.clearTimeout.bind(window));s&&this._stampActivity(t.id,s,r)}}_vacTick(){if(this.hass)for(const e of this._devices){if(e.hidden||!this._isVacDev(e))continue;if("static_icon"===Ei(e.marker?.display)){this._vacRt.delete(e.id);continue}const t=this._vacSource(e);if(!t)continue;const i=this._vacEntity(e),n=Cc(this.hass.states[i||""]?.state),r=bc(this.hass.states[t]?.attributes);let o=this._vacRt.get(e.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(e.id,o)),n&&!o.moving&&(o.trail=[],o.lastPos=null);const s="never"!==zc(e.marker?.vacuum)&&!r?.path.length;!n&&o.moving&&(o.endedTs=Date.now(),s&&o.lastPos&&(o.trail=Rc(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=n;const a=r?.pos;if(n&&a){const e=a.x+":"+a.y;if(e!==o.lastKey){const t=Date.now();o.jump=o.lastTs>0&&t-o.lastTs>1e4,o.lastKey=e,o.lastTs=t,s&&o.lastPos&&(o.trail=Rc(o.trail,o.lastPos,40)),o.lastPos=[a.x,a.y]}}}}_vacEnsureMarker(e){const t=this._serverCfg;if(!t)return null;t.markers=t.markers||[];const i=t.markers.find(t=>t.id===e.id);if(i)return i;if("device"!==e.bindingKind&&"entity"!==e.bindingKind||!e.bindingRef)return null;const n={id:e.id,binding:e.bindingKind+":"+e.bindingRef,space:e.space||null,area:e.area||null,hidden:!!e.hidden};return t.markers.push(n),n}_renderVacSection(e){return this._editorRuntimeOrThrow()._renderVacSection(e)}_vacMapId(e,t,i=this._planHass){const n=this._vacEntity(e),r=n?i?.states?.[n]?.attributes?.selected_map:null;return o=t.mapId,s=r,"default"!==o?o:null!=s?String(s):"default";var o,s}_vacObservedMapId(e,t,i=this._planHass){const n=bc(i?.states?.[t]?.attributes);return n?this._vacMapId(e,n,i):void 0}_vacSaveMatrix(e,t,i,n,r=""){return this._editorRuntimeOrThrow()._vacSaveMatrix(e,t,i,n,r)}_vacPlanRoomAnchors(e){return this._editorRuntimeOrThrow()._vacPlanRoomAnchors(e)}_vacAutoCalibrate(e){return this._editorRuntimeOrThrow()._vacAutoCalibrate(e)}_vacApplyCalibrationProposal(e){return this._editorRuntimeOrThrow()._vacApplyCalibrationProposal(e)}_vacStartFit(e){return this._editorRuntimeOrThrow()._vacStartFit(e)}_vacFitSave(){return this._editorRuntimeOrThrow()._vacFitSave()}_vacFitTurn(e){return this._editorRuntimeOrThrow()._vacFitTurn(e)}_vacGhostCentre(e){return this._editorRuntimeOrThrow()._vacGhostCentre(e)}_vacDelta(e,t,i){return this._editorRuntimeOrThrow()._vacDelta(e,t,i)}_vacFitPointer(e,t){return this._editorRuntimeOrThrow()._vacFitPointer(e,t)}_renderVacFit(e){return this._editorRuntime?this._editorRuntimeOrThrow()._renderVacFit(e):V}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const e=this.renderRoot,t=this._stageEl,i=this._vacLastView,n=e?.querySelectorAll?.(".vacpuck")||[];if(!t||!i||!n.length)return void(this._vacRaf=0);const r=t.getBoundingClientRect();for(const t of n){const n=t.getAttribute("data-mid"),o=t.getBoundingClientRect(),s=i.x+(o.left+o.width/2-r.left)/r.width*i.w,a=i.y+(o.top+o.height/2-r.top)/r.height*i.h;for(const t of e.querySelectorAll(`line.tip[data-mid="${n}"]`))t.setAttribute("x2",s.toFixed(1)),t.setAttribute("y2",a.toFixed(1))}this._vacRafLoop()})}_vacTrailPathD(e,t){const i=e.map(e=>e.map(([e,i])=>cc(t,e,i))),n=function(e,t,i=console.warn){if(!Number.isFinite(t)||t<=0)return[];const n=[];let r=0;for(const i of e){if(!i.every(vc)){r++;continue}const e=i.filter((e,t)=>0===t||!yc(e,i[t-1]));if(e.length<2)continue;const o=[{kind:"move",point:e[0]}];if(2!==e.length){for(let i=1;i0&&i(`[houseplan] vacuum trail: ${r} segment(s) dropped — non-finite point (check map calibration)`),n}(i,this._cmToUnits(17.5)),r=e=>{const t=this._scenePoint(e);return`${t[0].toFixed(1)} ${t[1].toFixed(1)}`};return n.map(e=>e.map(e=>"move"===e.kind?`M ${r(e.point)}`:"line"===e.kind?`L ${r(e.point)}`:`Q ${r(e.control)} ${r(e.point)}`).join(" ")).join(" ")}_renderVacuums(e,t,i){if(this._markup||"decor"===this._mode)return V;const n=this._space+"|"+t.x+"|"+t.y+"|"+t.w+"|"+t.h,r=this._vacJumpOnce||n!==this._vacViewKey;this._vacViewKey=n,this._vacJumpOnce=!1;const o=[],s=[];for(const n of e){if(n.hidden||!this._isVacDev(n))continue;if("static_icon"===Ei(n.marker?.display))continue;const e=this._renderDeviceSnapshot?.facts.get(`vacuum:${n.id}`),a=e?.source??this._vacSource(n,this._renderPlanHass);if(!a)continue;const l=e?.telemetry??bc(this._renderPlanHass?.states[a]?.attributes);if(!l)continue;const c=e?.routes??Nc(n.id,n.marker?.vacuum??null,n.space,a),h=e?.resolution??Lc({routes:c,observed:Bc(c,[a],e=>this._vacObservedMapId(n,e)),spaceIds:new Set(this._model.map(e=>e.id))}),d=e?.server??this._vacSrvTrails[n.id],u=jc({resolution:h,routes:c,renderSpace:i,rootSource:n.marker?.vacuum?.source??null,serverCurrent:d?.current??null,serverPrevious:d?.previous??null,explicitRoutes:Array.isArray(n.marker?.vacuum?.map_routes)});if(!u.live&&!u.previous)continue;const p=u.live,_=e?.runtime??this._vacRt.get(n.id),m=_?.moving??!1,g=zc(n.marker?.vacuum),f="always"===g||"cleaning"===g&&m,v=d,y=u.currentRunMatches&&Array.isArray(v?.current?.points)?v.current:null,b=u.previous&&Array.isArray(v?.previous?.points)?v.previous:null;if("always"===g&&b&&u.previous){const e=mc(b.points),t=this._vacTrailPathD(e,u.previous);t&&s.push(W``)}if(f&&p){const e=gc(l,y,_?.trail||[]),t=!m||"integration"!==e.source&&"server"!==e.source?e.path:fc(e.path);if(t.length){const e=this._vacTrailPathD(t,p);e&&s.push(W``);const i=t[t.length-1];if(m&&i?.length>=2){const e=i[i.length-1],[t,r]=cc(p,e[0],e[1]),o=this._scenePoint([t,r]),a=o[0].toFixed(1),l=o[1].toFixed(1);s.push(W``)}}}if(!m||!l.pos||!p)continue;const[w,k]=cc(p,l.pos.x,l.pos.y),x=this._scenePoint([w,k]),S=(x[0]-t.x)/t.w*100,$=(x[1]-t.y)/t.h*100,M=_&&_.lastTs>0&&Date.now()-_.lastTs>6e4,R=n.marker?.icon||n.icon||"mdi:robot-vacuum";o.push(j`
    {e.stopPropagation();const t=this._vacEntity(n);t&&this._openMoreInfo(t)}}> -
    `)}return this._vacLastView=t,o.length&&!this._vacRaf&&this._vacRafLoop(),o.length||s.length?W` - ${s.length?j`${s}`:V} - ${o}`:V}_renderDevice(e,t,i=!0,n){const r=this._pos(e),o=n?.visualScene??this._scenePoint([r.x,r.y]),s=(o[0]-t.x)/t.w*100,a=(o[1]-t.y)/t.h*100,l=this._devicePresentation(e,i),c=[`left:${s}%`,`top:${a}%`,...Ip(l)],h=l.disabledReason,d=l.haDisabled?this._t(`marker.ha_disabled_${h}`):e.userHidden?this._t("marker.hidden_ghost"):e.name,u=fp(l),p="view"===this._mode||"devices"===this._mode,_=[d,l.haDisabled?"":this._t(`marker.state_a11y_${u}`),"none"!==l.pulse.kind?this._t(`marker.pulse_a11y_${l.pulse.reason}`):"",l.valueFullText||l.valueText||"",Xu(l.valueBadge),null!=l.lqiText&&l.lqiBand?this._t(`marker.lqi_a11y_${l.lqiBand}`,{value:l.lqiText}):""].filter(Boolean).join(", "),m=[e.model,l.valueBadge?.fullText||"",null!=l.lqiText?"LQI "+l.lqiText:""].filter(Boolean).join(" · ");return W`
    `)}return this._vacLastView=t,o.length&&!this._vacRaf&&this._vacRafLoop(),o.length||s.length?j` + ${s.length?W`${s}`:V} + ${o}`:V}_renderDevice(e,t,i=!0,n){const r=this._pos(e),o=n?.visualScene??this._scenePoint([r.x,r.y]),s=(o[0]-t.x)/t.w*100,a=(o[1]-t.y)/t.h*100,l=this._devicePresentation(e,i),c=[`left:${s}%`,`top:${a}%`,...Lp(l)],h=l.disabledReason,d=l.haDisabled?this._t(`marker.ha_disabled_${h}`):e.userHidden?this._t("marker.hidden_ghost"):e.name,u=kp(l),p="view"===this._mode||"devices"===this._mode,_=[d,l.haDisabled?"":this._t(`marker.state_a11y_${u}`),"none"!==l.pulse.kind?this._t(`marker.pulse_a11y_${l.pulse.reason}`):"",l.valueFullText||l.valueText||"",tp(l.valueBadge),null!=l.lqiText&&l.lqiBand?this._t(`marker.lqi_a11y_${l.lqiBand}`,{value:l.lqiText}):""].filter(Boolean).join(", "),m=[e.model,l.valueBadge?.fullText||"",null!=l.lqiText?"LQI "+l.lqiText:""].filter(Boolean).join(" · ");return j`
    this._clickDevice(t,e)} @keydown=${t=>this._keyDevice(t,e)} @@ -5728,10 +5728,10 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e @pointercancel=${t=>this._pointerCancel(t,e)} @lostpointercapture=${t=>this._pointerCancel(t,e)} > - ${Ep(l,{newDevice:this._newIds.has(e.id),newDeviceTitle:this._t("device.new"),disabledTitle:l.haDisabled?d:""})} + ${qp(l,{newDevice:this._newIds.has(e.id),newDeviceTitle:this._t("device.new"),disabledTitle:l.haDisabled?d:""})} ${this._vacRouteBadge(e)} -
    `}_vacRouteBadge(e){if(!this._isVacDev(e)||e.hidden)return V;if("static_icon"===Ei(e.marker?.display))return V;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${e.id}`),i=function(e,t){if(!t||!e)return null;switch(e.kind){case"unmapped":case"needs_calibration":case"ambiguous":case"missing_space":return e.kind;default:return null}}(t?.resolution,this._vacRt.get(e.id)?.moving??!1);if(!i)return V;const n=this._t(`vac.route_warn_${i}`);return W` - `}_roomArea(e){const t=ei(e);if(!t)return null;const i=this._spaceModel();if(!i)return null;const n=this._spaceWalls.length&&e.id&&this._innerRoomContour(i,e.id)||t,r=this._cleanFloor(e,n),o=this._cellCm/this._gridPitch;return Vn(r.area*o*o/1e4,"mi"===this._renderPlanHass?.config?.unit_system?.length)}_roomTemp(e){const t=e.settings?.temp_source;if(t)return Dd(this._renderPlanHass,t,"temp",this._markers);const i=Ad(this._spaceModel()?.id,e);return i?this._climate().get(i)?.temp??null:null}_roomHum(e){const t=e.settings?.hum_source;if(t)return Dd(this._renderPlanHass,t,"hum",this._markers);const i=Ad(this._spaceModel()?.id,e);return i?this._climate().get(i)?.hum??null:null}_climate(){const e=this._serverCfg?.markers,t=this._renderPlanHass,i=this._climateCache,n=this._settings.exclude_integrations;if(i&&i.h===t&&i.r===this._iconRules&&i.mk===e&&i.ex===n)return i.m;const r=Id(t,this._iconRules,e,this._excluded);return this._climateCache={h:t,r:this._iconRules,mk:e,ex:n,m:r},r}_resetRoomDialogFields(){return this._editorRuntimeOrThrow()._resetRoomDialogFields()}_openRoomEdit(e){return this._editorRuntimeOrThrow()._openRoomEdit(e)}_roomSettingsFromDialog(){return this._editorRuntimeOrThrow()._roomSettingsFromDialog()}_saveRoomEdit(){return this._editorRuntimeOrThrow()._saveRoomEdit()}_roomSrcCandidates(){return this._editorRuntimeOrThrow()._roomSrcCandidates()}_roomSrcLabel(e){return this._editorRuntimeOrThrow()._roomSrcLabel(e)}_labelPos(e,t){const i=this._layout["rl_"+(e.id||"")];if(i&&i.s===t)return{x:i.x*Sf,y:i.y*Sf};const n=this._roomCenter(e),r=this._gridPitch;return{x:Qa(Xt(n[0],r)),y:Qa(Xt(n[1],r))}}_labelDown(e,t,i){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelDown(e,t,i)}_labelMove(e,t,i){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelMove(e,t,i)}_labelUp(e){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelUp(e)}_labelScale(e){const t=this._layout["rl_"+(e.id||"")]?.k;return"number"==typeof t&&Number.isFinite(t)?Math.min(3,Math.max(.5,t)):1}_rlResizeDown(e,t,i){return this._editorRuntimeOrThrow()._rlResizeDown(e,t,i)}_rlResizeMove(e){return this._editorRuntimeOrThrow()._rlResizeMove(e)}_rlResizeUp(){return this._editorRuntimeOrThrow()._rlResizeUp()}_renderRoomGear(e,t,i){return this._editorRuntimeOrThrow()._renderRoomGear(e,t,i)}_renderRoomLabel(e,t,i,n,r){if(!e.name&&!this._markup)return V;const o=this._labelPos(e,t.id),s=r?.visualScene??this._scenePoint([o.x,o.y]),a=(s[0]-i.x)/i.w*100,l=(s[1]-i.y)/i.h*100,c=Math.min(1,n.opacity+.25),h=this._labelScale(e),d=[];if(n.labelTemp||n.labelHum||n.labelLqi&&e.area||n.labelLight){if(n.labelTemp){const t=this._roomTemp(e);null!=t&&d.push(W`${t}°`)}if(n.labelHum){const t=this._roomHum(e);null!=t&&d.push(W`${t}%`)}if(n.labelLqi&&e.area){const t=this._roomLqi(e.area);null!=t&&d.push(W`${t}`)}if(n.labelLight){const t=(u=cd(this._renderPlanHass,this._renderDevices,e,this._virtualLights)).length?{on:u.filter(e=>e.on).length,total:u.length}:null;if(t){const e=0===t.on?this._t("roomcard.light_off"):t.on===t.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:t.on,total:t.total});d.push(W`${e}`)}}}var u;const p=!!e.area,_=!this._markup;return W`
    `}_vacRouteBadge(e){if(!this._isVacDev(e)||e.hidden)return V;if("static_icon"===Ei(e.marker?.display))return V;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${e.id}`),i=function(e,t){if(!t||!e)return null;switch(e.kind){case"unmapped":case"needs_calibration":case"ambiguous":case"missing_space":return e.kind;default:return null}}(t?.resolution,this._vacRt.get(e.id)?.moving??!1);if(!i)return V;const n=this._t(`vac.route_warn_${i}`);return j` + `}_roomArea(e){const t=ei(e);if(!t)return null;const i=this._spaceModel();if(!i)return null;const n=this._spaceWalls.length&&e.id&&this._innerRoomContour(i,e.id)||t,r=this._cleanFloor(e,n),o=this._cellCm/this._gridPitch;return Vn(r.area*o*o/1e4,"mi"===this._renderPlanHass?.config?.unit_system?.length)}_roomTemp(e){const t=e.settings?.temp_source;if(t)return Id(this._renderPlanHass,t,"temp",this._markers);const i=Ed(this._spaceModel()?.id,e);return i?this._climate().get(i)?.temp??null:null}_roomHum(e){const t=e.settings?.hum_source;if(t)return Id(this._renderPlanHass,t,"hum",this._markers);const i=Ed(this._spaceModel()?.id,e);return i?this._climate().get(i)?.hum??null:null}_climate(){const e=this._serverCfg?.markers,t=this._renderPlanHass,i=this._climateCache,n=this._settings.exclude_integrations;if(i&&i.h===t&&i.r===this._iconRules&&i.mk===e&&i.ex===n)return i.m;const r=Ld(t,this._iconRules,e,this._excluded);return this._climateCache={h:t,r:this._iconRules,mk:e,ex:n,m:r},r}_resetRoomDialogFields(){return this._editorRuntimeOrThrow()._resetRoomDialogFields()}_openRoomEdit(e){return this._editorRuntimeOrThrow()._openRoomEdit(e)}_roomSettingsFromDialog(){return this._editorRuntimeOrThrow()._roomSettingsFromDialog()}_saveRoomEdit(){return this._editorRuntimeOrThrow()._saveRoomEdit()}_roomSrcCandidates(){return this._editorRuntimeOrThrow()._roomSrcCandidates()}_roomSrcLabel(e){return this._editorRuntimeOrThrow()._roomSrcLabel(e)}_labelPos(e,t){const i=this._layout["rl_"+(e.id||"")];if(i&&i.s===t)return{x:i.x*Tf,y:i.y*Tf};const n=this._roomCenter(e),r=this._gridPitch;return{x:Qa(Xt(n[0],r)),y:Qa(Xt(n[1],r))}}_labelDown(e,t,i){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelDown(e,t,i)}_labelMove(e,t,i){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelMove(e,t,i)}_labelUp(e){if(this._editorRuntime)return this._editorRuntimeOrThrow()._labelUp(e)}_labelScale(e){const t=this._layout["rl_"+(e.id||"")]?.k;return"number"==typeof t&&Number.isFinite(t)?Math.min(3,Math.max(.5,t)):1}_rlResizeDown(e,t,i){return this._editorRuntimeOrThrow()._rlResizeDown(e,t,i)}_rlResizeMove(e){return this._editorRuntimeOrThrow()._rlResizeMove(e)}_rlResizeUp(){return this._editorRuntimeOrThrow()._rlResizeUp()}_renderRoomGear(e,t,i){return this._editorRuntimeOrThrow()._renderRoomGear(e,t,i)}_renderRoomLabel(e,t,i,n,r){if(!e.name&&!this._markup)return V;const o=this._labelPos(e,t.id),s=r?.visualScene??this._scenePoint([o.x,o.y]),a=(s[0]-i.x)/i.w*100,l=(s[1]-i.y)/i.h*100,c=Math.min(1,n.opacity+.25),h=this._labelScale(e),d=[];if(n.labelTemp||n.labelHum||n.labelLqi&&e.area||n.labelLight){if(n.labelTemp){const t=this._roomTemp(e);null!=t&&d.push(j`${t}°`)}if(n.labelHum){const t=this._roomHum(e);null!=t&&d.push(j`${t}%`)}if(n.labelLqi&&e.area){const t=this._roomLqi(e.area);null!=t&&d.push(j`${t}`)}if(n.labelLight){const t=(u=_d(this._renderPlanHass,this._renderDevices,e,this._virtualLights)).length?{on:u.filter(e=>e.on).length,total:u.length}:null;if(t){const e=0===t.on?this._t("roomcard.light_off"):t.on===t.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:t.on,total:t.total});d.push(j`${e}`)}}}var u;const p=!!e.area,_=!this._markup;return j`
    ${e.name||(this._markup?this._t("room.unnamed"):"")}${p?W`${e.name||(this._markup?this._t("room.unnamed"):"")}${p?j`{t.stopPropagation(),this._clickRoom(e)}:V} @pointerdown=${_?e=>e.stopPropagation():V}>`:V} - ${d.length?W`${d}`:V} - ${"plan"===this._mode?["tl","tr","bl","br"].map(i=>W`${d}`:V} + ${"plan"===this._mode?["tl","tr","bl","br"].map(i=>j`this._rlResizeDown(i,e,t.id)} @pointermove=${e=>this._rlResizeMove(e)} @pointerup=${()=>this._rlResizeUp()} @pointercancel=${()=>this._rlResizeUp()}>`):V} -
    `}_renderLiveEditorMeasurements(e){const t=e,i=this._opMeasureView,n=this._decorMeasure,r=this._bdLive,o=this._editorRuntime?._furnLive()??null;return W` - ${this._measureAnchor?W`
    ${this._renderMeasureLabel(t)}
    `:V} - ${this._resize?.liveLabels?W`
    ${this._resize.liveLabels.map(e=>W`
    `}_renderLiveEditorMeasurements(e){const t=e,i=this._opMeasureView,n=this._decorMeasure,r=this._bdLive,o=this._editorRuntime?._furnLive()??null;return j` + ${this._measureAnchor?j`
    ${this._renderMeasureLabel(t)}
    `:V} + ${this._resize?.liveLabels?j`
    ${this._resize.liveLabels.map(e=>j`
    ${e.text}
    `)}
    `:V} - ${i?W`
    ${i.labels.map(e=>W`
    ${i.labels.map(e=>j`
    ${e.text}
    `)}
    `:V} - ${n?W`
    ${n.text}
    `:V} - ${o?W`
    ${o.map(e=>W`
    ${o.map(e=>j`
    ${e.text}
    `)}
    `:V} - ${r?W`
    ${r.text}
    `:V} - `}get _measureAnchor(){return this._markup&&this._cursorPt?"draw"===this._tool&&this._path.length&&!this._contourClosed?this._path[this._path.length-1]:"split"===this._tool&&this._splitSel?.pts?.length?this._splitSel.pts[this._splitSel.pts.length-1]:null:null}_renderMeasureLabel(e){const t=this._measureAnchor,i=this._cursorPt,n=(i[0]-e.x)/e.w*100,r=(i[1]-e.y)/e.h*100,o=Nn(t,i),s=Math.round(10*o)/10,a=function(e,t,i=.001){if(e.length<2||t.length<2)return!1;const n=Math.abs(t[0]-e[0]),r=Math.abs(t[1]-e[1]);if(!Number.isFinite(n)||!Number.isFinite(r)||Math.hypot(n,r)<=i)return!1;const o=Math.max(n,r,1);return n<=i*o||r<=i*o||Math.abs(n-r)<=i*o}(t,i,2e-4*this._gridPitch);return W`
    - ${this._fmtLen(t,i)} · ${s}°
    `}get _decorMeasure(){const e=this._decorDraft;if(!e||"decor"!==this._mode)return null;const[t,i]=e.a,[n,r]=e.b;if(Math.abs(t-n)<1e-6&&Math.abs(i-r)<1e-6)return null;const o=(t+n)/2,s=(i+r)/2;if("line"===e.kind){const t=Nn(e.a,e.b);return{x:o,y:s,on45:Ln(t),text:`${this._fmtLen(e.a,e.b)} · ${Math.round(10*t)/10}°`}}const a=this._fmtLen([t,i],[n,i]),l=this._fmtLen([n,i],[n,r]);if("ellipse"===e.kind){const e=this._fmtLen([0,0],[Math.abs(n-t)/2,0]),a=this._fmtLen([0,0],[0,Math.abs(r-i)/2]);return{x:o,y:s,on45:!1,text:Math.abs(Math.abs(n-t)-Math.abs(r-i))<1e-6?`R ${e}`:`Rx ${e} × Ry ${a}`}}return{x:o,y:s,on45:!1,text:`${a} × ${l} · ${Vn($r(Math.abs(n-t),this._cellCm,this._gridPitch)*$r(Math.abs(r-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const e=this._drag.id.slice(3),t=this._spaceModel()?.rooms.find(t=>t.id===e);return t?(()=>{const e=this._labelPos(t,this._space);return[e.x,e.y]})():null}return null}if("devices"===this._mode&&this._deviceDrag?.moved){const e=this._devices.find(e=>e.id===this._deviceDrag.id);return e?(()=>{const t=this._pos(e);return[t.x,t.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const e=this._decorList.find(e=>e.id===this._decorMove.id);if(!e)return null;const t=Sf,i=this._decorH;return"line"===e.kind?[e.x1*t,e.y1*i]:[e.x*t,e.y*i]}return null}return null}_alignCandidates(){return this._editorRuntimeOrThrow()._alignCandidates()}_renderAlignGuides(){return this._editorRuntimeOrThrow()._renderAlignGuides()}_renderOpeningCenterTick(e){return this._editorRuntimeOrThrow()._renderOpeningCenterTick(e)}_renderOpeningDimensionGuides(e){return this._editorRuntimeOrThrow()._renderOpeningDimensionGuides(e)}_roomCenter(e){if(e.poly){const t=e.poly.length;return[e.poly.reduce((e,t)=>e+t[0],0)/t,e.poly.reduce((e,t)=>e+t[1],0)/t]}return[e.x+e.w/2,e.y+.1*Math.min(e.w,e.h)]}_openingAmt(e){const t=e.contact&&this._renderOpeningEntityAvailable(e.contact)?this._renderPlanHass.states[e.contact]:null;return si(e.type,t?.state,!!e.invert,t?.attributes?.current_position)}_planEntityAvailable(e){return!!e&&(!Sd(this._fullRegistryHass,e,xd(this._markers))&&"active"===this._bindingStatus("entity:"+e).kind)}_renderEntityAvailable(e){return!!e&&(!Sd(this._renderPlanHass,e,xd(this._markers))&&(!!this._renderPlanHass.entities?.[e]&&!!this._renderPlanHass.states?.[e]))}_openingEntityAvailable(e){return function(e,t,i=Th(e)){return!!t&&"active"===Eh(e,`entity:${t}`,i).kind}(this.hass,e,this._haRegistry)}_renderOpeningEntityAvailable(e){return t=this._renderPlanHass,!!(i=e)&&!!t?.states?.[i];var t,i}_renderOpeningPlacementPreview(){return this._editorRuntimeOrThrow()._renderOpeningPlacementPreview()}_renderOpenings(e,t){const i=t?this._openingsR.filter(e=>t.includes(e.id)):this._openingsR;if(!i.length)return j``;const n=this._spaceModel();if(!n)return j``;const r=e.color,o=this._spaceWalls,s=this._openCuts(),a=this._openingWallIndexFor(n,s).value;return j`${i.map(e=>{if(e.orphanReason)return j` + ${this._fmtLen(t,i)} · ${s}°
    `}get _decorMeasure(){const e=this._decorDraft;if(!e||"decor"!==this._mode)return null;const[t,i]=e.a,[n,r]=e.b;if(Math.abs(t-n)<1e-6&&Math.abs(i-r)<1e-6)return null;const o=(t+n)/2,s=(i+r)/2;if("line"===e.kind){const t=Hn(e.a,e.b);return{x:o,y:s,on45:Ln(t),text:`${this._fmtLen(e.a,e.b)} · ${Math.round(10*t)/10}°`}}const a=this._fmtLen([t,i],[n,i]),l=this._fmtLen([n,i],[n,r]);if("ellipse"===e.kind){const e=this._fmtLen([0,0],[Math.abs(n-t)/2,0]),a=this._fmtLen([0,0],[0,Math.abs(r-i)/2]);return{x:o,y:s,on45:!1,text:Math.abs(Math.abs(n-t)-Math.abs(r-i))<1e-6?`R ${e}`:`Rx ${e} × Ry ${a}`}}return{x:o,y:s,on45:!1,text:`${a} × ${l} · ${Vn($r(Math.abs(n-t),this._cellCm,this._gridPitch)*$r(Math.abs(r-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const e=this._drag.id.slice(3),t=this._spaceModel()?.rooms.find(t=>t.id===e);return t?(()=>{const e=this._labelPos(t,this._space);return[e.x,e.y]})():null}return null}if("devices"===this._mode&&this._deviceDrag?.moved){const e=this._devices.find(e=>e.id===this._deviceDrag.id);return e?(()=>{const t=this._pos(e);return[t.x,t.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const e=this._decorList.find(e=>e.id===this._decorMove.id);if(!e)return null;const t=Tf,i=this._decorH;return"line"===e.kind?[e.x1*t,e.y1*i]:[e.x*t,e.y*i]}return null}return null}_alignCandidates(){return this._editorRuntimeOrThrow()._alignCandidates()}_renderAlignGuides(){return this._editorRuntimeOrThrow()._renderAlignGuides()}_renderOpeningCenterTick(e){return this._editorRuntimeOrThrow()._renderOpeningCenterTick(e)}_renderOpeningDimensionGuides(e){return this._editorRuntimeOrThrow()._renderOpeningDimensionGuides(e)}_roomCenter(e){if(e.poly){const t=e.poly.length;return[e.poly.reduce((e,t)=>e+t[0],0)/t,e.poly.reduce((e,t)=>e+t[1],0)/t]}return[e.x+e.w/2,e.y+.1*Math.min(e.w,e.h)]}_openingAmt(e){const t=e.contact&&this._renderOpeningEntityAvailable(e.contact)?this._renderPlanHass.states[e.contact]:null;return si(e.type,t?.state,!!e.invert,t?.attributes?.current_position)}_planEntityAvailable(e){return!!e&&(!Td(this._fullRegistryHass,e,Cd(this._markers))&&"active"===this._bindingStatus("entity:"+e).kind)}_renderEntityAvailable(e){return!!e&&(!Td(this._renderPlanHass,e,Cd(this._markers))&&(!!this._renderPlanHass.entities?.[e]&&!!this._renderPlanHass.states?.[e]))}_openingEntityAvailable(e){return function(e,t,i=zh(e)){return!!t&&"active"===qh(e,`entity:${t}`,i).kind}(this.hass,e,this._haRegistry)}_renderOpeningEntityAvailable(e){return t=this._renderPlanHass,!!(i=e)&&!!t?.states?.[i];var t,i}_renderOpeningPlacementPreview(){return this._editorRuntimeOrThrow()._renderOpeningPlacementPreview()}_renderOpenings(e,t){const i=t?this._openingsR.filter(e=>t.includes(e.id)):this._openingsR;if(!i.length)return W``;const n=this._spaceModel();if(!n)return W``;const r=e.color,o=this._spaceWalls,s=this._openCuts(),a=this._openingWallIndexFor(n,s).value;return W`${i.map(e=>{if(e.orphanReason)return W`{t.stopPropagation(),this._editOpening(e)}}> ! - `;const t=this._openingAmt(e),i=t>0&&!!e.contact&&this._renderOpeningEntityAvailable(e.contact)?"var(--hp-open)":r,n="gate"===e.type?!e.flip_v:e.flip_v,s=e.partitionHost||o.length||"gate"===e.type?this._openingFace(e,a,!!n):{ox:0,oy:0,cm:0,side:-1},l={type:e.type,length:e.rlen,angle:e.angle,amount:t,flipH:!!e.flip_h,flipV:!!e.flip_v,base:r,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s},{half:c,outlineHalf:h,hitHalf:d}=Wu(l),u=Ia(10,this._cellCm),p=Ia(12,this._cellCm);return j``;const t=this._openingAmt(e),i=t>0&&!!e.contact&&this._renderOpeningEntityAvailable(e.contact)?"var(--hp-open)":r,n="gate"===e.type?!e.flip_v:e.flip_v,s=e.partitionHost||o.length||"gate"===e.type?this._openingFace(e,a,!!n):{ox:0,oy:0,cm:0,side:-1},l={type:e.type,length:e.rlen,angle:e.angle,amount:t,flipH:!!e.flip_h,flipV:!!e.flip_v,base:r,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s},{half:c,outlineHalf:h,hitHalf:d}=Ku(l),u=Ia(10,this._cellCm),p=Ia(12,this._cellCm);return W` - ${Ku(l)} + ${Qu(l)} @@ -5794,7 +5794,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e @pointermove=${t=>this._opPointerMove(t,e)} @pointerup=${t=>this._opPointerUp(t,e)} @pointercancel=${t=>this._opPointerUp(t,e)}> - `})}`}_renderOpeningLocks(e,t){const i=this._openingsR.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&e.lock&&this._renderOpeningEntityAvailable(e.lock));if(!i.length)return W``;const n=this._spaceModel();if(!n)return W``;const r=this._openCuts(),o=this._openingWallIndexFor(n,r).value;return W`${i.map(i=>{const n=this._renderPlanHass.states[i.lock]?.state,r="locked"===n,s=r||["unlocked","open","opening","unlocking","locking"].includes(String(n)),a="gate"===i.type?this._openingFace(i,o,!i.flip_v):null,l=qu({x:i.rx,y:i.ry,angle:i.angle,flipV:!!i.flip_v,gateFace:a},this._cellCm)[0],c=t?.get(String(i.id)),h=c?.visualScene??this._scenePoint(l),d=(h[0]-e.x)/e.w*100,u=(h[1]-e.y)/e.h*100;return W`
    `})}`}_renderOpeningLocks(e,t){const i=this._openingsR.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&e.lock&&this._renderOpeningEntityAvailable(e.lock));if(!i.length)return j``;const n=this._spaceModel();if(!n)return j``;const r=this._openCuts(),o=this._openingWallIndexFor(n,r).value;return j`${i.map(i=>{const n=this._renderPlanHass.states[i.lock]?.state,r="locked"===n,s=r||["unlocked","open","opening","unlocking","locking"].includes(String(n)),a="gate"===i.type?this._openingFace(i,o,!i.flip_v):null,l=Gu({x:i.rx,y:i.ry,angle:i.angle,flipV:!!i.flip_v,gateFace:a},this._cellCm)[0],c=t?.get(String(i.id)),h=c?.visualScene??this._scenePoint(l),d=(h[0]-e.x)/e.w*100,u=(h[1]-e.y)/e.h*100;return j`
    -
    `})}`}async _lockAction(e,t){if(this._openingEntityAvailable(e)){if("unlock"===t){const t=this.hass?.states?.[e]?.attributes?.friendly_name||e,i=await this._confirmDanger({key:"unlock",kind:"warning",title:this._t("confirm.unlock_title"),message:this._t("confirm.unlock_body"),objectName:t,confirmLabel:this._t("opening.unlock_action"),cancelLabel:this._t("btn.cancel")}),n=this._openingInfo;if(!i||!this._openingEntityAvailable(e)||!n||"door"!==n.type&&"gate"!==n.type||n.lock!==e||"locked"!==this.hass?.states?.[e]?.state)return}this.hass?.callService?.("lock",t,{entity_id:e})}}_renderOpeningInfoCard(){const e=this._openingInfo,t="passage"!==e.type&&e.contact&&this._openingEntityAvailable(e.contact)?e.contact:null,i=("door"===e.type||"gate"===e.type)&&e.lock&&this._openingEntityAvailable(e.lock)?e.lock:null,n=t?this.hass.states[t]?.state:null,r=this._openingAmt(e),o=i?this.hass.states[i]?.state:null,s="door"===e.type?"opening.door":"gate"===e.type?"opening.gate":"passage"===e.type?"opening.passage":"opening.window",a="door"===e.type?"mdi:door":"gate"===e.type?"mdi:gate":"passage"===e.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===e.type?r>0?"mdi:gate-open":"mdi:gate":r>0?"mdi:door-open":"mdi:door-closed",c=(e,t,i,n="")=>W`
    ${t}${i}
    `;return W``})}`}async _lockAction(e,t){if(this._openingEntityAvailable(e)){if("unlock"===t){const t=this.hass?.states?.[e]?.attributes?.friendly_name||e,i=await this._confirmDanger({key:"unlock",kind:"warning",title:this._t("confirm.unlock_title"),message:this._t("confirm.unlock_body"),objectName:t,confirmLabel:this._t("opening.unlock_action"),cancelLabel:this._t("btn.cancel")}),n=this._openingInfo;if(!i||!this._openingEntityAvailable(e)||!n||"door"!==n.type&&"gate"!==n.type||n.lock!==e||"locked"!==this.hass?.states?.[e]?.state)return}this.hass?.callService?.("lock",t,{entity_id:e})}}_renderOpeningInfoCard(){const e=this._openingInfo,t="passage"!==e.type&&e.contact&&this._openingEntityAvailable(e.contact)?e.contact:null,i=("door"===e.type||"gate"===e.type)&&e.lock&&this._openingEntityAvailable(e.lock)?e.lock:null,n=t?this.hass.states[t]?.state:null,r=this._openingAmt(e),o=i?this.hass.states[i]?.state:null,s="door"===e.type?"opening.door":"gate"===e.type?"opening.gate":"passage"===e.type?"opening.passage":"opening.window",a="door"===e.type?"mdi:door":"gate"===e.type?"mdi:gate":"passage"===e.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===e.type?r>0?"mdi:gate-open":"mdi:gate":r>0?"mdi:door-open":"mdi:door-closed",c=(e,t,i,n="")=>j`
    ${t}${i}
    `;return j`this._openingInfo=null}>
    ${t?c(l,this._t("opening.contact_label"),"unavailable"===n||null==n?this._t("opening.state_unknown"):this._t(r>0?"opening.open":"opening.closed"),r>0?"warn":"ok"):V} ${i?c("locked"===o?"mdi:lock":"mdi:lock-open-variant",this._t("opening.lock_label"),"locked"===o?this._t("opening.locked"):["unlocked","open"].includes(String(o))?this._t("opening.unlocked"):this._t("opening.state_unknown"),"locked"===o?"ok":"warn"):V} - ${i&&("locked"===o||["unlocked","open"].includes(String(o)))?W``:i&&["locking","unlocking"].includes(String(o))?W``:i&&["locking","unlocking"].includes(String(o))?j``:V} - ${t||i?V:W`

    ${this._t("opening.no_entities")}

    `} + ${t||i?V:j`

    ${this._t("opening.no_entities")}

    `}
    -
    `}_renderOpeningDialog(){return this._editorRuntimeOrThrow()._renderOpeningDialog()}_gridLevels(){return this._editorRuntimeOrThrow()._gridLevels()}_renderMarkupDefs(e){return this._editorRuntimeOrThrow()._renderMarkupDefs(e)}_renderPhysicalEditorLayer(){return this._editorRuntimeOrThrow()._renderPhysicalEditorLayer()}_renderHiddenWallDiagnosticOverlay(){return this._editorRuntimeOrThrow()._renderHiddenWallDiagnosticOverlay()}_renderPlanSnapOverlay(){return this._editorRuntimeOrThrow()._renderPlanSnapOverlay()}_syncPlanSnapActiveMarker(e){return this._editorRuntimeOrThrow()._syncPlanSnapActiveMarker(e)}_syncPlanSnapConflictMarkers(e){return this._editorRuntimeOrThrow()._syncPlanSnapConflictMarkers(e)}_planSnapPhysicalSegment(e){return this._editorRuntimeOrThrow()._planSnapPhysicalSegment(e)}_drawPreviewJoinPatchD(e,t){return this._editorRuntimeOrThrow()._drawPreviewJoinPatchD(e,t)}_renderMarkupLayer(e){return this._editorRuntimeOrThrow()._renderMarkupLayer(e)}_renderActiveChainInk(){return this._editorRuntimeOrThrow()._renderActiveChainInk()}_renderPartitionDeleteDialog(){return this._editorRuntimeOrThrow()._renderPartitionDeleteDialog()}_renderRoomDeleteDialog(){return this._editorRuntimeOrThrow()._renderRoomDeleteDialog()}_renderPhysicalDialog(){return this._editorRuntimeOrThrow()._renderPhysicalDialog()}_renderMarkupBar(){return this._editorRuntimeOrThrow()._renderMarkupBar()}_renderDevicesBar(){return this._editorRuntimeOrThrow()._renderDevicesBar()}_renderDeviceInbox(){return this._editorRuntimeOrThrow()._renderDeviceInbox()}_cardEntities(e){const t=this._planHass,i=[],n=new Set,r=e=>{if(!e||n.has(e)||!t.states[e])return;const r=t.entities[e];if("config"===r?.entity_category||"diagnostic"===r?.entity_category)return;n.add(e);const o=e.split(".")[0];["light","switch","fan","humidifier","siren","input_boolean"].includes(o)?i.push({eid:e,kind:"toggle"}):["cover","valve","lock","climate","media_player","vacuum","water_heater"].includes(o)?i.push({eid:e,kind:"open"}):["sensor","binary_sensor","number","select"].includes(o)&&i.push({eid:e,kind:"value"})};for(const i of cd(t,this._devices,null,this._virtualLights))if(i.device.id===e.id)for(const e of[...i.serviceEids,...i.stateEids])r(e);e.primary&&r(e.primary);for(const t of e.entities)r(t);return i.slice(0,12)}_cardToggle(e){const t=e.split(".")[0];"lock"!==t&&"alarm_control_panel"!==t&&this._planEntityAvailable(e)&&this.hass.callService("homeassistant","toggle",{entity_id:e}).catch(e=>this._showToast(this._t("toast.error",{err:this._errText(e)})))}_renderInfoCard(){const e=this._infoCard,t=e.primary?this.hass.states[e.primary]:void 0,i=t?Gi(this.hass,e.primary)?.text??t.state:null,n=(e.controls??e.marker?.controls??[]).filter(Mn).filter(e=>this._planEntityAvailable(e));return W``}_renderOpeningDialog(){return this._editorRuntimeOrThrow()._renderOpeningDialog()}_gridLevels(){return this._editorRuntimeOrThrow()._gridLevels()}_renderMarkupDefs(e){return this._editorRuntimeOrThrow()._renderMarkupDefs(e)}_renderPhysicalEditorLayer(){return this._editorRuntimeOrThrow()._renderPhysicalEditorLayer()}_renderHiddenWallDiagnosticOverlay(){return this._editorRuntimeOrThrow()._renderHiddenWallDiagnosticOverlay()}_renderPlanSnapOverlay(){return this._editorRuntimeOrThrow()._renderPlanSnapOverlay()}_syncPlanSnapActiveMarker(e){return this._editorRuntimeOrThrow()._syncPlanSnapActiveMarker(e)}_syncPlanSnapConflictMarkers(e){return this._editorRuntimeOrThrow()._syncPlanSnapConflictMarkers(e)}_planSnapPhysicalSegment(e){return this._editorRuntimeOrThrow()._planSnapPhysicalSegment(e)}_drawPreviewJoinPatchD(e,t){return this._editorRuntimeOrThrow()._drawPreviewJoinPatchD(e,t)}_renderMarkupLayer(e){return this._editorRuntimeOrThrow()._renderMarkupLayer(e)}_renderActiveChainInk(){return this._editorRuntimeOrThrow()._renderActiveChainInk()}_renderPartitionDeleteDialog(){return this._editorRuntimeOrThrow()._renderPartitionDeleteDialog()}_renderRoomDeleteDialog(){return this._editorRuntimeOrThrow()._renderRoomDeleteDialog()}_renderPhysicalDialog(){return this._editorRuntimeOrThrow()._renderPhysicalDialog()}_renderMarkupBar(){return this._editorRuntimeOrThrow()._renderMarkupBar()}_renderDevicesBar(){return this._editorRuntimeOrThrow()._renderDevicesBar()}_renderDeviceInbox(){return this._editorRuntimeOrThrow()._renderDeviceInbox()}_cardEntities(e){const t=this._planHass,i=[],n=new Set,r=e=>{if(!e||n.has(e)||!t.states[e])return;const r=t.entities[e];if("config"===r?.entity_category||"diagnostic"===r?.entity_category)return;n.add(e);const o=e.split(".")[0];["light","switch","fan","humidifier","siren","input_boolean"].includes(o)?i.push({eid:e,kind:"toggle"}):["cover","valve","lock","climate","media_player","vacuum","water_heater"].includes(o)?i.push({eid:e,kind:"open"}):["sensor","binary_sensor","number","select"].includes(o)&&i.push({eid:e,kind:"value"})};for(const i of _d(t,this._devices,null,this._virtualLights))if(i.device.id===e.id)for(const e of[...i.serviceEids,...i.stateEids])r(e);e.primary&&r(e.primary);for(const t of e.entities)r(t);return i.slice(0,12)}_cardToggle(e){const t=e.split(".")[0];"lock"!==t&&"alarm_control_panel"!==t&&this._planEntityAvailable(e)&&this.hass.callService("homeassistant","toggle",{entity_id:e}).catch(e=>this._showToast(this._t("toast.error",{err:this._errText(e)})))}_renderInfoCard(){const e=this._infoCard,t=e.primary?this.hass.states[e.primary]:void 0,i=t?Gi(this.hass,e.primary)?.text??t.state:null,n=(e.controls??e.marker?.controls??[]).filter(Mn).filter(e=>this._planEntityAvailable(e));return j`
    - ${(()=>{const t=this._cardEntities(e);return t.length?W`
    - ${t.map(({eid:e,kind:t})=>{const i=this.hass.states[e],n=this.hass.entities[e]?.name||i?.attributes?.friendly_name||e,r=i?Gi(this.hass,e)?.text??i.state:"",o="on"===i?.state||["open","unlocked","playing","cleaning"].includes(i?.state);return W`
    - + ${(()=>{const t=this._cardEntities(e);return t.length?j`
    + ${t.map(({eid:e,kind:t})=>{const i=this.hass.states[e],n=this.hass.entities[e]?.name||i?.attributes?.friendly_name||e,r=i?Gi(this.hass,e)?.text??i.state:"",o="on"===i?.state||["open","unlocked","playing","cleaning"].includes(i?.state);return j`
    + ${n} - ${"toggle"===t?W``:"open"===t?W``:W`${r}`} + ${"toggle"===t?j``:"open"===t?j``:j`${r}`}
    `})}
    `:V})()} - ${e.model?W`
    ${this._t("info.model")}${e.model}
    `:V} - ${i&&!this._cardEntities(e).length?W`
    ${this._t("info.state")}${i}
    `:V} - ${Ii(e.link)?W`
    ${this._t("info.link")} + ${e.model?j`
    ${this._t("info.model")}${e.model}
    `:V} + ${i&&!this._cardEntities(e).length?j`
    ${this._t("info.state")}${i}
    `:V} + ${Ii(e.link)?j`
    ${this._t("info.link")} ${e.link}
    `:V} - ${e.description?W`
    ${e.description}
    `:V} - ${e.pdfs&&e.pdfs.length?W`
    ${this._t("info.manuals")} - ${e.pdfs.map(e=>W` + ${e.description?j`
    ${e.description}
    `:V} + ${e.pdfs&&e.pdfs.length?j`
    `:V} - ${n.length?W`
    ${this._t("info.controls")} + ${n.length?j`
    ${this._t("info.controls")} - ${n.map(e=>{const t=this.hass.states[e],i="on"===t?.state;return W` + ${n.map(e=>{const t=this.hass.states[e],i="on"===t?.state;return j` ${t?.attributes?.friendly_name||e}`})}
    `:V} - ${e.model||i||e.link||e.description||e.pdfs&&e.pdfs.length||n.length?V:W`
    ${this._t("info.none")}
    `} + ${e.model||i||e.link||e.description||e.pdfs&&e.pdfs.length||n.length?V:j`
    ${this._t("info.none")}
    `}
    - ${e.primary?W``:V}
    - `}_markerValueBadgeFields(e){return this._editorRuntimeOrThrow()._markerValueBadgeFields(e)}_markerDraft(e){return this._editorRuntimeOrThrow()._markerDraft(e)}_markerPreviewDevice(e){return this._editorRuntimeOrThrow()._markerPreviewDevice(e)}_markerPreviewDevices(e){return this._editorRuntimeOrThrow()._markerPreviewDevices(e)}_toggleIntent(e,t=this._devices){return ou({hass:this._planHass,registryHass:this._fullRegistryHass,devices:t,device:e,virtualLights:this._virtualLights})}_toggleIntentForDialog(e){return this._editorRuntimeOrThrow()._toggleIntentForDialog(e)}_toggleStateText(e,t){const i=this._planHass?.states?.[e]||this.hass?.states?.[e];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):t}catch{return t}}_toggleConfirmationStateText(e){const t=String(e.state||"unknown"),i=e.entityId?this._toggleStateText(e.entityId,t):t;if(i.trim().toLocaleLowerCase()!==t.trim().toLocaleLowerCase())return i;const n={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[t];return n?this._t(n):t.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(e){const t={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(e,t){if(!au(e)||!e.nextEffect||!e.targets.length)return[];const i="group"===e.kind,n=i?e.targets.filter(e=>"on"===e.state).length:0,r=i?0===n?t.groupAllOff():t.groupCurrent(n,e.targets.length):t.state(e.targets[0]);let o;return o="toggle"===e.nextEffect?t.expectedByHa():i&&"turn-on"===e.nextEffect?t.groupAllOn():i&&"turn-off"===e.nextEffect?t.groupAllOff():t.effect(e.nextEffect),[t.current(r),t.expected(o),...e.skippedTargets.length?[t.unavailable(e.skippedTargets.length)]:[]]}(e,{state:e=>this._toggleConfirmationStateText(e),current:e=>this._t("confirm.current_state",{state:e}),expected:e=>this._t("confirm.expected_state",{state:e}),groupCurrent:(e,t)=>this._t("confirm.group_current",{on:e,total:t}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:e=>this._t("confirm.unavailable_targets",{count:e}),effect:e=>this._t(t[e]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(e){return this._editorRuntimeOrThrow()._toggleHintLines(e)}_effectiveStoredTapAction(e,t){return this._editorRuntimeOrThrow()._effectiveStoredTapAction(e,t)}_effectiveMarkerTapAction(e,t=this._markerPreviewDevice(e)){return this._editorRuntimeOrThrow()._effectiveMarkerTapAction(e,t)}_announceToggleDraft(e){return this._editorRuntimeOrThrow()._announceToggleDraft(e)}_valueBadgeForBinding(e,t){return this._editorRuntimeOrThrow()._valueBadgeForBinding(e,t)}_markerSpatialSource(e){return this._editorRuntimeOrThrow()._markerSpatialSource(e)}_markerAutoHasSpatialSource(e){return this._editorRuntimeOrThrow()._markerAutoHasSpatialSource(e)}_setMarkerLightRole(e){return this._editorRuntimeOrThrow()._setMarkerLightRole(e)}_controlRefInfo(e){return this._editorRuntimeOrThrow()._controlRefInfo(e)}_valueBadgeCandidateLabel(e){return this._editorRuntimeOrThrow()._valueBadgeCandidateLabel(e)}_controlCandidates(e){return this._editorRuntimeOrThrow()._controlCandidates(e)}_addControlRef(e,t){return this._editorRuntimeOrThrow()._addControlRef(e,t)}_setMarkerGlowMode(e){return this._editorRuntimeOrThrow()._setMarkerGlowMode(e)}_renderMarkerDialog(){return this._editorRuntimeOrThrow()._renderMarkerDialog()}_renderSpaceDialog(){return this._onboardingRuntime&&this._spaceDialog&&this._spaceDialogUsesOnboardingRuntime(this._spaceDialog.mode)?this._onboardingRuntime._renderSpaceDialog():this._editorRuntimeOrThrow()._renderSpaceDialog()}_renderMergeDialog(){return this._editorRuntimeOrThrow()._renderMergeDialog()}_renderCardPreview(e,t,i){const n=18*e;return W`
    + `}_markerValueBadgeFields(e){return this._editorRuntimeOrThrow()._markerValueBadgeFields(e)}_markerDraft(e){return this._editorRuntimeOrThrow()._markerDraft(e)}_markerPreviewDevice(e){return this._editorRuntimeOrThrow()._markerPreviewDevice(e)}_markerPreviewDevices(e){return this._editorRuntimeOrThrow()._markerPreviewDevices(e)}_toggleIntent(e,t=this._devices){return hu({hass:this._planHass,registryHass:this._fullRegistryHass,devices:t,device:e,virtualLights:this._virtualLights})}_toggleIntentForDialog(e){return this._editorRuntimeOrThrow()._toggleIntentForDialog(e)}_toggleStateText(e,t){const i=this._planHass?.states?.[e]||this.hass?.states?.[e];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):t}catch{return t}}_toggleConfirmationStateText(e){const t=String(e.state||"unknown"),i=e.entityId?this._toggleStateText(e.entityId,t):t;if(i.trim().toLocaleLowerCase()!==t.trim().toLocaleLowerCase())return i;const n={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[t];return n?this._t(n):t.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(e){const t={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(e,t){if(!uu(e)||!e.nextEffect||!e.targets.length)return[];const i="group"===e.kind,n=i?e.targets.filter(e=>"on"===e.state).length:0,r=i?0===n?t.groupAllOff():t.groupCurrent(n,e.targets.length):t.state(e.targets[0]);let o;return o="toggle"===e.nextEffect?t.expectedByHa():i&&"turn-on"===e.nextEffect?t.groupAllOn():i&&"turn-off"===e.nextEffect?t.groupAllOff():t.effect(e.nextEffect),[t.current(r),t.expected(o),...e.skippedTargets.length?[t.unavailable(e.skippedTargets.length)]:[]]}(e,{state:e=>this._toggleConfirmationStateText(e),current:e=>this._t("confirm.current_state",{state:e}),expected:e=>this._t("confirm.expected_state",{state:e}),groupCurrent:(e,t)=>this._t("confirm.group_current",{on:e,total:t}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:e=>this._t("confirm.unavailable_targets",{count:e}),effect:e=>this._t(t[e]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(e){return this._editorRuntimeOrThrow()._toggleHintLines(e)}_effectiveStoredTapAction(e,t){return this._editorRuntimeOrThrow()._effectiveStoredTapAction(e,t)}_effectiveMarkerTapAction(e,t=this._markerPreviewDevice(e)){return this._editorRuntimeOrThrow()._effectiveMarkerTapAction(e,t)}_announceToggleDraft(e){return this._editorRuntimeOrThrow()._announceToggleDraft(e)}_valueBadgeForBinding(e,t){return this._editorRuntimeOrThrow()._valueBadgeForBinding(e,t)}_markerSpatialSource(e){return this._editorRuntimeOrThrow()._markerSpatialSource(e)}_markerAutoHasSpatialSource(e){return this._editorRuntimeOrThrow()._markerAutoHasSpatialSource(e)}_setMarkerLightRole(e){return this._editorRuntimeOrThrow()._setMarkerLightRole(e)}_controlRefInfo(e){return this._editorRuntimeOrThrow()._controlRefInfo(e)}_valueBadgeCandidateLabel(e){return this._editorRuntimeOrThrow()._valueBadgeCandidateLabel(e)}_controlCandidates(e){return this._editorRuntimeOrThrow()._controlCandidates(e)}_addControlRef(e,t){return this._editorRuntimeOrThrow()._addControlRef(e,t)}_setMarkerGlowMode(e){return this._editorRuntimeOrThrow()._setMarkerGlowMode(e)}_renderMarkerDialog(){return this._editorRuntimeOrThrow()._renderMarkerDialog()}_renderSpaceDialog(){return this._onboardingRuntime&&this._spaceDialog&&this._spaceDialogUsesOnboardingRuntime(this._spaceDialog.mode)?this._onboardingRuntime._renderSpaceDialog():this._editorRuntimeOrThrow()._renderSpaceDialog()}_renderMergeDialog(){return this._editorRuntimeOrThrow()._renderMergeDialog()}_renderCardPreview(e,t,i){const n=18*e;return j`
    ${this._t("preview.room_name")} @@ -5872,4 +5872,4 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e 45% · ${this._t("roomcard.light_partial",{on:1,total:3})} -
    `}_renderRoomSource(e){return this._editorRuntimeOrThrow()._renderRoomSource(e)}_renderRoomDialog(){return this._editorRuntimeOrThrow()._renderRoomDialog()}}zf.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_editorRuntimeLoadingVisible:{state:!0},_backdropGuard:{state:!0},_tapConfirm:{state:!0},_dangerConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_decorImagePalette:{state:!0},_decorAssetCatalog:{state:!0},_decorAssetBusy:{state:!0},_furnCategory:{state:!0},_furnPreviewInput:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_deviceInbox:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_supportDialog:{state:!0},_alignDialog:{state:!0},_preflightClipboardFallback:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0}},zf.ZOOM_MAX=8,zf.ZOOM_MIN=1/3,zf.styles=[xu,zm],customElements.get("houseplan-card")||customElements.define("houseplan-card",zf),window.customCards=window.customCards||[],window.customCards.find(e=>"houseplan-card"===e.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${df} `,"background:#3ea6ff;color:#04121f;font-weight:700","");export{Il as $,V as A,Ip as B,Xu as C,le as D,Ep as E,Vm as F,vi as G,Or as H,ki as I,xi as J,qt as K,$i as L,Xa as M,Na as N,di as O,vo as P,ei as Q,Po as R,Wp as S,jp as T,gs as U,Qr as V,Wo as W,Bo as X,n_ as Y,Hl as Z,el as _,Pm as a,Ro as a$,Al as a0,$s as a1,ls as a2,Ss as a3,Ks as a4,As as a5,ni as a6,Ka as a7,_u as a8,ku as a9,Cn as aA,Bn as aB,R_ as aC,Sr as aD,$_ as aE,Sl as aF,Dl as aG,jl as aH,Va as aI,Ul as aJ,ps as aK,Zs as aL,Zo as aM,la as aN,Aa as aO,t_ as aP,ha as aQ,Rs as aR,Gm as aS,hn as aT,_r as aU,pr as aV,ur as aW,cn as aX,Pe as aY,Lu as aZ,yg as a_,Ms as aa,yo as ab,bu as ac,uu as ad,Ko as ae,Cs as af,mu as ag,ea as ah,na as ai,_o as aj,go as ak,Yr as al,Qp as am,Uo as an,Ya as ao,qo as ap,Ba as aq,qa as ar,Zi as as,Ji as at,Ui as au,Vi as av,Ua as aw,xd as ax,Sd as ay,ii as az,W as b,mi as b$,Qa as b0,Xt as b1,Zt as b2,Er as b3,da as b4,ic as b5,e_ as b6,fo as b7,Am as b8,gi as b9,Nn as bA,br as bB,kr as bC,Bl as bD,zr as bE,ql as bF,Ol as bG,zl as bH,Wl as bI,Nl as bJ,Ll as bK,b_ as bL,Yo as bM,Wu as bN,yu as bO,af as bP,vu as bQ,ra as bR,tf as bS,lf as bT,Up as bU,oi as bV,gu as bW,wu as bX,Ri as bY,_i as bZ,ri as b_,ui as ba,Di as bb,Da as bc,fa as bd,ga as be,Vo as bf,Go as bg,Xs as bh,Jt as bi,vl as bj,Ra as bk,Ma as bl,Un as bm,Vn as bn,yi as bo,us as bp,ds as bq,o_ as br,s_ as bs,Dr as bt,Fr as bu,Pr as bv,$r as bw,wr as bx,xr as by,Cr as bz,Jl as c,cd as c$,Xo as c0,zi as c1,kn as c2,lp as c3,cp as c4,Yh as c5,tu as c6,Ei as c7,qi as c8,jn as c9,mc as cA,bc as cB,Tc as cC,lc as cD,wc as cE,gc as cF,fc as cG,Cc as cH,$c as cI,rc as cJ,En as cK,Hn as cL,si as cM,nf as cN,Ku as cO,ef as cP,bl as cQ,Ts as cR,ns as cS,rs as cT,Ae as cU,Fd as cV,hp as cW,dp as cX,Td as cY,hu as cZ,hd as c_,On as ca,bd as cb,__ as cc,mo as cd,kd as ce,yd as cf,ln as cg,sn as ch,on as ci,Ea as cj,Xp as ck,rn as cl,nn as cm,tn as cn,en as co,Oa as cp,h_ as cq,r_ as cr,Rr as cs,dn as ct,Km as cu,no as cv,mr as cw,Fe as cx,Ne as cy,Ie as cz,Fm as d,od as d0,Zh as d1,Mn as d2,Kh as d3,wd as d4,xn as d5,Cp as d6,Ju as d7,sd as d8,ad as d9,Si as dA,Fp as dB,Og as dC,Eg as dD,xg as dE,Op as dF,Fa as dG,pe as dH,_e as dI,U as dJ,Eu as dK,Ru as dL,Au as dM,Cu as dN,Yt as dO,zf as dP,Jh as da,Xd as db,Hi as dc,Oi as dd,Qu as de,Ii as df,Ha as dg,Ni as dh,Li as di,bo as dj,hi as dk,Md as dl,Cd as dm,Ga as dn,nc as dp,pg as dq,_g as dr,Bu as ds,gg as dt,fl as du,mg as dv,fg as dw,wa as dx,js as dy,qu as dz,Pc as e,Mc as f,Js as g,xo as h,Rc as i,$o as j,So as k,Hu as l,Ia as m,zc as n,Oc as o,Co as p,o as q,Ic as r,Qi as s,he as t,Ut as u,xu as v,j as w,Nu as x,pp as y,Pp as z}; +
    `}_renderRoomSource(e){return this._editorRuntimeOrThrow()._renderRoomSource(e)}_renderRoomDialog(){return this._editorRuntimeOrThrow()._renderRoomDialog()}}Of.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_editorRuntimeLoadingVisible:{state:!0},_backdropGuard:{state:!0},_tapConfirm:{state:!0},_dangerConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_decorImagePalette:{state:!0},_decorAssetCatalog:{state:!0},_decorAssetBusy:{state:!0},_furnCategory:{state:!0},_furnPreviewInput:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_deviceInbox:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_supportDialog:{state:!0},_alignDialog:{state:!0},_preflightClipboardFallback:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0}},Of.ZOOM_MAX=8,Of.ZOOM_MIN=1/3,Of.styles=[Cu,Om],customElements.get("houseplan-card")||customElements.define("houseplan-card",Of),window.customCards=window.customCards||[],window.customCards.find(e=>"houseplan-card"===e.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${gf} `,"background:#3ea6ff;color:#04121f;font-weight:700","");export{Ll as $,V as A,Lp as B,tp as C,le as D,qp as E,Zm as F,vi as G,Or as H,ki as I,xi as J,qt as K,$i as L,Xa as M,Ha as N,di as O,vo as P,ei as Q,Fo as R,Kp as S,Yp as T,gs as U,Qr as V,jo as W,Bo as X,l_ as Y,Fl as Z,el as _,Nm as a,Sg as a$,El as a0,$s as a1,ls as a2,Ss as a3,Ks as a4,Ps as a5,ni as a6,Ka as a7,yu as a8,Ru as a9,Cn as aA,Bn as aB,P_ as aC,Sr as aD,D_ as aE,Cl as aF,Il as aG,Yl as aH,Va as aI,Xl as aJ,jl as aK,ps as aL,Zs as aM,Zo as aN,la as aO,Pa as aP,s_ as aQ,ha as aR,Rs as aS,Jm as aT,hn as aU,_r as aV,pr as aW,ur as aX,cn as aY,Fe as aZ,Uu as a_,Ms as aa,yo as ab,$u as ac,fu as ad,Ko as ae,Cs as af,bu as ag,ea as ah,na as ai,_o as aj,go as ak,Yr as al,r_ as am,Uo as an,Ya as ao,qo as ap,Ba as aq,qa as ar,Zi as as,Ji as at,Ui as au,Vi as av,Ua as aw,Cd as ax,Td as ay,ii as az,j as b,ri as b$,Ro as b0,Qa as b1,Xt as b2,Zt as b3,Er as b4,da as b5,ac as b6,o_ as b7,fo as b8,Em as b9,Cr as bA,Hn as bB,br as bC,kr as bD,Vl as bE,Ar as bF,Gl as bG,Bl as bH,Ol as bI,Kl as bJ,Wl as bK,Ul as bL,$_ as bM,Yo as bN,Ku as bO,Su as bP,uf as bQ,xu as bR,ra as bS,af as bT,pf as bU,Xp as bV,oi as bW,wu as bX,Mu as bY,Ri as bZ,_i as b_,gi as ba,ui as bb,Di as bc,Da as bd,fa as be,ga as bf,Vo as bg,Go as bh,Xs as bi,Jt as bj,vl as bk,Ra as bl,Ma as bm,Un as bn,Vn as bo,yi as bp,us as bq,ds as br,h_ as bs,d_ as bt,Dr as bu,zr as bv,Fr as bw,$r as bx,wr as by,xr as bz,nc as c,md as c$,mi as c0,Xo as c1,Ai as c2,kn as c3,pp as c4,_p as c5,ed as c6,su as c7,Ei as c8,qi as c9,Ie as cA,bc as cB,$c as cC,zc as cD,pc as cE,Mc as cF,wc as cG,kc as cH,Fc as cI,Dc as cJ,cc as cK,En as cL,Nn as cM,si as cN,lf as cO,Qu as cP,sf as cQ,bl as cR,Ts as cS,ns as cT,rs as cU,Pe as cV,Hd as cW,mp as cX,gp as cY,zd as cZ,mu as c_,Wn as ca,On as cb,$d as cc,y_ as cd,mo as ce,Rd as cf,Sd as cg,ln as ch,sn as ci,on as cj,Ea as ck,t_ as cl,rn as cm,nn as cn,tn as co,en as cp,Oa as cq,m_ as cr,c_ as cs,Rr as ct,dn as cu,Qm as cv,no as cw,mr as cx,ze as cy,He as cz,Hm as d,_d as d0,hd as d1,id as d2,Mn as d3,Qh as d4,Md as d5,xn as d6,Fp as d7,np as d8,dd as d9,Ws as dA,Gu as dB,Si as dC,Hp as dD,Bg as dE,qg as dF,Cg as dG,Bp as dH,za as dI,pe as dJ,_e as dK,U as dL,qu as dM,Pu as dN,Eu as dO,Fu as dP,Yt as dQ,Of as dR,ud as da,nd as db,tu as dc,Ni as dd,Oi as de,rp as df,Ii as dg,Na as dh,Hi as di,Li as dj,bo as dk,hi as dl,Ad as dm,Fd as dn,Ga as dp,Rl as dq,lc as dr,vg as ds,yg as dt,Vu as du,wg as dv,fl as dw,bg as dx,kg as dy,wa as dz,Nc as e,Ac as f,Js as g,xo as h,Pc as i,$o as j,So as k,ju as l,Ia as m,Oc as n,Bc as o,Co as p,o as q,Lc as r,Qi as s,he as t,Ut as u,Cu as v,W as w,Wu as x,vp as y,Np as z}; diff --git a/dist/houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js b/dist/houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js similarity index 79% rename from dist/houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js rename to dist/houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js index f9f0ed84..1be3800c 100644 --- a/dist/houseplan-assets/houseplan-editor-runtime-Ak2xnYks.js +++ b/dist/houseplan-assets/houseplan-editor-runtime-BvuzmUE5.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{s as t,e,n as s,f as i,i as o,l as a,o as n,r,A as l,b as h,a as c,c as d,d as p,D as u,w as _,N as m,g,h as f,j as b,k as v,m as y,p as $,q as w,t as k,u as x,v as S,x as M,y as D,z as C,B as P,C as I,E as T,F as z,G as R,H as A,I as F,J as N,K as H,L,M as E,O,P as B,Q as W,R as G,S as j,T as q,U,V as K,W as V,X as J,Y,Z as X,_ as Z,$ as Q,a0 as tt,a1 as et,a2 as st,a3 as it,a4 as ot,a5 as at,a6 as nt,a7 as rt,a8 as lt,a9 as ht,aa as ct,ab as dt,ac as pt,ad as ut,ae as _t,af as mt,ag as gt,ah as ft,ai as bt,aj as vt,ak as yt,al as $t,am as wt,an as kt,ao as xt,ap as St,aq as Mt,ar as Dt,as as Ct,at as Pt,au as It,av as Tt,aw as zt,ax as Rt,ay as At,az as Ft,aA as Nt,aB as Ht,aC as Lt,aD as Et,aE as Ot,aF as Bt,aG as Wt,aH as Gt,aI as jt,aJ as qt,aK as Ut,aL as Kt,aM as Vt,aN as Jt,aO as Yt,aP as Xt,aQ as Zt,aR as Qt,aS as te,aT as ee,aU as se,aV as ie,aW as oe,aX as ae,aY as ne,aZ as re,a_ as le,a$ as he,b0 as ce,b1 as de,b2 as pe,b3 as ue,b4 as _e,b5 as me,b6 as ge,b7 as fe,b8 as be,b9 as ve,ba as ye,bb as $e,bc as we,bd as ke,be as xe,bf as Se,bg as Me,bh as De,bi as Ce,bj as Pe,bk as Ie,bl as Te,bm as ze,bn as Re,bo as Ae,bp as Fe,bq as Ne,br as He,bs as Le,bt as Ee,bu as Oe,bv as Be,bw as We,bx as Ge,by as je,bz as qe,bA as Ue,bB as Ke,bC as Ve,bD as Je,bE as Ye,bF as Xe,bG as Ze,bH as Qe,bI as ts,bJ as es,bK as ss,bL as is,bM as os,bN as as,bO as ns,bP as rs,bQ as ls,bR as hs,bS as cs,bT as ds,bU as ps,bV as us,bW as _s,bX as ms,bY as gs,bZ as fs,b_ as bs,b$ as vs,c0 as ys,c1 as $s,c2 as ws,c3 as ks,c4 as xs,c5 as Ss,c6 as Ms,c7 as Ds,c8 as Cs,c9 as Ps,ca as Is,cb as Ts,cc as zs,cd as Rs,ce as As,cf as Fs,cg as Ns,ch as Hs,ci as Ls,cj as Es,ck as Os,cl as Bs,cm as Ws,cn as Gs,co as js,cp as qs,cq as Us,cr as Ks,cs as Vs,ct as Js,cu as Ys,cv as Xs,cw as Zs,cx as Qs,cy as ti,cz as ei,cA as si,cB as ii,cC as oi,cD as ai,cE as ni,cF as ri,cG as li,cH as hi,cI as ci,cJ as di,cK as pi,cL as ui,cM as _i,cN as mi,cO as gi,cP as fi,cQ as bi,cR as vi,cS as yi,cT as $i,cU as wi,cV as ki,cW as xi,cX as Si,cY as Mi,cZ as Di,c_ as Ci,c$ as Pi,d0 as Ii,d1 as Ti,d2 as zi,d3 as Ri,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Hi,d8 as Li,d9 as Ei,da as Oi,db as Bi,dc as Wi,dd as Gi,de as ji,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji,dk as Yi,dl as Xi,dm as Zi,dn as Qi}from"./houseplan-card-CODdCIWj.js";import{i as to}from"./guard-BR4mAQsM.js";import{F as eo,f as so,p as io,c as oo,s as ao,i as no,e as ro,r as lo,a as ho,b as co,d as po,g as uo,t as _o}from"./backdrop-pick-BnsHKWaS.js";import{t as mo,h as go,m as fo,T as bo}from"./zigbee-topology-BUFPOnoy.js";var vo={"gs.hint":"Fill colors apply to every space; each color has its own opacity. Which fill mode a space uses is set in that space's dialog.","gs.show_room_tooltip":"Show the room information window on hover","support.about_group":"About the card","support.guide_group":"Documentation","support.guide":"User guide","support.form_group":"Send a report or suggestion","support.contact":"Contact details (email/tg/WhatsApp), optional.","support.message":"Message","support.attach":"Attach anonymized information from your plan","support.attach_hint":"Includes only allowed plan geometry, settings and bounded runtime facts. Excludes names, Home Assistant IDs, live states, URLs, files, and your message/contact.","support.geometry_warning":"The package contains no names or Home Assistant IDs, but it does contain the exact geometry and dimensions of your home.","support.close_busy_title":"Stop the current operation?","support.close_busy_body":"House Plan is preparing or sending the report. Closing now stops waiting for the result.","support.building":"Preparing anonymized data…","support.preview_summary":"Package v{version} · {spaces} spaces · {size} KiB","support.prepared":"Snapshot prepared {n} min ago","support.show_data":"Show data","support.download":"Download JSON","support.refresh":"Refresh snapshot","support.privacy":"When you send, your message, optional contact and, if selected, exact geometry leave your Home Assistant through the House Plan project relay and are visible to maintainers. The project node keeps the report for up to 30 days. Network infrastructure sees your HA server address, but House Plan does not retain it raw; rate-limit and idempotency metadata is kept for up to 24 hours.","support.error_title":"The report was not sent","support.manual_recovery":"You can keep the message and attachment and continue manually:","support.copy_message":"Copy message","support.success":"Report sent: {id}. Save this number when contacting support.","support.copy_id":"Copy ID","support.sending":"Sending…","support.retry":"Retry","support.send":"Send","support.update_required":"Update the House Plan card and integration to compatible versions to send reports.","support.message_copied":"Message copied","support.id_copied":"Report ID copied","support.copy_failed":"Could not access the clipboard. Select and copy the text manually.","support.validation.message_required":"Enter a message.","support.validation.message_too_long":"The message must contain no more than 10,000 characters.","support.validation.contact_too_long":"Contact details must contain no more than 320 characters.","support.validation.preview_missing":"Wait for the attachment preview or turn the attachment off.","support.validation.preview_expired":"The attachment preview expired. Refresh the snapshot.","support.error.support_invalid_message":"Check the message and try again.","support.error.support_preview_expired":"The attachment preview expired or is no longer available. Refresh the snapshot.","support.error.support_package_too_large":"The anonymized package exceeds the 8 MiB limit.","support.error.support_rate_limited":"Too many reports or previews were requested. Try again later.","support.error.support_unavailable":"The private support service is temporarily unavailable. Your draft remains here.","support.error.support_rejected":"The report did not pass the support service validation.","support.error.unauthorized":"You do not have permission to send this report.","vac.routes_section":"Maps and floors","vac.routes_current_map":"Current map","vac.routes_no_map":"no telemetry","vac.routes_status":"Routing","vac.routes_state_ready":"map assigned and calibrated","vac.routes_state_needs_calibration":"map assigned, calibration needed","vac.routes_state_unmapped":"current map is not assigned to a floor","vac.routes_state_ambiguous":"two maps are indistinguishable — no floor is chosen","vac.routes_state_missing_space":"the map's space was deleted","vac.routes_state_none":"no map data","vac.routes_empty":"No map is assigned to a floor yet.","vac.route_map_default":"no map id","vac.route_active":"Active","vac.route_space":"Space","vac.route_space_none":"not selected","vac.route_status_ready":"ready","vac.route_status_needs_calibration":"needs calibration","vac.route_status_ambiguous":"ambiguous","vac.route_status_missing_space":"space deleted","vac.route_missing_space_group":"Deleted space","vac.route_add_current":"Add current map","vac.route_delete":"Remove map","vac.route_delete_title":"Remove the map from its floor?","vac.route_delete_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_delete_confirm":"Remove","vac.route_space_title":"Move the map to another space?","vac.route_space_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_space_confirm":"Move","vac.route_missing_space_hint":"One of the maps points at a deleted space: pick a new one or remove the map. Until then the robot is not drawn for that map.","vac.route_default_hint":"The source reports no stable map id. Several floors cannot be told apart without another source or the robot's own selected map.","vac.route_target_hint":"The dock stays in the “{space}” space regardless of the current map.","vac.route_add_source":"Add a map source","vac.route_add_source_hint":"For integrations that give each map its own camera. The “All cameras” section above widens this list.","vac.route_source_no_map":"no map reported"};const yo={en:vo,ru:{"gs.hint":"Цвета заливок действуют на все пространства; у каждого цвета своя прозрачность. Какой режим заливки использует пространство — задаётся в его диалоге.","gs.show_room_tooltip":"Показывать окно с информацией при наведении на комнату","support.about_group":"О карточке","support.guide_group":"Документация","support.guide":"Руководство пользователя","support.form_group":"Отправить репорт или предложение","support.contact":"Контакт для связи (email/tg/WhatsApp), необязательно.","support.message":"Сообщение","support.attach":"Прикрепить обезличенную информацию из вашего плана","support.attach_hint":"В пакет входят только разрешённые геометрия, настройки и ограниченные сведения о среде. Не входят имена, HA id, текущие состояния, URL, файлы, сообщение и контакт.","support.geometry_warning":"Пакет не содержит имён и HA id, но содержит точную геометрию и размеры дома.","support.close_busy_title":"Прервать текущую операцию?","support.close_busy_body":"House Plan подготавливает или отправляет репорт. При закрытии ожидание результата прекратится.","support.building":"Подготавливаем обезличенные данные…","support.preview_summary":"Пакет v{version} · пространств: {spaces} · {size} КиБ","support.prepared":"Снимок подготовлен {n} мин назад","support.show_data":"Показать данные","support.download":"Скачать JSON","support.refresh":"Обновить снимок","support.privacy":"При отправке сообщение, необязательный контакт и, если выбран пакет, точная геометрия покидают ваш Home Assistant через relay проекта House Plan и доступны мейнтейнерам. Узел проекта хранит репорт до 30 дней. Сетевая инфраструктура видит адрес сервера HA, но House Plan не сохраняет его в исходном виде; метаданные лимитов и идемпотентности хранятся до 24 часов.","support.error_title":"Репорт не отправлен","support.manual_recovery":"Сообщение и вложение можно сохранить и продолжить вручную:","support.copy_message":"Копировать сообщение","support.success":"Репорт отправлен: {id}. Сохраните номер для связи с поддержкой.","support.copy_id":"Копировать ID","support.sending":"Отправляем…","support.retry":"Повторить","support.send":"Отправить","support.update_required":"Обновите карточку и интеграцию House Plan до совместимых версий, чтобы отправлять репорты.","support.message_copied":"Сообщение скопировано","support.id_copied":"ID репорта скопирован","support.copy_failed":"Не удалось получить доступ к буферу обмена. Выделите и скопируйте текст вручную.","support.validation.message_required":"Введите сообщение.","support.validation.message_too_long":"Сообщение должно содержать не более 10 000 символов.","support.validation.contact_too_long":"Контакт должен содержать не более 320 символов.","support.validation.preview_missing":"Дождитесь предпросмотра вложения или отключите его.","support.validation.preview_expired":"Предпросмотр вложения истёк. Обновите снимок.","support.error.support_invalid_message":"Проверьте сообщение и повторите попытку.","support.error.support_preview_expired":"Предпросмотр вложения истёк или больше недоступен. Обновите снимок.","support.error.support_package_too_large":"Обезличенный пакет превышает лимит 8 МиБ.","support.error.support_rate_limited":"Запрошено слишком много репортов или предпросмотров. Повторите позже.","support.error.support_unavailable":"Закрытая служба поддержки временно недоступна. Черновик сохранён в этом окне.","support.error.support_rejected":"Репорт не прошёл проверку службы поддержки.","support.error.unauthorized":"У вас нет прав на отправку этого репорта.","vac.routes_section":"Карты и этажи","vac.routes_current_map":"Текущая карта","vac.routes_no_map":"источник молчит","vac.routes_status":"Маршрутизация","vac.routes_state_ready":"карта сопоставлена и откалибрована","vac.routes_state_needs_calibration":"карта сопоставлена, нужна калибровка","vac.routes_state_unmapped":"текущая карта не сопоставлена этажу","vac.routes_state_ambiguous":"две карты неразличимы — этаж не выбирается","vac.routes_state_missing_space":"пространство карты удалено","vac.routes_state_none":"нет данных о карте","vac.routes_empty":"Ни одна карта ещё не сопоставлена этажу.","vac.route_map_default":"без идентификатора","vac.route_active":"Текущая","vac.route_space":"Пространство","vac.route_space_none":"не выбрано","vac.route_status_ready":"готова","vac.route_status_needs_calibration":"нужна калибровка","vac.route_status_ambiguous":"неоднозначна","vac.route_status_missing_space":"пространство удалено","vac.route_missing_space_group":"Пространство удалено","vac.route_add_current":"Добавить текущую карту","vac.route_delete":"Удалить карту","vac.route_delete_title":"Удалить карту с этажа?","vac.route_delete_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_delete_confirm":"Удалить","vac.route_space_title":"Перенести карту в другое пространство?","vac.route_space_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_space_confirm":"Перенести","vac.route_missing_space_hint":"Одна из карт ссылается на удалённое пространство: выберите новое или удалите карту. Пока ссылка не исправлена, робот на этой карте не рисуется.","vac.route_default_hint":"Источник не сообщает стабильный идентификатор карты. Несколько этажей нельзя различить без другого источника или собственной карты робота.","vac.route_target_hint":"Док остаётся в пространстве «{space}» независимо от текущей карты.","vac.route_add_source":"Добавить источник карты","vac.route_add_source_hint":"Для интеграций, где у каждой карты своя камера. Список расширяется разделом «Все камеры» выше.","vac.route_source_no_map":"карта не читается"},de:{"gs.hint":"Füllfarben gelten für jeden Bereich; jede Farbe hat ihre eigene Deckkraft. Der Füllmodus wird in den Einstellungen des jeweiligen Bereichs festgelegt.","gs.show_room_tooltip":"Rauminformationen beim Darüberfahren anzeigen","support.about_group":"Über die Karte","support.guide_group":"Dokumentation","support.guide":"Benutzerhandbuch","support.form_group":"Bericht oder Vorschlag senden","support.contact":"Kontakt (E-Mail/tg/WhatsApp), optional.","support.message":"Nachricht","support.attach":"Anonymisierte Informationen aus dem Plan anhängen","support.attach_hint":"Enthält nur erlaubte Plangeometrie, Einstellungen und begrenzte Laufzeitdaten. Namen, Home-Assistant-IDs, Live-Zustände, URLs, Dateien, Nachricht und Kontakt werden ausgeschlossen.","support.geometry_warning":"Das Paket enthält keine Namen oder Home-Assistant-IDs, aber die exakte Geometrie und die Maße Ihres Hauses.","support.close_busy_title":"Aktuellen Vorgang abbrechen?","support.close_busy_body":"House Plan bereitet den Bericht vor oder sendet ihn. Beim Schließen wird nicht weiter auf das Ergebnis gewartet.","support.building":"Anonymisierte Daten werden vorbereitet…","support.preview_summary":"Paket v{version} · {spaces} Bereiche · {size} KiB","support.prepared":"Schnappschuss vor {n} Min. erstellt","support.show_data":"Daten anzeigen","support.download":"JSON herunterladen","support.refresh":"Schnappschuss aktualisieren","support.privacy":"Beim Senden verlassen Ihre Nachricht, der optionale Kontakt und, falls ausgewählt, die exakte Geometrie Ihren Home Assistant über das House-Plan-Projektrelay und sind für die Maintainer sichtbar. Der Projektserver speichert den Bericht bis zu 30 Tage. Die Netzwerkinfrastruktur sieht die Adresse Ihres HA-Servers, House Plan speichert sie jedoch nicht im Rohformat; Limit- und Idempotenzdaten bleiben bis zu 24 Stunden erhalten.","support.error_title":"Der Bericht wurde nicht gesendet","support.manual_recovery":"Nachricht und Anhang können gespeichert und manuell weitergegeben werden:","support.copy_message":"Nachricht kopieren","support.success":"Bericht gesendet: {id}. Bewahren Sie diese Nummer für den Support auf.","support.copy_id":"ID kopieren","support.sending":"Wird gesendet…","support.retry":"Erneut versuchen","support.send":"Senden","support.update_required":"Aktualisieren Sie House-Plan-Karte und Integration auf kompatible Versionen, um Berichte zu senden.","support.message_copied":"Nachricht kopiert","support.id_copied":"Berichts-ID kopiert","support.copy_failed":"Kein Zugriff auf die Zwischenablage. Markieren und kopieren Sie den Text manuell.","support.validation.message_required":"Geben Sie eine Nachricht ein.","support.validation.message_too_long":"Die Nachricht darf höchstens 10.000 Zeichen enthalten.","support.validation.contact_too_long":"Der Kontakt darf höchstens 320 Zeichen enthalten.","support.validation.preview_missing":"Warten Sie auf die Vorschau oder deaktivieren Sie den Anhang.","support.validation.preview_expired":"Die Anhangsvorschau ist abgelaufen. Aktualisieren Sie den Schnappschuss.","support.error.support_invalid_message":"Prüfen Sie die Nachricht und versuchen Sie es erneut.","support.error.support_preview_expired":"Die Anhangsvorschau ist abgelaufen oder nicht mehr verfügbar. Aktualisieren Sie den Schnappschuss.","support.error.support_package_too_large":"Das anonymisierte Paket überschreitet das Limit von 8 MiB.","support.error.support_rate_limited":"Zu viele Berichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","support.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar. Der Entwurf bleibt in diesem Fenster erhalten.","support.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","support.error.unauthorized":"Sie dürfen diesen Bericht nicht senden.","vac.routes_section":"Karten und Etagen","vac.routes_current_map":"Aktuelle Karte","vac.routes_no_map":"keine Telemetrie","vac.routes_status":"Zuordnung","vac.routes_state_ready":"Karte zugeordnet und kalibriert","vac.routes_state_needs_calibration":"Karte zugeordnet, Kalibrierung nötig","vac.routes_state_unmapped":"aktuelle Karte keiner Etage zugeordnet","vac.routes_state_ambiguous":"zwei Karten nicht unterscheidbar — keine Etage gewählt","vac.routes_state_missing_space":"der Raum der Karte wurde gelöscht","vac.routes_state_none":"keine Kartendaten","vac.routes_empty":"Noch keine Karte einer Etage zugeordnet.","vac.route_map_default":"ohne Karten-ID","vac.route_active":"Aktiv","vac.route_space":"Raum","vac.route_space_none":"nicht gewählt","vac.route_status_ready":"bereit","vac.route_status_needs_calibration":"Kalibrierung nötig","vac.route_status_ambiguous":"mehrdeutig","vac.route_status_missing_space":"Raum gelöscht","vac.route_missing_space_group":"Gelöschter Bereich","vac.route_add_current":"Aktuelle Karte hinzufügen","vac.route_delete":"Karte entfernen","vac.route_delete_title":"Karte von der Etage entfernen?","vac.route_delete_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_delete_confirm":"Entfernen","vac.route_space_title":"Karte in einen anderen Raum verschieben?","vac.route_space_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_space_confirm":"Verschieben","vac.route_missing_space_hint":"Eine Karte verweist auf einen gelöschten Raum: neuen wählen oder Karte entfernen. Bis dahin wird der Roboter für diese Karte nicht gezeichnet.","vac.route_default_hint":"Die Quelle meldet keine stabile Karten-ID. Mehrere Etagen lassen sich ohne andere Quelle oder die vom Roboter gewählte Karte nicht unterscheiden.","vac.route_target_hint":"Die Station bleibt unabhängig von der aktuellen Karte im Raum „{space}“.","vac.route_add_source":"Kartenquelle hinzufügen","vac.route_add_source_hint":"Für Integrationen, die jeder Karte eine eigene Kamera geben. Der Abschnitt „Alle Kameras“ oben erweitert diese Liste.","vac.route_source_no_map":"keine Karte gemeldet"},fr:{"gs.hint":"Les couleurs de remplissage s’appliquent à tous les espaces ; chaque couleur possède sa propre opacité. Le mode de remplissage utilisé par un espace se règle dans la boîte de dialogue de cet espace.","gs.show_room_tooltip":"Afficher les informations de la pièce au survol","support.about_group":"À propos de la carte","support.guide_group":"Documentation d’aide","support.guide":"Guide utilisateur","support.form_group":"Envoyer un rapport ou une suggestion","support.contact":"Contact (e-mail/tg/WhatsApp), facultatif.","support.message":"Votre message","support.attach":"Joindre des informations anonymisées de votre plan","support.attach_hint":"Inclut uniquement la géométrie, les réglages autorisés et des données d’exécution limitées. Exclut les noms, identifiants Home Assistant, états en direct, URL, fichiers, message et contact.","support.geometry_warning":"Le paquet ne contient ni noms ni identifiants Home Assistant, mais il contient la géométrie et les dimensions exactes de votre logement.","support.close_busy_title":"Interrompre l’opération en cours ?","support.close_busy_body":"House Plan prépare ou envoie le rapport. Fermer maintenant arrête l’attente du résultat.","support.building":"Préparation des données anonymisées…","support.preview_summary":"Paquet v{version} · {spaces} espaces · {size} Kio","support.prepared":"Instantané préparé il y a {n} min","support.show_data":"Afficher les données","support.download":"Télécharger le JSON","support.refresh":"Actualiser l’instantané","support.privacy":"Lors de l’envoi, votre message, le contact facultatif et, si elle est sélectionnée, la géométrie exacte quittent votre Home Assistant via le relais du projet House Plan et sont visibles par les mainteneurs. Le serveur du projet conserve le rapport jusqu’à 30 jours. L’infrastructure réseau voit l’adresse de votre serveur HA, mais House Plan ne la conserve pas en clair ; les métadonnées de limitation et d’idempotence sont gardées jusqu’à 24 heures.","support.error_title":"Le rapport n’a pas été envoyé","support.manual_recovery":"Vous pouvez conserver le message et la pièce jointe puis continuer manuellement :","support.copy_message":"Copier le message","support.success":"Rapport envoyé : {id}. Conservez ce numéro pour contacter l’assistance.","support.copy_id":"Copier l’ID","support.sending":"Envoi…","support.retry":"Réessayer","support.send":"Envoyer","support.update_required":"Mettez à jour la carte et l’intégration House Plan vers des versions compatibles pour envoyer des rapports.","support.message_copied":"Message copié","support.id_copied":"ID du rapport copié","support.copy_failed":"Impossible d’accéder au presse-papiers. Sélectionnez et copiez le texte manuellement.","support.validation.message_required":"Saisissez un message.","support.validation.message_too_long":"Le message ne doit pas dépasser 10 000 caractères.","support.validation.contact_too_long":"Le contact ne doit pas dépasser 320 caractères.","support.validation.preview_missing":"Attendez l’aperçu de la pièce jointe ou désactivez-la.","support.validation.preview_expired":"L’aperçu de la pièce jointe a expiré. Actualisez l’instantané.","support.error.support_invalid_message":"Vérifiez le message et réessayez.","support.error.support_preview_expired":"L’aperçu de la pièce jointe a expiré ou n’est plus disponible. Actualisez l’instantané.","support.error.support_package_too_large":"Le paquet anonymisé dépasse la limite de 8 Mio.","support.error.support_rate_limited":"Trop de rapports ou d’aperçus ont été demandés. Réessayez plus tard.","support.error.support_unavailable":"Le service d’assistance privé est temporairement indisponible. Le brouillon reste dans cette fenêtre.","support.error.support_rejected":"Le rapport n’a pas passé la validation du service d’assistance.","support.error.unauthorized":"Vous n’êtes pas autorisé à envoyer ce rapport.","vac.routes_section":"Cartes et étages","vac.routes_current_map":"Carte actuelle","vac.routes_no_map":"aucune télémétrie","vac.routes_status":"Routage","vac.routes_state_ready":"carte assignée et calibrée","vac.routes_state_needs_calibration":"carte assignée, calibrage requis","vac.routes_state_unmapped":"carte actuelle non assignée à un étage","vac.routes_state_ambiguous":"deux cartes indiscernables — aucun étage choisi","vac.routes_state_missing_space":"l'espace de la carte a été supprimé","vac.routes_state_none":"aucune donnée de carte","vac.routes_empty":"Aucune carte n'est encore assignée à un étage.","vac.route_map_default":"sans identifiant","vac.route_active":"Active","vac.route_space":"Espace","vac.route_space_none":"non sélectionné","vac.route_status_ready":"prête","vac.route_status_needs_calibration":"calibrage requis","vac.route_status_ambiguous":"ambiguë","vac.route_status_missing_space":"espace supprimé","vac.route_missing_space_group":"Espace supprimé","vac.route_add_current":"Ajouter la carte actuelle","vac.route_delete":"Supprimer la carte","vac.route_delete_title":"Retirer la carte de son étage ?","vac.route_delete_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_delete_confirm":"Supprimer","vac.route_space_title":"Déplacer la carte vers un autre espace ?","vac.route_space_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_space_confirm":"Déplacer","vac.route_missing_space_hint":"Une carte pointe vers un espace supprimé : choisissez-en un autre ou supprimez la carte. D'ici là, le robot n'est pas dessiné pour cette carte.","vac.route_default_hint":"La source ne fournit pas d'identifiant de carte stable. Plusieurs étages ne peuvent pas être distingués sans une autre source ou la carte sélectionnée du robot.","vac.route_target_hint":"La station reste dans l'espace « {space} » quelle que soit la carte actuelle.","vac.route_add_source":"Ajouter une source de carte","vac.route_add_source_hint":"Pour les intégrations qui donnent à chaque carte sa propre caméra. La section « Toutes les caméras » ci-dessus élargit cette liste.","vac.route_source_no_map":"aucune carte signalée"}};function $o(e,s,i){return t(yo[e]?.[s]??vo[s]??s,i)}function wo(t,e,s,i,o){return{markerId:t,source:i,mapId:o,space:e.length?"":s}}function ko(t,e,s){return{...t,space:s.has(e)?e:""}}function xo(t,e=Math.random){const s=new Set(t);for(let t=0;t<64;t+=1){const t="vr_"+Math.floor(16777215*e()).toString(36).padStart(5,"0");if(!s.has(t))return t}return"vr_"+Date.now().toString(36)}function So(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const Mo=new WeakMap,Do=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function Co(t,i,o){const u=t.host,_=a(u.hass,u._config?.language),m=(t,e)=>$o(_,t,e),g=i.marker?.vacuum||{},f=Array.isArray(g.map_routes),b=u._vacSource(i)||"",v=e(i.id,g,i.space,b),y=(u._serverCfg?.spaces||[]).filter(t=>"string"==typeof t?.id&&!!t.id).map(t=>({id:t.id,name:String(t.name||t.id)})),$=new Set(y.map(t=>t.id)),w=n(v,[b],t=>u._vacObservedMapId(i,t)),k=r({routes:v,observed:w,spaceIds:$}),x="ready"===k.kind||"needs_calibration"===k.kind||"missing_space"===k.kind?k.route.id:"",S=b?w[b]:void 0,M=async e=>{let o=f?g.map_routes??null:null;if(!o&&(o=function(t,e,i,o){if(!i)return null;const a=t?.calibration;if(!a||"object"!=typeof a)return null;const n=new Set,r=[];for(const t of Object.keys(a)){const l=s(a[t]);if(!l)continue;const h=o(n);n.add(h),r.push({id:h,source:i,map_id:t,space:e,calibration:l})}return r.length?r:null}(g,i.space,b,t=>xo(t))??[],!b&&Object.keys(g.calibration||{}).length))return!1;const a=e(o);return!!a&&(async e=>{const s=u._serverCfg;if(!s)return!1;const o=JSON.parse(JSON.stringify(s));o.markers=o.markers||[];let a=o.markers.find(t=>t.id===i.id);if(!a){if("device"!==i.bindingKind&&"entity"!==i.bindingKind||!i.bindingRef)return!1;a={id:i.id,binding:`${i.bindingKind}:${i.bindingRef}`,space:i.space||null,area:i.area||null,hidden:!!i.hidden},o.markers.push(a)}a.vacuum={...a.vacuum||{},map_routes:e},delete a.vacuum.calibration;const n=c(s,o,u._cfgContentFingerprint,u._cfgRev,d);u._serverCfg=o,u._regSignature="",u._maybeRebuildDevices(),u.requestUpdate(),u._saveConfigDebounced.pending()&&u._saveConfigDebounced.cancel();try{return await t._saveConfigNow(),!0}catch(t){return p(u,n,d),u._regSignature="",u._maybeRebuildDevices(),u.requestUpdate(),u._showToast(u._t("toast.cfg_save_failed",{err:u._errText(t)})),!1}})(a)},D=o.candidates.filter(t=>t.entityId!==b&&!v.some(e=>e.source===t.entityId)),C=async(t,e)=>{if(!e||e===t.space)return;await u._confirmDanger({key:"vacuum_route_space",kind:"warning",title:m("vac.route_space_title"),message:m("vac.route_space_body"),objectName:t.map_id||m("vac.route_map_default"),confirmLabel:m("vac.route_space_confirm"),cancelLabel:u._t("btn.cancel")})&&await M(s=>function(t,e,s,i){return t.map(t=>t.id===e?{...t,id:i,space:s,calibration:null}:t)}(s,t.id,e,xo(new Set(v.map(t=>t.id)))))},P=new Map(y.map((t,e)=>[t.id,e])),I=(t,e)=>t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)||t.id.localeCompare(e.id),T=v.filter(t=>$.has(t.space)).sort((t,e)=>(P.get(t.space)??0)-(P.get(e.space)??0)||I(t,e)),z=v.filter(t=>!$.has(t.space)).sort(I),R=[...T,...z],A=!!b&&void 0!==S&&!v.some(t=>t.source===b&&t.map_id===S);let F=Mo.get(t);const N=F?.source||"",H=F?.mapId||"",L=!!F&&v.some(t=>t.source===N&&t.map_id===H);F&&(F.markerId!==i.id||u._vacObservedMapId(i,F.source)!==F.mapId||L&&!F.saving)&&(Mo.delete(t),F=void 0),F?.space&&!$.has(F.space)&&(F=ko(F,"",$),Mo.set(t,F));const E=e=>h` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{s as t,e,n as s,f as i,i as o,l as a,o as n,r,A as l,b as h,a as c,c as d,d as p,D as u,w as _,N as m,g,h as f,j as b,k as v,m as y,p as $,q as w,t as k,u as x,v as S,x as M,y as D,z as C,B as P,C as I,E as T,F as z,G as R,H as A,I as F,J as N,K as H,L,M as E,O,P as B,Q as W,R as G,S as j,T as q,U,V as K,W as V,X as J,Y,Z as X,_ as Z,$ as Q,a0 as tt,a1 as et,a2 as st,a3 as it,a4 as ot,a5 as at,a6 as nt,a7 as rt,a8 as lt,a9 as ht,aa as ct,ab as dt,ac as pt,ad as ut,ae as _t,af as mt,ag as gt,ah as ft,ai as bt,aj as vt,ak as yt,al as $t,am as wt,an as kt,ao as xt,ap as St,aq as Mt,ar as Dt,as as Ct,at as Pt,au as It,av as Tt,aw as zt,ax as Rt,ay as At,az as Ft,aA as Nt,aB as Ht,aC as Lt,aD as Et,aE as Ot,aF as Bt,aG as Wt,aH as Gt,aI as jt,aJ as qt,aK as Ut,aL as Kt,aM as Vt,aN as Jt,aO as Yt,aP as Xt,aQ as Zt,aR as Qt,aS as te,aT as ee,aU as se,aV as ie,aW as oe,aX as ae,aY as ne,aZ as re,a_ as le,a$ as he,b0 as ce,b1 as de,b2 as pe,b3 as ue,b4 as _e,b5 as me,b6 as ge,b7 as fe,b8 as be,b9 as ve,ba as ye,bb as $e,bc as we,bd as ke,be as xe,bf as Se,bg as Me,bh as De,bi as Ce,bj as Pe,bk as Ie,bl as Te,bm as ze,bn as Re,bo as Ae,bp as Fe,bq as Ne,br as He,bs as Le,bt as Ee,bu as Oe,bv as Be,bw as We,bx as Ge,by as je,bz as qe,bA as Ue,bB as Ke,bC as Ve,bD as Je,bE as Ye,bF as Xe,bG as Ze,bH as Qe,bI as ts,bJ as es,bK as ss,bL as is,bM as os,bN as as,bO as ns,bP as rs,bQ as ls,bR as hs,bS as cs,bT as ds,bU as ps,bV as us,bW as _s,bX as ms,bY as gs,bZ as fs,b_ as bs,b$ as vs,c0 as ys,c1 as $s,c2 as ws,c3 as ks,c4 as xs,c5 as Ss,c6 as Ms,c7 as Ds,c8 as Cs,c9 as Ps,ca as Is,cb as Ts,cc as zs,cd as Rs,ce as As,cf as Fs,cg as Ns,ch as Hs,ci as Ls,cj as Es,ck as Os,cl as Bs,cm as Ws,cn as Gs,co as js,cp as qs,cq as Us,cr as Ks,cs as Vs,ct as Js,cu as Ys,cv as Xs,cw as Zs,cx as Qs,cy as ti,cz as ei,cA as si,cB as ii,cC as oi,cD as ai,cE as ni,cF as ri,cG as li,cH as hi,cI as ci,cJ as di,cK as pi,cL as ui,cM as _i,cN as mi,cO as gi,cP as fi,cQ as bi,cR as vi,cS as yi,cT as $i,cU as wi,cV as ki,cW as xi,cX as Si,cY as Mi,cZ as Di,c_ as Ci,c$ as Pi,d0 as Ii,d1 as Ti,d2 as zi,d3 as Ri,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Hi,d8 as Li,d9 as Ei,da as Oi,db as Bi,dc as Wi,dd as Gi,de as ji,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji,dk as Yi,dl as Xi,dm as Zi,dn as Qi,dp as to,dq as eo}from"./houseplan-card-Bhpi71t0.js";import{i as so}from"./guard-BgTQLSGB.js";import{F as io,f as oo,p as ao,c as no,s as ro,i as lo,e as ho,r as co,a as po,b as uo,d as _o,g as mo,t as go}from"./backdrop-pick-CV_as5Xh.js";import{t as fo,h as bo,m as vo,T as yo}from"./zigbee-topology-B-C5QCCD.js";import{GENERATED_FURNITURE_ART as $o,FURNITURE_ART_FINGERPRINT as wo}from"./furniture-plan-art.generated-Bs3YknKY.js";var ko={"gs.hint":"Fill colors apply to every space; each color has its own opacity. Which fill mode a space uses is set in that space's dialog.","gs.show_room_tooltip":"Show the room information window on hover","support.about_group":"About the card","support.guide_group":"Documentation","support.guide":"User guide","support.form_group":"Send a report or suggestion","support.contact":"Contact details (email/tg/WhatsApp), optional.","support.message":"Message","support.attach":"Attach anonymized information from your plan","support.attach_hint":"Includes only allowed plan geometry, settings and bounded runtime facts. Excludes names, Home Assistant IDs, live states, URLs, files, and your message/contact.","support.geometry_warning":"The package contains no names or Home Assistant IDs, but it does contain the exact geometry and dimensions of your home.","support.close_busy_title":"Stop the current operation?","support.close_busy_body":"House Plan is preparing or sending the report. Closing now stops waiting for the result.","support.building":"Preparing anonymized data…","support.preview_summary":"Package v{version} · {spaces} spaces · {size} KiB","support.prepared":"Snapshot prepared {n} min ago","support.show_data":"Show data","support.download":"Download JSON","support.refresh":"Refresh snapshot","support.privacy":"When you send, your message, optional contact and, if selected, exact geometry leave your Home Assistant through the House Plan project relay and are visible to maintainers. The project node keeps the report for up to 30 days. Network infrastructure sees your HA server address, but House Plan does not retain it raw; rate-limit and idempotency metadata is kept for up to 24 hours.","support.error_title":"The report was not sent","support.manual_recovery":"You can keep the message and attachment and continue manually:","support.copy_message":"Copy message","support.success":"Report sent: {id}. Save this number when contacting support.","support.copy_id":"Copy ID","support.sending":"Sending…","support.retry":"Retry","support.send":"Send","support.update_required":"Update the House Plan card and integration to compatible versions to send reports.","support.message_copied":"Message copied","support.id_copied":"Report ID copied","support.copy_failed":"Could not access the clipboard. Select and copy the text manually.","support.validation.message_required":"Enter a message.","support.validation.message_too_long":"The message must contain no more than 10,000 characters.","support.validation.contact_too_long":"Contact details must contain no more than 320 characters.","support.validation.preview_missing":"Wait for the attachment preview or turn the attachment off.","support.validation.preview_expired":"The attachment preview expired. Refresh the snapshot.","support.error.support_invalid_message":"Check the message and try again.","support.error.support_preview_expired":"The attachment preview expired or is no longer available. Refresh the snapshot.","support.error.support_package_too_large":"The anonymized package exceeds the 8 MiB limit.","support.error.support_rate_limited":"Too many reports or previews were requested. Try again later.","support.error.support_unavailable":"The private support service is temporarily unavailable. Your draft remains here.","support.error.support_rejected":"The report did not pass the support service validation.","support.error.unauthorized":"You do not have permission to send this report.","vac.routes_section":"Maps and floors","vac.routes_current_map":"Current map","vac.routes_no_map":"no telemetry","vac.routes_status":"Routing","vac.routes_state_ready":"map assigned and calibrated","vac.routes_state_needs_calibration":"map assigned, calibration needed","vac.routes_state_unmapped":"current map is not assigned to a floor","vac.routes_state_ambiguous":"two maps are indistinguishable — no floor is chosen","vac.routes_state_missing_space":"the map's space was deleted","vac.routes_state_none":"no map data","vac.routes_empty":"No map is assigned to a floor yet.","vac.route_map_default":"no map id","vac.route_active":"Active","vac.route_space":"Space","vac.route_space_none":"not selected","vac.route_status_ready":"ready","vac.route_status_needs_calibration":"needs calibration","vac.route_status_ambiguous":"ambiguous","vac.route_status_missing_space":"space deleted","vac.route_missing_space_group":"Deleted space","vac.route_add_current":"Add current map","vac.route_delete":"Remove map","vac.route_delete_title":"Remove the map from its floor?","vac.route_delete_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_delete_confirm":"Remove","vac.route_space_title":"Move the map to another space?","vac.route_space_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_space_confirm":"Move","vac.route_missing_space_hint":"One of the maps points at a deleted space: pick a new one or remove the map. Until then the robot is not drawn for that map.","vac.route_default_hint":"The source reports no stable map id. Several floors cannot be told apart without another source or the robot's own selected map.","vac.route_target_hint":"The dock stays in the “{space}” space regardless of the current map.","vac.route_add_source":"Add a map source","vac.route_add_source_hint":"For integrations that give each map its own camera. The “All cameras” section above widens this list.","vac.route_source_no_map":"no map reported"};const xo={en:ko,ru:{"gs.hint":"Цвета заливок действуют на все пространства; у каждого цвета своя прозрачность. Какой режим заливки использует пространство — задаётся в его диалоге.","gs.show_room_tooltip":"Показывать окно с информацией при наведении на комнату","support.about_group":"О карточке","support.guide_group":"Документация","support.guide":"Руководство пользователя","support.form_group":"Отправить репорт или предложение","support.contact":"Контакт для связи (email/tg/WhatsApp), необязательно.","support.message":"Сообщение","support.attach":"Прикрепить обезличенную информацию из вашего плана","support.attach_hint":"В пакет входят только разрешённые геометрия, настройки и ограниченные сведения о среде. Не входят имена, HA id, текущие состояния, URL, файлы, сообщение и контакт.","support.geometry_warning":"Пакет не содержит имён и HA id, но содержит точную геометрию и размеры дома.","support.close_busy_title":"Прервать текущую операцию?","support.close_busy_body":"House Plan подготавливает или отправляет репорт. При закрытии ожидание результата прекратится.","support.building":"Подготавливаем обезличенные данные…","support.preview_summary":"Пакет v{version} · пространств: {spaces} · {size} КиБ","support.prepared":"Снимок подготовлен {n} мин назад","support.show_data":"Показать данные","support.download":"Скачать JSON","support.refresh":"Обновить снимок","support.privacy":"При отправке сообщение, необязательный контакт и, если выбран пакет, точная геометрия покидают ваш Home Assistant через relay проекта House Plan и доступны мейнтейнерам. Узел проекта хранит репорт до 30 дней. Сетевая инфраструктура видит адрес сервера HA, но House Plan не сохраняет его в исходном виде; метаданные лимитов и идемпотентности хранятся до 24 часов.","support.error_title":"Репорт не отправлен","support.manual_recovery":"Сообщение и вложение можно сохранить и продолжить вручную:","support.copy_message":"Копировать сообщение","support.success":"Репорт отправлен: {id}. Сохраните номер для связи с поддержкой.","support.copy_id":"Копировать ID","support.sending":"Отправляем…","support.retry":"Повторить","support.send":"Отправить","support.update_required":"Обновите карточку и интеграцию House Plan до совместимых версий, чтобы отправлять репорты.","support.message_copied":"Сообщение скопировано","support.id_copied":"ID репорта скопирован","support.copy_failed":"Не удалось получить доступ к буферу обмена. Выделите и скопируйте текст вручную.","support.validation.message_required":"Введите сообщение.","support.validation.message_too_long":"Сообщение должно содержать не более 10 000 символов.","support.validation.contact_too_long":"Контакт должен содержать не более 320 символов.","support.validation.preview_missing":"Дождитесь предпросмотра вложения или отключите его.","support.validation.preview_expired":"Предпросмотр вложения истёк. Обновите снимок.","support.error.support_invalid_message":"Проверьте сообщение и повторите попытку.","support.error.support_preview_expired":"Предпросмотр вложения истёк или больше недоступен. Обновите снимок.","support.error.support_package_too_large":"Обезличенный пакет превышает лимит 8 МиБ.","support.error.support_rate_limited":"Запрошено слишком много репортов или предпросмотров. Повторите позже.","support.error.support_unavailable":"Закрытая служба поддержки временно недоступна. Черновик сохранён в этом окне.","support.error.support_rejected":"Репорт не прошёл проверку службы поддержки.","support.error.unauthorized":"У вас нет прав на отправку этого репорта.","vac.routes_section":"Карты и этажи","vac.routes_current_map":"Текущая карта","vac.routes_no_map":"источник молчит","vac.routes_status":"Маршрутизация","vac.routes_state_ready":"карта сопоставлена и откалибрована","vac.routes_state_needs_calibration":"карта сопоставлена, нужна калибровка","vac.routes_state_unmapped":"текущая карта не сопоставлена этажу","vac.routes_state_ambiguous":"две карты неразличимы — этаж не выбирается","vac.routes_state_missing_space":"пространство карты удалено","vac.routes_state_none":"нет данных о карте","vac.routes_empty":"Ни одна карта ещё не сопоставлена этажу.","vac.route_map_default":"без идентификатора","vac.route_active":"Текущая","vac.route_space":"Пространство","vac.route_space_none":"не выбрано","vac.route_status_ready":"готова","vac.route_status_needs_calibration":"нужна калибровка","vac.route_status_ambiguous":"неоднозначна","vac.route_status_missing_space":"пространство удалено","vac.route_missing_space_group":"Пространство удалено","vac.route_add_current":"Добавить текущую карту","vac.route_delete":"Удалить карту","vac.route_delete_title":"Удалить карту с этажа?","vac.route_delete_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_delete_confirm":"Удалить","vac.route_space_title":"Перенести карту в другое пространство?","vac.route_space_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_space_confirm":"Перенести","vac.route_missing_space_hint":"Одна из карт ссылается на удалённое пространство: выберите новое или удалите карту. Пока ссылка не исправлена, робот на этой карте не рисуется.","vac.route_default_hint":"Источник не сообщает стабильный идентификатор карты. Несколько этажей нельзя различить без другого источника или собственной карты робота.","vac.route_target_hint":"Док остаётся в пространстве «{space}» независимо от текущей карты.","vac.route_add_source":"Добавить источник карты","vac.route_add_source_hint":"Для интеграций, где у каждой карты своя камера. Список расширяется разделом «Все камеры» выше.","vac.route_source_no_map":"карта не читается"},de:{"gs.hint":"Füllfarben gelten für jeden Bereich; jede Farbe hat ihre eigene Deckkraft. Der Füllmodus wird in den Einstellungen des jeweiligen Bereichs festgelegt.","gs.show_room_tooltip":"Rauminformationen beim Darüberfahren anzeigen","support.about_group":"Über die Karte","support.guide_group":"Dokumentation","support.guide":"Benutzerhandbuch","support.form_group":"Bericht oder Vorschlag senden","support.contact":"Kontakt (E-Mail/tg/WhatsApp), optional.","support.message":"Nachricht","support.attach":"Anonymisierte Informationen aus dem Plan anhängen","support.attach_hint":"Enthält nur erlaubte Plangeometrie, Einstellungen und begrenzte Laufzeitdaten. Namen, Home-Assistant-IDs, Live-Zustände, URLs, Dateien, Nachricht und Kontakt werden ausgeschlossen.","support.geometry_warning":"Das Paket enthält keine Namen oder Home-Assistant-IDs, aber die exakte Geometrie und die Maße Ihres Hauses.","support.close_busy_title":"Aktuellen Vorgang abbrechen?","support.close_busy_body":"House Plan bereitet den Bericht vor oder sendet ihn. Beim Schließen wird nicht weiter auf das Ergebnis gewartet.","support.building":"Anonymisierte Daten werden vorbereitet…","support.preview_summary":"Paket v{version} · {spaces} Bereiche · {size} KiB","support.prepared":"Schnappschuss vor {n} Min. erstellt","support.show_data":"Daten anzeigen","support.download":"JSON herunterladen","support.refresh":"Schnappschuss aktualisieren","support.privacy":"Beim Senden verlassen Ihre Nachricht, der optionale Kontakt und, falls ausgewählt, die exakte Geometrie Ihren Home Assistant über das House-Plan-Projektrelay und sind für die Maintainer sichtbar. Der Projektserver speichert den Bericht bis zu 30 Tage. Die Netzwerkinfrastruktur sieht die Adresse Ihres HA-Servers, House Plan speichert sie jedoch nicht im Rohformat; Limit- und Idempotenzdaten bleiben bis zu 24 Stunden erhalten.","support.error_title":"Der Bericht wurde nicht gesendet","support.manual_recovery":"Nachricht und Anhang können gespeichert und manuell weitergegeben werden:","support.copy_message":"Nachricht kopieren","support.success":"Bericht gesendet: {id}. Bewahren Sie diese Nummer für den Support auf.","support.copy_id":"ID kopieren","support.sending":"Wird gesendet…","support.retry":"Erneut versuchen","support.send":"Senden","support.update_required":"Aktualisieren Sie House-Plan-Karte und Integration auf kompatible Versionen, um Berichte zu senden.","support.message_copied":"Nachricht kopiert","support.id_copied":"Berichts-ID kopiert","support.copy_failed":"Kein Zugriff auf die Zwischenablage. Markieren und kopieren Sie den Text manuell.","support.validation.message_required":"Geben Sie eine Nachricht ein.","support.validation.message_too_long":"Die Nachricht darf höchstens 10.000 Zeichen enthalten.","support.validation.contact_too_long":"Der Kontakt darf höchstens 320 Zeichen enthalten.","support.validation.preview_missing":"Warten Sie auf die Vorschau oder deaktivieren Sie den Anhang.","support.validation.preview_expired":"Die Anhangsvorschau ist abgelaufen. Aktualisieren Sie den Schnappschuss.","support.error.support_invalid_message":"Prüfen Sie die Nachricht und versuchen Sie es erneut.","support.error.support_preview_expired":"Die Anhangsvorschau ist abgelaufen oder nicht mehr verfügbar. Aktualisieren Sie den Schnappschuss.","support.error.support_package_too_large":"Das anonymisierte Paket überschreitet das Limit von 8 MiB.","support.error.support_rate_limited":"Zu viele Berichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","support.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar. Der Entwurf bleibt in diesem Fenster erhalten.","support.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","support.error.unauthorized":"Sie dürfen diesen Bericht nicht senden.","vac.routes_section":"Karten und Etagen","vac.routes_current_map":"Aktuelle Karte","vac.routes_no_map":"keine Telemetrie","vac.routes_status":"Zuordnung","vac.routes_state_ready":"Karte zugeordnet und kalibriert","vac.routes_state_needs_calibration":"Karte zugeordnet, Kalibrierung nötig","vac.routes_state_unmapped":"aktuelle Karte keiner Etage zugeordnet","vac.routes_state_ambiguous":"zwei Karten nicht unterscheidbar — keine Etage gewählt","vac.routes_state_missing_space":"der Raum der Karte wurde gelöscht","vac.routes_state_none":"keine Kartendaten","vac.routes_empty":"Noch keine Karte einer Etage zugeordnet.","vac.route_map_default":"ohne Karten-ID","vac.route_active":"Aktiv","vac.route_space":"Raum","vac.route_space_none":"nicht gewählt","vac.route_status_ready":"bereit","vac.route_status_needs_calibration":"Kalibrierung nötig","vac.route_status_ambiguous":"mehrdeutig","vac.route_status_missing_space":"Raum gelöscht","vac.route_missing_space_group":"Gelöschter Bereich","vac.route_add_current":"Aktuelle Karte hinzufügen","vac.route_delete":"Karte entfernen","vac.route_delete_title":"Karte von der Etage entfernen?","vac.route_delete_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_delete_confirm":"Entfernen","vac.route_space_title":"Karte in einen anderen Raum verschieben?","vac.route_space_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_space_confirm":"Verschieben","vac.route_missing_space_hint":"Eine Karte verweist auf einen gelöschten Raum: neuen wählen oder Karte entfernen. Bis dahin wird der Roboter für diese Karte nicht gezeichnet.","vac.route_default_hint":"Die Quelle meldet keine stabile Karten-ID. Mehrere Etagen lassen sich ohne andere Quelle oder die vom Roboter gewählte Karte nicht unterscheiden.","vac.route_target_hint":"Die Station bleibt unabhängig von der aktuellen Karte im Raum „{space}“.","vac.route_add_source":"Kartenquelle hinzufügen","vac.route_add_source_hint":"Für Integrationen, die jeder Karte eine eigene Kamera geben. Der Abschnitt „Alle Kameras“ oben erweitert diese Liste.","vac.route_source_no_map":"keine Karte gemeldet"},fr:{"gs.hint":"Les couleurs de remplissage s’appliquent à tous les espaces ; chaque couleur possède sa propre opacité. Le mode de remplissage utilisé par un espace se règle dans la boîte de dialogue de cet espace.","gs.show_room_tooltip":"Afficher les informations de la pièce au survol","support.about_group":"À propos de la carte","support.guide_group":"Documentation d’aide","support.guide":"Guide utilisateur","support.form_group":"Envoyer un rapport ou une suggestion","support.contact":"Contact (e-mail/tg/WhatsApp), facultatif.","support.message":"Votre message","support.attach":"Joindre des informations anonymisées de votre plan","support.attach_hint":"Inclut uniquement la géométrie, les réglages autorisés et des données d’exécution limitées. Exclut les noms, identifiants Home Assistant, états en direct, URL, fichiers, message et contact.","support.geometry_warning":"Le paquet ne contient ni noms ni identifiants Home Assistant, mais il contient la géométrie et les dimensions exactes de votre logement.","support.close_busy_title":"Interrompre l’opération en cours ?","support.close_busy_body":"House Plan prépare ou envoie le rapport. Fermer maintenant arrête l’attente du résultat.","support.building":"Préparation des données anonymisées…","support.preview_summary":"Paquet v{version} · {spaces} espaces · {size} Kio","support.prepared":"Instantané préparé il y a {n} min","support.show_data":"Afficher les données","support.download":"Télécharger le JSON","support.refresh":"Actualiser l’instantané","support.privacy":"Lors de l’envoi, votre message, le contact facultatif et, si elle est sélectionnée, la géométrie exacte quittent votre Home Assistant via le relais du projet House Plan et sont visibles par les mainteneurs. Le serveur du projet conserve le rapport jusqu’à 30 jours. L’infrastructure réseau voit l’adresse de votre serveur HA, mais House Plan ne la conserve pas en clair ; les métadonnées de limitation et d’idempotence sont gardées jusqu’à 24 heures.","support.error_title":"Le rapport n’a pas été envoyé","support.manual_recovery":"Vous pouvez conserver le message et la pièce jointe puis continuer manuellement :","support.copy_message":"Copier le message","support.success":"Rapport envoyé : {id}. Conservez ce numéro pour contacter l’assistance.","support.copy_id":"Copier l’ID","support.sending":"Envoi…","support.retry":"Réessayer","support.send":"Envoyer","support.update_required":"Mettez à jour la carte et l’intégration House Plan vers des versions compatibles pour envoyer des rapports.","support.message_copied":"Message copié","support.id_copied":"ID du rapport copié","support.copy_failed":"Impossible d’accéder au presse-papiers. Sélectionnez et copiez le texte manuellement.","support.validation.message_required":"Saisissez un message.","support.validation.message_too_long":"Le message ne doit pas dépasser 10 000 caractères.","support.validation.contact_too_long":"Le contact ne doit pas dépasser 320 caractères.","support.validation.preview_missing":"Attendez l’aperçu de la pièce jointe ou désactivez-la.","support.validation.preview_expired":"L’aperçu de la pièce jointe a expiré. Actualisez l’instantané.","support.error.support_invalid_message":"Vérifiez le message et réessayez.","support.error.support_preview_expired":"L’aperçu de la pièce jointe a expiré ou n’est plus disponible. Actualisez l’instantané.","support.error.support_package_too_large":"Le paquet anonymisé dépasse la limite de 8 Mio.","support.error.support_rate_limited":"Trop de rapports ou d’aperçus ont été demandés. Réessayez plus tard.","support.error.support_unavailable":"Le service d’assistance privé est temporairement indisponible. Le brouillon reste dans cette fenêtre.","support.error.support_rejected":"Le rapport n’a pas passé la validation du service d’assistance.","support.error.unauthorized":"Vous n’êtes pas autorisé à envoyer ce rapport.","vac.routes_section":"Cartes et étages","vac.routes_current_map":"Carte actuelle","vac.routes_no_map":"aucune télémétrie","vac.routes_status":"Routage","vac.routes_state_ready":"carte assignée et calibrée","vac.routes_state_needs_calibration":"carte assignée, calibrage requis","vac.routes_state_unmapped":"carte actuelle non assignée à un étage","vac.routes_state_ambiguous":"deux cartes indiscernables — aucun étage choisi","vac.routes_state_missing_space":"l'espace de la carte a été supprimé","vac.routes_state_none":"aucune donnée de carte","vac.routes_empty":"Aucune carte n'est encore assignée à un étage.","vac.route_map_default":"sans identifiant","vac.route_active":"Active","vac.route_space":"Espace","vac.route_space_none":"non sélectionné","vac.route_status_ready":"prête","vac.route_status_needs_calibration":"calibrage requis","vac.route_status_ambiguous":"ambiguë","vac.route_status_missing_space":"espace supprimé","vac.route_missing_space_group":"Espace supprimé","vac.route_add_current":"Ajouter la carte actuelle","vac.route_delete":"Supprimer la carte","vac.route_delete_title":"Retirer la carte de son étage ?","vac.route_delete_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_delete_confirm":"Supprimer","vac.route_space_title":"Déplacer la carte vers un autre espace ?","vac.route_space_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_space_confirm":"Déplacer","vac.route_missing_space_hint":"Une carte pointe vers un espace supprimé : choisissez-en un autre ou supprimez la carte. D'ici là, le robot n'est pas dessiné pour cette carte.","vac.route_default_hint":"La source ne fournit pas d'identifiant de carte stable. Plusieurs étages ne peuvent pas être distingués sans une autre source ou la carte sélectionnée du robot.","vac.route_target_hint":"La station reste dans l'espace « {space} » quelle que soit la carte actuelle.","vac.route_add_source":"Ajouter une source de carte","vac.route_add_source_hint":"Pour les intégrations qui donnent à chaque carte sa propre caméra. La section « Toutes les caméras » ci-dessus élargit cette liste.","vac.route_source_no_map":"aucune carte signalée"}};function So(e,s,i){return t(xo[e]?.[s]??ko[s]??s,i)}function Mo(t,e,s,i,o){return{markerId:t,source:i,mapId:o,space:e.length?"":s}}function Do(t,e,s){return{...t,space:s.has(e)?e:""}}function Co(t,e=Math.random){const s=new Set(t);for(let t=0;t<64;t+=1){const t="vr_"+Math.floor(16777215*e()).toString(36).padStart(5,"0");if(!s.has(t))return t}return"vr_"+Date.now().toString(36)}function Po(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const Io=new WeakMap,To=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function zo(t,i,o){const u=t.host,_=a(u.hass,u._config?.language),m=(t,e)=>So(_,t,e),g=i.marker?.vacuum||{},f=Array.isArray(g.map_routes),b=u._vacSource(i)||"",v=e(i.id,g,i.space,b),y=(u._serverCfg?.spaces||[]).filter(t=>"string"==typeof t?.id&&!!t.id).map(t=>({id:t.id,name:String(t.name||t.id)})),$=new Set(y.map(t=>t.id)),w=n(v,[b],t=>u._vacObservedMapId(i,t)),k=r({routes:v,observed:w,spaceIds:$}),x="ready"===k.kind||"needs_calibration"===k.kind||"missing_space"===k.kind?k.route.id:"",S=b?w[b]:void 0,M=async e=>{let o=f?g.map_routes??null:null;if(!o&&(o=function(t,e,i,o){if(!i)return null;const a=t?.calibration;if(!a||"object"!=typeof a)return null;const n=new Set,r=[];for(const t of Object.keys(a)){const l=s(a[t]);if(!l)continue;const h=o(n);n.add(h),r.push({id:h,source:i,map_id:t,space:e,calibration:l})}return r.length?r:null}(g,i.space,b,t=>Co(t))??[],!b&&Object.keys(g.calibration||{}).length))return!1;const a=e(o);return!!a&&(async e=>{const s=u._serverCfg;if(!s)return!1;const o=JSON.parse(JSON.stringify(s));o.markers=o.markers||[];let a=o.markers.find(t=>t.id===i.id);if(!a){if("device"!==i.bindingKind&&"entity"!==i.bindingKind||!i.bindingRef)return!1;a={id:i.id,binding:`${i.bindingKind}:${i.bindingRef}`,space:i.space||null,area:i.area||null,hidden:!!i.hidden},o.markers.push(a)}a.vacuum={...a.vacuum||{},map_routes:e},delete a.vacuum.calibration;const n=c(s,o,u._cfgContentFingerprint,u._cfgRev,d);u._serverCfg=o,u._regSignature="",u._maybeRebuildDevices(),u.requestUpdate(),u._saveConfigDebounced.pending()&&u._saveConfigDebounced.cancel();try{return await t._saveConfigNow(),!0}catch(t){return p(u,n,d),u._regSignature="",u._maybeRebuildDevices(),u.requestUpdate(),u._showToast(u._t("toast.cfg_save_failed",{err:u._errText(t)})),!1}})(a)},D=o.candidates.filter(t=>t.entityId!==b&&!v.some(e=>e.source===t.entityId)),C=async(t,e)=>{if(!e||e===t.space)return;await u._confirmDanger({key:"vacuum_route_space",kind:"warning",title:m("vac.route_space_title"),message:m("vac.route_space_body"),objectName:t.map_id||m("vac.route_map_default"),confirmLabel:m("vac.route_space_confirm"),cancelLabel:u._t("btn.cancel")})&&await M(s=>function(t,e,s,i){return t.map(t=>t.id===e?{...t,id:i,space:s,calibration:null}:t)}(s,t.id,e,Co(new Set(v.map(t=>t.id)))))},P=new Map(y.map((t,e)=>[t.id,e])),I=(t,e)=>t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)||t.id.localeCompare(e.id),T=v.filter(t=>$.has(t.space)).sort((t,e)=>(P.get(t.space)??0)-(P.get(e.space)??0)||I(t,e)),z=v.filter(t=>!$.has(t.space)).sort(I),R=[...T,...z],A=!!b&&void 0!==S&&!v.some(t=>t.source===b&&t.map_id===S);let F=Io.get(t);const N=F?.source||"",H=F?.mapId||"",L=!!F&&v.some(t=>t.source===N&&t.map_id===H);F&&(F.markerId!==i.id||u._vacObservedMapId(i,F.source)!==F.mapId||L&&!F.saving)&&(Io.delete(t),F=void 0),F?.space&&!$.has(F.space)&&(F=Do(F,"",$),Io.set(t,F));const E=e=>h`
  • ${e.map_id||m("vac.route_map_default")} @@ -35,7 +35,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    - `}}const tc=(t,e)=>t[0]*e[1]-t[1]*e[0],ec=(t,e)=>t[0]*e[0]+t[1]*e[1],sc=(t,e)=>[t[0]-e[0],t[1]-e[1]],ic=(t,e,s)=>[t[0]+e[0]*s,t[1]+e[1]*s];function oc(t,e,s){return Math.abs(tc(t,e))<=s}function ac(t,e,s){return Math.abs(tc(sc(t,e),s))}function nc(t,e,s,i,o){const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(!(r>o&&s>0))return[];const l=[a/r,n/r];return function(t,e,s){const i=e.map(([e,s])=>[Math.max(0,Math.min(e,s)),Math.min(t,Math.max(e,s))]).filter(([t,e])=>e>t+s).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),o=[];for(const t of i){const e=o[o.length-1];!e||t[0]>e[1]+s?o.push([...t]):e[1]=Math.max(e[1],t[1])}const a=[];let n=0;for(const[t,e]of o)t>n+s&&a.push([n,t]),n=Math.max(n,e);return t>n+s&&a.push([n,t]),a}(r,i.flatMap(e=>{const i=e.b[0]-e.a[0],a=e.b[1]-e.a[1],n=Math.hypot(i,a);if(!(n>o&&oc(l,[i/n,a/n],1e-6)))return[];if(ac(e.a,t,l)>1.1*Math.max(s,o)||ac(e.b,t,l)>1.1*Math.max(s,o))return[];return[[ec(sc(e.a,t),l),ec(sc(e.b,t),l)]]}),o).flatMap(([e,i])=>{const o=Vt({a:ic(t,l,e),b:ic(t,l,i),halfDepth:s});return o?[o]:[]})}function rc(t){const e=t.coordScale??1,s=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),i=[];for(const s of t.rooms||[]){if(!s?.id)continue;const o=et(t.rooms,s.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!o||o.poly.length<3)continue;const a=Ut(o.poly,o.offsets);!a||a.length<3||i.push({roomId:s.id,profile:o,inner:a})}i.sort((t,e)=>t.roomId.localeCompare(e.roomId));const o=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,s=[Math.cos(e),Math.sin(e)],i=Math.max(0,t.length)/2;return{a:ic([t.x,t.y],s,-i),b:ic([t.x,t.y],s,i)}}),a=[];for(const i of Kt(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of nc(i.a,i.b,i.depthUnits/2,o,s))a.push({body:t});const n=new Map;for(const e of t.partitionCuts||[]){const t=n.get(e.hostId)||[];t.push(e),n.set(e.hostId,t)}for(const e of t.partitions||[]){const i=$(e.cm,t.cellCm,t.gridPitch)/2;for(const t of nc(e.a,e.b,i,n.get(e.id)||[],s))a.push({body:t,partitionId:e.id})}return{rooms:i,boundaries:a,epsilon:s}}function lc(t,e,s,i){const o=t.profile.offsets[e];if(!(o>0))return null;const a=function(t,e){const s=t[e],i=t[(e+1)%t.length],o=i[0]-s[0],a=i[1]-s[1],n=Math.hypot(o,a)||1;return function(t){let e=0;for(let s=0;s=0?[-a/n,o/n]:[a/n,-o/n]}(t.profile.poly,e),n=ic(s.center,a,o),r=[];for(let e=0;ei&&oc(s.axis,[l[0]/h,l[1]/h],1e-6)))continue;if(ac(o,n,s.axis)>i||ac(a,n,s.axis)>i)continue;const c=ec(sc(o,n),s.axis),d=ec(sc(a,n),s.axis);r.push([Math.min(c,d),Math.max(c,d)])}const l=function(t,e){t.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);const s=[];for(const i of t){const t=s[s.length-1];!t||i[0]>t[1]+e?s.push([...i]):t[1]=Math.max(t[1],i[1])}return s}(r,i).find(([t,e])=>t<=i&&e>=-i);if(!l)return null;const[h,c]=l,d=ic(n,s.axis,-s.half),p=ic(n,s.axis,s.half),u=Math.max(0,-s.half-h),_=Math.max(0,c-s.half),m=u>0?ic(n,s.axis,h):d,g=_>0?ic(n,s.axis,c):p,f=ec(a,s.normal)>=0?1:-1,b=(e,i,o)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:s.axis,labelNormal:a,distance:o,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:b(d,m,u),right:b(p,g,_)}}function hc(t){const e=ic(t.center,t.axis,-t.half),s=ic(t.center,t.axis,t.half),i=ic(t.center,t.axis,Math.min(-t.half,t.targetLo)),o=ic(t.center,t.axis,Math.max(t.half,t.targetHi)),a=(e,s)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(s[0]-e[0],s[1]-e[1]),source:"host-end"});return[a(e,i),a(s,o)]}function cc(t,e,s,i){const o=sc(s,e),a=ec(o,o);if(!(a>i*i))return Math.hypot(...sc(t,e))<=i;const n=ec(sc(t,e),o)/a;if(n<-i||n>1+i)return!1;const r=ic(e,o,Math.max(0,Math.min(1,n)));return Math.hypot(...sc(t,r))<=i}function dc(t,e,s){let i=!1;for(let o=0,a=e.length-1;ot[1]!=h>t[1]&&t[0]<(l-n)*(t[1]-r)/(h-r)+n&&(i=!i)}return i}function pc(t,e,s,i,o,a){const n=sc(i,s),r=tc(e,n);if(Math.abs(r)<=a)return null;const l=sc(s,t),h=tc(l,n)/r,c=tc(l,e)/r;return h<-a||h>o+a||c<-a||c>1+a?null:Math.max(0,Math.min(o,h))}function uc(t,e,s){const i=hc(s),o="partition"===t.host?.kind?t.host.id:void 0;return[{base:i[0],direction:[-s.axis[0],-s.axis[1]]},{base:i[1],direction:s.axis}].map(({base:t,direction:s})=>{const i=t.distance,a=function(t,e,s,i,o,a){let n=null;for(const r of i)if(!o||r.partitionId!==o){if(dc(t,r.body,a))return 0;for(let i=0;iec(sc(t,o),s));return{center:o,axis:s,normal:i,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...a),targetHi:Math.max(...a)}}(t),i=e.rooms.flatMap(t=>{const i=function(t,e,s){const{profile:i}=t;let o=null;for(let t=0;t0))continue;const a=i.poly[t],n=i.poly[(t+1)%i.poly.length],r=sc(n,a),l=Math.hypot(r[0],r[1]);if(!(l>s&&oc(e.axis,[r[0]/l,r[1]/l],1e-6)))continue;if(ac(a,e.center,e.axis)>s||ac(n,e.center,e.axis)>s)continue;const h=ec(sc(a,e.center),e.axis),c=ec(sc(n,e.center),e.axis),d=Math.min(h,c),p=Math.max(h,c);if(d>-e.half+s||p0?d:p<0?-p:0);(!o||u2)return hc(s);if(i.length){const t=i.map(({room:t,edge:i})=>lc(t,i,s,e.epsilon));if(t.some(t=>!t))return hc(s);const o=t;return[...o.map(t=>t.left),...o.map(t=>t.right)]}return uc(t,e,s)}const mc="1.73.0-beta.1",gc={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon"},fc={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon"},bc=2e3,vc=1e3,yc=(t,e,s,i)=>{for(t.delete(e),t.set(e,s);t.size>i;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},$c=1e3,wc=2e3,kc=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}},xc="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";class Sc{constructor(t){this.host=t,this._junctionBaselineCache=new WeakMap,this._resizePreviewNodes=null,this._resizeBaselineLimits=[],this._resizeBaseFrameStable=!0,this._supportPreviewGeneration=0,this._decorAssetGuardReplace=null,this._undoGeometry=()=>{if(this.host._physicalDrag||this.host._physicalRotate)return void this._cancelPhysicalGesture();if(this.host._decorDraft)return this.host._decorDraft=null,void this.host.requestUpdate();if(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)return void this._cancelDecorGesture();if(this.host._resize.dragging)return void this._rszCancelDrag();const t=this.host._geometryHistory.undo();t&&(this._applyGeometryState(t.before,!0)?this.host._showToast(this.host._t("history.undone",{name:t.name})):this.host._geometryHistory.clear())},this._redoGeometry=()=>{if(this.host._physicalDrag||this.host._physicalRotate)return void this._cancelPhysicalGesture();if(this.host._decorDraft)return this.host._decorDraft=null,void this.host.requestUpdate();if(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)return void this._cancelDecorGesture();if(this.host._resize.dragging)return void this._rszCancelDrag();const t=this.host._geometryHistory.redo();t&&(this._applyGeometryState(t.after,!0)?this.host._showToast(this.host._t("history.redone",{name:t.name})):this.host._geometryHistory.clear())},this._savePhysicalDialog=()=>{const t=this.host._physicalDialog,e=this.host._curSpaceCfg,s=this.host._spaceModel();if(!t||!e||!s)return;const i=ao(t.cm);if(null==i)return void this._showPhysicalRange("column"===t.kind?Jt:100,"column"===t.kind?1:0);const o=this.host._imperial?2.54*i:i,a="column"===t.kind?Jt:100,n="column"===t.kind?1:0;if(!Number.isFinite(o)||oa)return void this._showPhysicalRange(a,n);if("column"===t.kind){const e=s.wall_columns.find(e=>e.id===t.id);if(!e)return;const i=ao(t.angle||"0");if("circle"!==t.shape&&(null==i||i<0||i>=90))return void this.host._showToast(this.host._t("toast.physical_angle"));const a="circle"===t.shape?{id:t.id,shape:"circle",center:e.center,cm:o}:{id:t.id,shape:"square",center:e.center,cm:o,angle:i};if(s.wall_columns.some(e=>e.id!==t.id&&Yt(e,a,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"))}const r=this._geometrySnapshot();if("partition"===t.kind){const s=(e.partitions||[]).find(e=>e.id===t.id);if(s&&0===o&&Xt(e.openings,{kind:"partition",id:t.id}))return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"));s&&(s.cm=o)}else if("column"===t.kind){const s=(e.wall_columns||[]).find(e=>e.id===t.id);s&&(s.cm=Zt(o),s.shape="circle"===t.shape?"circle":"square","square"===s.shape?s.angle=ao(t.angle||"0"):delete s.angle)}else{const s=(e.room_drafts||[]).find(e=>e.id===t.id);s?.segments?.[t.segment||0]&&(s.segments[t.segment||0].cm=o)}const l=this._commitPhysicalGeometry(this.host._t("history.physical_edit"),r);this.host._physicalDialog=null,l||this.host.requestUpdate()},this._deletePhysicalSelection=async()=>{const t=this.host._physicalSel,e=this.host._curSpaceCfg;if(!t||!e)return;if("draft"===t.kind)return void await this._deleteDraftWhole();const s=this._geometrySnapshot();if("partition"===t.kind){const s=(e.openings||[]).filter(e=>"partition"===e.host?.kind&&e.host.id===t.id).sort((t,e)=>(t.host?.t||0)-(e.host?.t||0));if(s.length)return void(this.host._partitionDeleteDialog={id:t.id,openings:s.map(t=>JSON.parse(JSON.stringify(t)))})}const i="partition"===t.kind?"partitions":"column"===t.kind?"wall_columns":"room_drafts";e[i]=(e[i]||[]).filter(e=>e.id!==t.id),e[i].length||delete e[i],this.host._activeDraftId===t.id&&this._cancelPath(),this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),s)},this._confirmPartitionDelete=()=>{const t=this.host._partitionDeleteDialog,e=this.host._curSpaceCfg;if(!t||!e)return;const s=this._geometrySnapshot();e.partitions=(e.partitions||[]).filter(e=>e.id!==t.id),e.partitions.length||delete e.partitions,e.openings=(e.openings||[]).filter(e=>"partition"!==e.host?.kind||e.host.id!==t.id),e.openings.length||delete e.openings,this.host._partitionDeleteDialog=null,this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),s)},this._deleteDraftWhole=async()=>{const t="draft"===this.host._physicalDialog?.kind?this.host._physicalDialog.id:"draft"===this.host._physicalSel?.kind?this.host._physicalSel.id:null,e=this.host._space;if(!t||!this.host._curSpaceCfg)return;if(!await this.host._confirmDanger({key:"delete-draft",kind:"destructive",title:this.host._t("confirm.delete_draft_title"),message:this.host._t("confirm.delete_draft_body"),confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")})||this.host._space!==e)return;const s=this.host._curSpaceCfg;if(!s||!(s.room_drafts||[]).some(e=>e.id===t))return;const i=this._geometrySnapshot();s.room_drafts=(s.room_drafts||[]).filter(e=>e.id!==t),s.room_drafts.length||delete s.room_drafts,this.host._activeDraftId===t&&this._cancelPath(),this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),i)},this._deleteDraftSegment=async()=>{const t=this.host._physicalDialog,e=this.host._space;if(!t||"draft"!==t.kind||!this.host._curSpaceCfg)return;const s=t.id,i=t.segment||0,o=await this.host._confirmDanger({key:"delete-draft-segment",kind:"destructive",title:this.host._t("confirm.delete_draft_segment_title"),message:this.host._t("confirm.delete_draft_segment_body"),confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),a=this.host._physicalDialog;if(!o||this.host._space!==e||"draft"!==a?.kind||a.id!==s||(a.segment||0)!==i)return;const n=this.host._curSpaceCfg;if(!n)return;const r=(n.room_drafts||[]).findIndex(t=>t.id===s);if(r<0)return;const l=n.room_drafts[r];if(!Array.isArray(l.segments)||!Number.isInteger(i)||i<0||i>=l.segments.length)return;const h=i,c=[],d=l.points.slice(0,h+1),p=l.points.slice(h+1);if(d.length>=2&&c.push({id:l.id,points:d,segments:l.segments.slice(0,h)}),p.length>=2&&c.push({id:c.length?`${l.id}-${Date.now().toString(36)}`:l.id,points:p,segments:l.segments.slice(h+1)}),2===c.length&&n.room_drafts.length>=200)return void this.host._showToast(this.host._t("toast.physical_limit"));const u=this._geometrySnapshot();n.room_drafts.splice(r,1,...c),n.room_drafts.length||delete n.room_drafts,this.host._activeDraftId===l.id&&this._cancelPath(),this.host._physicalDialog=null,this.host._physicalSel=c.length?{kind:"draft",id:c[0].id}:null,this._commitPhysicalGeometry(this.host._t("history.draft_segment_delete"),u)},this._furnShiftListener=t=>{if("Shift"!==t.key)return;const e=this.host._furnPreviewInput;if(!e)return;const s="keydown"===t.type;e.free!==s&&(this.host._furnPreviewInput={...e,free:s},this.host.requestUpdate())},this._furnShiftAttached=!1,this._confirmRoomDelete=t=>{const e=this.host._roomDeleteDialog,s=this.host._curSpaceCfg,i=this.host._spaceModel();if(!e||!s||!i)return;const o=i.rooms.find(t=>t.id===e.roomId);if(!o)return void(this.host._roomDeleteDialog=null);const a=this.host._openCuts(),n=Ph(ct(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,$c).filter(t=>t.roomId===o.id),i.partitions,this.host._openingsR.map(t=>({...t,x:t.rx,y:t.ry})),.02*this.host._gridPitch),r=new Set(n.materialize.filter(t=>!t.reusePartitionId).map(t=>t.interval.key)).size;if(t&&(s.partitions||[]).length+r>wc)return void this.host._showToast(this.host._t("toast.physical_limit"));const l=this._geometrySnapshot(),h=Qt(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,$c);if(t){s.partitions||=[];const t=new Map,e=new Map,i=t=>{const e=(s.wall_segments||[]).find(e=>{const s=[Number(e.a?.[0])*$c,Number(e.a?.[1])*$c],i=[Number(e.b?.[0])*$c,Number(e.b?.[1])*$c];return this._samePt(t.a,s)&&this._samePt(t.b,i)||this._samePt(t.a,i)&&this._samePt(t.b,s)});return"string"==typeof e?.id&&e.id?e.id:null},o=Date.now().toString(36);for(const a of n.materialize){let n=a.reusePartitionId?s.partitions.find(t=>t.id===a.reusePartitionId):e.get(a.interval.key);n||(n={id:i(a.interval)||`partition-room-${o}-${e.size}`,a:[a.interval.a[0]/$c,a.interval.a[1]/$c],b:[a.interval.b[0]/$c,a.interval.b[1]/$c],cm:a.interval.cm},s.partitions.push(n),e.set(a.interval.key,n)),t.set(a.interval.key,n)}for(const e of s.openings||[]){const s=n.openingIntervals.get(e.id),i=s?t.get(s):null,o=this.host._openingsR.find(t=>t.id===e.id);if(!i||!o)continue;const a={a:[i.a[0]*$c,i.a[1]*$c],b:[i.b[0]*$c,i.b[1]*$c]};e.host={kind:"partition",id:i.id,t:Ih([o.rx,o.ry],a)}}}else if(n.removeOpeningIds.length){const t=new Set(n.removeOpeningIds);s.openings=(s.openings||[]).filter(e=>!t.has(e.id)),s.openings.length||delete s.openings}s.rooms=s.rooms.filter(t=>t.id!==o.id),this.host._cfgEpoch++;const c=this.host._normalizeWalls(h,this.host._openCuts());c.length?s.walls=c:delete s.walls,this.host._roomDeleteDialog=null,this._commitPhysicalGeometry(this.host._t(t?"history.delete_room_keep_walls":"history.delete_room_with_walls"),l),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate()},this._rebindPartitionOpening=()=>{const t=this.host._openingDialog;if(!t?.id)return;const e=t.id;this._activateMarkupTool("opening"),"opening"===this.host._tool&&(this.host._openingRebindId=e,this.host._openingPreset={type:t.type,lengthCm:t.lengthCm,flipH:t.flipH,flipV:t.flipV,revision:++this.host._openingPresetRevision},this.host._openingDialog=null,this.host._openingHoverCandidate=null)},this._deviceInboxTabKey=t=>{if("ArrowLeft"!==t.key&&"ArrowRight"!==t.key)return;const e=this.host._deviceInbox;if(!e)return;const s=["on_plan","available","hidden","readd"],i="ArrowRight"===t.key?1:-1,o=(s.indexOf(e.tab)+i+s.length)%s.length;this.host._deviceInbox={...e,tab:s[o],limit:100,onlyNew:!1},t.preventDefault()},this._keepClosedAsPartitions=()=>{if(this.host._wallFaceBatch)return void this._decideWallFace(!1);if(!this.host._contourClosed||this.host._pendingSplit||!this.host._curSpaceCfg)return;const t=this.host._curSpaceCfg,e=this.host._path.slice(0,-1);if((t.partitions||[]).length+e.length>wc)return void this.host._showToast(this.host._t("toast.physical_limit"));const s=this._geometrySnapshot(),i=sh(e.length,[...this.host._draftSegmentCms,this.host._closingWallCm??void 0],this.host._drawWallCm,dt);t.partitions||=[];const o=Date.now().toString(36),a=this.host._activeDraftId?(t.room_drafts||[]).find(t=>t.id===this.host._activeDraftId):null,n=this._draftSegmentsForPath(this.host._path,a,i);for(let s=0;st.id!==this.host._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._commitPhysicalGeometry(this.host._t("history.contour_to_partitions"),s),this.host._roomDialog=!1,this.host._path=[],delete this.host._resumeDraftBySpace[this.host._space],this.host._activeDraftId=null,this.host._draftSegmentCms=[],this.host._closingWallCm=null},this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,saved:t?.plans||[],savedBusy:!1})}catch(t){const e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}},this._openSettingsDialog=()=>{if(!this.host._norm)return;const t=this.host._glowRadiusCm,e=this.host._imperial?Math.round(t/30.48*10)/10:Math.round(t)/100;this.host._settingsDialog={colors:JSON.parse(JSON.stringify(this.host._fillColors)),glowRadius:e,bgColor:ae(this.host._settings,{bgColor:null})||null,northDeg:oe(this.host._settings,{}),bgMode:ie(this.host._settings,{}),sunRays:se(this.host._settings,{}),showRoomTooltip:ee(this.host._settings),zigbeeTopology:te(this.host._settings),busy:!1}},this._openSupportDialog=()=>{this.host._norm&&this.host._canEdit&&(clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this._supportPreviewGeneration+=1,this.host._supportDialog={draftId:qh("draft"),idempotencyKey:qh("report"),submissionFingerprint:"",contact:"",message:"",attach:!1,status:"idle",preview:null,rawOpen:!1,errorCode:"",reportId:""})},this._openAlignDialog=()=>this._previewAlignDialog(!1),this._toggleOptimizeLivePositions=()=>{const t=this.host._alignDialog;t&&!t.busy&&t.report.liveMissingPositions.length&&this._previewAlignDialog(!t.removeLiveMissingPositions)},this._openBackupExport=()=>{this.host._settingsDialog=null,this.host._backupExportDialog={kind:"full",planOnly:!1,busy:!1,error:""}},this._decorStylePersistTimer=null,this._openRulesDialog=()=>{if(!this.host._norm)return;const t=this.host._settings.icon_rules,e=(t&&t.length?t:ne).map(t=>({...t}));this.host._rulesDialog={rules:e,test:"",busy:!1}},this._discoveryPreviewMemo=null,this._decorImages=new Qh(t,{decorSnap:(t,e)=>this._decorSnap(t,e),geometrySnapshot:()=>this._geometrySnapshot(),clearFurniturePreview:()=>this._clearFurniturePreview(),recordGeometry:(t,e)=>this._recordGeometry(t,e),saveConfig:()=>this._saveConfig(),saveShape:()=>this._decorSaveShape(),setGuardReplace:t=>{this._decorAssetGuardReplace=t},furnShiftDetach:()=>this._furnShiftDetach(),furnPick:t=>this._furnPick(t),furnFieldValue:t=>this._furnFieldValue(t),furnFieldToCm:t=>this._furnFieldToCm(t)}),t._editorSecondary=new Eh({root:()=>t.renderRoot,requestUpdate:()=>t.requestUpdate(),updateComplete:()=>t.updateComplete,clearTip:()=>{t._tip=null}}),t._resize=new Ya}_routeLiveEditorUpdate(t,e){const s=Oo(this.host,t,e);return!s&&this.host._resize.preview&&(this._resizeBaseFrameStable=!1),s}_commitLiveEditor(){!function(t){const e=t,s=Ho(t);s.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(s.raf),s.raf=0,Go(s);const i=e.renderRoot?.querySelector("[data-hp-live-editor]");i&&u(l,i);const o=e.renderRoot?.querySelector("[data-hp-live-editor-html]");if(o){const t=e._viewOr(e._baseVb());u(e._renderLiveEditorMeasurements(t),o)}Lo(s,s.requestedRevision)}(this.host)}_disposeLiveEditor(){!function(t){zo(t);const e=Ro.get(t);e&&(e.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e.raf),Go(e),Lo(e,e.requestedRevision),Ro.delete(t))}(this.host)}async _whenLiveEditorSettled(){await this.host.updateComplete,await function(t){const e=Ro.get(t);if(!e||!e.raf||e.paintedRevision>=e.requestedRevision)return Promise.resolve();const s=e.requestedRevision;return new Promise(t=>e.waiters.push({revision:s,resolve:t}))}(this.host)}_queuePointerMove(t,e){Io(this.host,t,e)}_flushPointerMove(t){To(this.host,t)}_cancelPointerMove(t){zo(this.host,t)}_help(t){const e=`${t}.aria`,s=a(this.host.hass,this.host._config?.language);return re(s,t)&&re(s,e)?h``:l}_setMode(t,e=!0){t!==this.host._mode&&this.host._cancelDangerConfirm(),this.host._endTabDrag(),this._clearFurniturePreview(),this.host._pendingNavMode=null;const s=this.host._spaceModel();if(!s)return this.host._cancelModeTransition(!1),void(this.host._mode="view");if(this.host._kiosk&&"view"!==t)return;if(this.host._mode===t){if(!e&&"view"===t&&this.host._modeTransitionBusy){const e=this.host._currentModeVisual(t),s=this.host._modeTransitionTargetZoom,i=this.host._modeTransitionTargetCenterX,o=this.host._modeTransitionTargetCenterY;this.host._cancelModeTransition(!1),this.host._commitViewModeAtomic(e,s,i,o)}return}if("devices"===this.host._mode&&this.host._cancelDeviceDrag(),this.host._bootSoftCancel(),("plan"===t||"decor"===t)&&!this.host._norm)return void this.host._showToast(this.host._t("toast.markup_needs_server"));if(this.host._wallFaceBatch&&this._roomDialogCancel(),"plan"===this.host._mode&&"draw"===this.host._tool&&!this._finishWallChain())return;this.host._clearTransientHover(!0),this.host._cancelDevicePressFeedback();const i=this.host._mode,o=this.host._effectiveProjection(),a=this.host._currentModeVisual(i),n=this.host._modeTransitionBusy,r=a&&"view"!==i&&"view"!==t?{...a,toolbarContentOpacity:this.host._reducedMotion?1:.35}:a;this.host._cancelModeTransition(!1),this.host._editorSecondary.closeForNavigation(),(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)&&this._cancelDecorGesture();const l=!s.bg&&"view"===t!=("view"===i),h=n&&"view"===i&&"view"!==t?this.host._modeTransitionEditorCamera:null;let c=h?.zoom??(n?this.host._modeTransitionTargetZoom:this.host._zoom),d=h?h.centerX:n?this.host._modeTransitionTargetCenterX:r?.viewport.centerX,p=h?h.centerY:n?this.host._modeTransitionTargetCenterY:r?.viewport.centerY;if("view"===i&&"view"!==t&&!n){const e=this.host._view;if(this.host._viewModeSnap={space:this.host._space,zoom:this.host._zoom,cx:e?this.host._logicalViewCenter(o)?.x:void 0,cy:e?this.host._logicalViewCenter(o)?.y:void 0},"iso"===o){const e=this.host._logicalViewCenter("iso");d=e?.x,p=e?.y,this.host._view=null,this.host._mode=t,this.host._applyView(this.host._zoom,e?.x,e?.y)}l&&(c=1,d=void 0,p=void 0)}if("plan"===i&&this.host._activeDraftId&&(this.host._resumeDraftBySpace[this.host._space]=this.host._activeDraftId),this.host._mode=t,"devices"===i&&"devices"!==t&&(this.host._showHidden=!1,this.host._deviceInbox=null,this.host._deviceInboxReturn=null,this.host._deviceInboxMemo=null),this.host._editorChromeMode="view"===t?i:t,"view"===t){"view"===i||n||(this.host._modeTransitionEditorCamera={zoom:this.host._zoom,centerX:r?.viewport.centerX,centerY:r?.viewport.centerY});const t=this.host._viewModeSnap;if(t&&t.space===this.host._space){c=t.zoom;const e=this.host._labsIso&&"iso"===this.host._viewPreference[this.host._space]?"iso":"flat",s=null!=t.cx&&null!=t.cy&&"iso"===e?le([t.cx,t.cy],0):null;d=s?.[0]??t.cx,p=s?.[1]??t.cy}else t&&(c=this.host._zoomBySpace[this.host._space]||1,d=void 0,p=void 0)}else this.host._modeTransitionEditorCamera={zoom:c,centerX:d,centerY:p};this.host._modeTransitionTargetZoom=c,this.host._modeTransitionTargetCenterX=d,this.host._modeTransitionTargetCenterY=p,("iso"===o||"view"===t&&this.host._labsIso&&"iso"===this.host._viewPreference[this.host._space])&&(this.host._modeTransitionForceAtomic=!0);const u=++this.host._modeTransitionRequest;e?r?(this.host._modeTransitionPreparing=!0,this.host._modeTransitionVisual=r,this.host._prepareModeTransition(u,r,t,c,d,p)):(this.host._modeTransitionPreparing=!1,this.host._modeTransitionVisual=null,this.host._zoom=c,this.host._view=null,requestAnimationFrame(()=>{this.host.isConnected&&u===this.host._modeTransitionRequest&&this.host._mode===t&&(this.host._applyView(c,d,p),"view"===t&&(this.host._viewModeSnap=null,this.host._modeTransitionEditorCamera=null),this.host.requestUpdate())})):"view"===t&&this.host._commitViewModeAtomic(r,c,d,p),this.host._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this.host._tool="draw",this.host._mergeSel=null,this.host._mergeDialog=null,this.host._splitSel=null,this.host._pendingSplit=null,this.host._selId=null,this.host._physicalSel=null,this.host._physicalDialog=null,this.host._physicalDrag=null,this._rszResetController(),this.host._tip=null,this.host._hoverRoom=null,this.host._decorDraft=null,this.host._decorSel=null,this.host._decorMove=null,this.host._backdropDialog=null,this.host._decorTool="select",this.host._bdDrag=null,this.host._dtDrag=null,this.host._dtBox=null,"plan"===t&&(this._primeDrawWallField(),this._resumeLastDraft()),this.host._saveNav()}_primeDrawWallField(){null===this.host._drawWallField&&(this.host._drawWallField=he(dt,this.host._imperial))}_showPhysicalRange(t=this.host._drawWallMaxCm,e=0){this.host._showToast(this.host._t("toast.physical_range",{min:he(e,this.host._imperial),max:he(t,this.host._imperial),unit:this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_draftSegmentCount(t=this.host._curSpaceCfg){return(t?.room_drafts||[]).reduce((t,e)=>t+(Array.isArray(e.segments)?e.segments.length:0),0)}_mergeSpacePartitions(t,e){const s=t?.partitions||[];if(s.length<2)return 0;const i=jr(s,{pitch:E,seedIds:e,geometry:Ur(t,{excludeDraftId:this.host._activeDraftId})});return i.merged?(t.partitions=i.partitions,qr(t.openings,t.partitions,i.openingMoves,{coordScale:$c,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch}),i.merged):0}_finishWallChain(){if("draw"!==this.host._tool||this.host._wallFaceBatch||this.host._roomDialog)return!0;const t=this.host._curSpaceCfg;if(!t||this.host._path.length<2)return this.host._path=[],this.host._activeDraftId=null,this.host._draftSegmentCms=[],this.host._closingWallCm=null,this._clearPlanSnapHover(),!0;const e=ih(this.host._path,sh(this.host._path.length-1,this.host._draftSegmentCms,this.host._drawWallCm,dt)),s=e.length;if((t.partitions||[]).length+s>wc)return this.host._showToast(this.host._t("toast.physical_limit")),!1;const i=this._geometrySnapshot();t.partitions||=[];const o=Date.now().toString(36),a=[],n=this.host._activeDraftId?(t.room_drafts||[]).find(t=>t.id===this.host._activeDraftId):null,r=this._draftSegmentsForPath(this.host._path,n,e.map(t=>t.cm));for(let i=0;it.id!==this.host._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._commitPhysicalGeometry(this.host._t("history.wall_chain_finish"),i),delete this.host._resumeDraftBySpace[this.host._space],this.host._path=[],this.host._activeDraftId=null,this.host._draftSegmentCms=[],this.host._closingWallCm=null,this._clearPlanSnapHover(),!0}_activateMarkupTool(t){t!==this.host._tool&&(this.host._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this.host._tool||this._finishWallChain())&&(this._cancelPath(),"resize"===this.host._tool&&(this.host._resize.dragging?this._rszCancelDrag():this.host._resize.reset()),this.host._tool=t,"draw"===t&&this._resumeLastDraft(),"resize"===t&&this.host._resize.selectRoom(null),"wallthick"===t&&(this.host._wallDialog=null)))}_limitReached(t){const e=this.host._curSpaceCfg;if(!e)return!0;const s="draft"===t?(e.room_drafts||[]).length>=200:"partition"===t?(e.partitions||[]).length>=wc:(e.wall_columns||[]).length>=500;return s&&this.host._showToast(this.host._t("toast.physical_limit")),s}_svgPoint(t){const e=this.host.renderRoot.querySelector(".stage").getBoundingClientRect();return this.host._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this.host._gridPitch;return[ce(de(t[0],e)),ce(de(t[1],e))]}_snapDrawPoint(t,e=!1){const s=this.host._path[this.host._path.length-1],i=e&&s?pe(s,t,this.host._gridPitch,Qi):t;return this._snap(i)}_planSnapOpeningCuts(t,e){if(!this.host._openingsR.length)return[];const s=this.host._openingWallIndexFor(t,e).value,i=[];for(const e of this.host._roomWallOpeningInputs(this.host._openingsR,t)){const t=bt(s,e);if(!t.negative&&!t.positive)continue;const o=e.angle*Math.PI/180,a=Math.cos(o)*e.length/2,n=Math.sin(o)*e.length/2;i.push([e.x-a,e.y-n,e.x+a,e.y+n])}return i}_planSnapGeometrySnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this.host._space,this.host._cfgEpoch,this.host._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this.host._planSnapGeometryCache?.key===e)return this.host._planSnapGeometryCache;const s=this.host._openCuts(),i=Vl({space:t,activeDraftId:this.host._activeDraftId,roomCuts:this._planSnapOpeningCuts(t,s),partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this.host._gridPitch});return this.host._planSnapGeometryCache={key:e,value:i},this.host._planSnapGeometryCache}_hiddenWallDiagnosticSnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|hidden-empty`,value:{segments:[],endpoints:[]}};const e=["hidden",this.host._space,this.host._cfgEpoch,this.host._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this.host._hiddenWallDiagnosticCache?.key===e)return this.host._hiddenWallDiagnosticCache;const s=Kl({space:t,activeDraftId:this.host._activeDraftId,epsilon:2e-4*this.host._gridPitch});return this.host._hiddenWallDiagnosticCache={key:e,value:s},this.host._hiddenWallDiagnosticCache}_planStructuralGeometrySnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this.host._space,this.host._cfgEpoch,this.host._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this.host._planStructuralGeometryCache?.key===e)return this.host._planStructuralGeometryCache;const s=Vl({space:t,activeDraftId:this.host._activeDraftId,epsilon:2e-4*this.host._gridPitch});return this.host._planStructuralGeometryCache={key:e,value:s},this.host._planStructuralGeometryCache}_planSnapContextKey(t){const e=this.host._path[0],s=this.host._path[this.host._path.length-1];return[t,this.host._tool,this.host._path.length,e?`${e[0]},${e[1]}`:"",s?`${s[0]},${s[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const s=this._planSnapGeometrySnapshot(),i=this.host._path[this.host._path.length-1],o="draw"===this.host._tool&&this.host._path.length>=3?[{point:this.host._path[0],key:"closure:first-point"}]:[],a={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this.host._gridPitch,excludePoints:i?[i]:[],extraEndpoints:o,epsilon:2e-4*this.host._gridPitch},n=e&&i?th(s.value,t,{...a,anchor:i}):function(t,e,s){if(!(El(e)&&s.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const i=s.epsilon??Ll,o=s.excludePoints||[],a=Zl(Xl(t,e,s),s.distinguishTolerance||0);if(a)return a;let n=null;for(const a of t.segments){const t=[a.a[0],a.a[1],a.b[0],a.b[1]],r=Ht([e[0],e[1]],t);if(r>s.tolerance)continue;const l=Ql(a,e,s.gridStep);!Jl(l,o,i)&&Yl(r,a.key,n)&&(n={kind:"line",point:l,key:a.key,distance:r,segment:a})}return n?{kind:"resolved",candidate:n,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(s.value,t,a),r="resolved"===n.kind?n.candidate:null,l=r?[...r.point]:this._snapDrawPoint(t,e),h=i?ue(i,l):l;return{point:h,candidate:r&&O(h,r.point)?r:null,conflicts:"ambiguous"===n.kind?n.conflicts:[],ambiguous:"ambiguous"===n.kind,contextKey:this._planSnapContextKey(s.key)}}_clearPlanSnapHover(t=!0){this.host._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this.host._cursorPt=null)}_samePt(t,e){return O(t,e)}_dropLegacySegments(t=this.host._serverCfg){for(const e of t?.markers||[])"ripple"===e.display&&(e.display="icon_ripple");for(const e of t?.spaces||[]){delete e.segments;const t=new Set,s=e=>"string"==typeof e&&e.length>=1&&e.length<=64&&!t.has(e),i=e=>(t.add(e),!0),o=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=jt);if(Array.isArray(e.partitions)&&(e.partitions=e.partitions.filter(t=>t&&s(t.id)&&o(t.a)&&o(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&i(t.id)).map(t=>({...t,cm:Number.isFinite(Number(t.cm))?Math.max(0,Math.min(100,Number(t.cm))):15})),e.partitions.length||delete e.partitions),Array.isArray(e.wall_columns)&&(e.wall_columns=e.wall_columns.filter(t=>t&&s(t.id)&&o(t.center)&&i(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:Zt(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:_e(t.angle)}})),e.wall_columns.length||delete e.wall_columns),Array.isArray(e.room_drafts)&&(e.room_drafts=e.room_drafts.filter(t=>t&&s(t.id)&&Array.isArray(t.points)&&t.points.length>=2&&t.points.every(o)&&i(t.id)).map(t=>{const e=_n(t);return{id:t.id,...e}}).filter(t=>t.points.length>=2),e.room_drafts.length||delete e.room_drafts),Array.isArray(e.walls)){const t=me(zt({spaces:[e]}),e.id),s=t?ge(e,t,$c,.02*xt).contour.map(t=>t.map(t=>t/$c)):j(e.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);e.walls=St(e.walls,e.rooms||[],E,1,s),e.walls.length||delete e.walls}}}_rollbackRejectedPhysicalWrites(t){if(!this.host._serverCfg||!t.length)return!1;let e=!1;for(const[s]of t){const t=this.host._pendingPhysicalWrites.get(s);t&&(e=this._restoreGeometryStateInConfig(this.host._serverCfg,t.before)||e,this.host._pendingPhysicalWrites.delete(s))}return!!e&&(this._clearGeometryGesture(),this.host._geometryHistory.clear(),this.host._cfgEpoch++,this.host._modelCache=null,this.host._wallUnionCache=null,this.host._physicalBodiesCache=null,this.host._frame=null,this.host._regSignature="",this.host._cfgContentFingerprint=d(this.host._serverCfg),this.host._maybeRebuildDevices(),this.host.requestUpdate(),!0)}async _reloadRejectedPhysicalWrite(){const t=this.host._writeChain;await t.catch(()=>{}),await this.host._reloadConfigOnly(!0)}_prepareConfigCandidate(t){return this._dropLegacySegments(t),fe(t)}_writeConfig(t=null){this.host._writesPending++,this.host._writeChain=be(this.host._writeChain,async()=>{if(!this.host._serverCfg)return;const e=d(this.host._serverCfg),s=this._prepareConfigCandidate(this.host._serverCfg),i=d(s);t&&e===t.attemptedFingerprint&&Object.assign(t,{revision:this.host._cfgRev,attempted:s,attemptedFingerprint:i});const o=[...this.host._pendingPhysicalWrites.entries()];for(const[t,e]of o){const i=s.spaces.find(e=>e.id===t),o=Y(i);if(o===e.fingerprint)continue;let a=!1;try{a=this.host._checkSpacePhysicalGeometry(s,t).ok}catch{a=!1}if(!a)throw this._restoreGeometryStateLocal(e.before),this.host._pendingPhysicalWrites.delete(t),this.host._geometryHistory.clear(),this.host._showToast(this.host._t("toast.geometry_unsafe")),Object.assign(new Error("unsafe wall geometry"),{code:"geometry-unsafe"});e.fingerprint=o}i!==d(this.host._serverCfg)&&(this.host._serverCfg=s),this.host._cfgContentFingerprint=i;try{await this.host._sendConfigCandidate(s)}catch(t){if(!this._rollbackRejectedPhysicalWrites(o))throw t;const e=t&&"object"==typeof t?t:Object.assign(new Error(String(t)),{cause:t});throw e.physicalGeometryRolledBack=!0,e}for(const[t,e]of o)this.host._pendingPhysicalWrites.get(t)?.fingerprint===e.fingerprint&&this.host._pendingPhysicalWrites.delete(t)});return this.host._writeChain.finally(()=>{this.host._writesPending--})}_saveConfig(){this.host._cfgEpoch++,this.host._saveConfigDebounced()}_geometrySnapshotFromConfig(t,e){const s=t?.spaces?.find(t=>t.id===e);if(!s)return null;const i=t=>JSON.parse(JSON.stringify(t)),o={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==s[t]&&(o[t]=s[t]);return{spaceId:e,rooms:i(s.rooms||[]),...Array.isArray(s.openings)?{openings:i(s.openings)}:{},...Array.isArray(s.walls)?{walls:i(s.walls)}:{},...Array.isArray(s.wall_segments)?{wall_segments:i(s.wall_segments)}:{},...Array.isArray(s.open_spans)?{open_spans:i(s.open_spans)}:{},...Array.isArray(s.room_drafts)?{room_drafts:i(s.room_drafts)}:{},...Array.isArray(s.partitions)?{partitions:i(s.partitions)}:{},...Array.isArray(s.wall_columns)?{wall_columns:i(s.wall_columns)}:{},...Array.isArray(s.decor)?{decor:i(s.decor)}:{},plan_transform:o}}_geometrySnapshot(t=this.host._space){return this._geometrySnapshotFromConfig(this.host._serverCfg,t)}_recordGeometry(t,e){if(!e)return;const s=this._geometrySnapshot(e.spaceId);s&&JSON.stringify(e)!==JSON.stringify(s)&&(this.host._geometryHistory.push({name:t,before:e,after:s}),this.host.requestUpdate())}_restoreGeometryStateInConfig(t,e,s=!1){const i=t?.spaces?.find(t=>t.id===e.spaceId);if(!i)return!1;const o=t=>JSON.parse(JSON.stringify(t)),a=new Map((i.rooms||[]).map(t=>[t.id,t]));if(i.rooms=o(e.rooms),s)for(const t of i.rooms){const e=a.get(t.id);!Array.isArray(t.wall_ids)&&Array.isArray(e?.wall_ids)&&e.wall_ids.length===t.poly?.length&&(t.wall_ids=o(e.wall_ids))}const n=(t,e)=>{void 0!==e?i[t]=o(e):s&&"wall_segments"===t||delete i[t]},r=new Map((i.openings||[]).map(t=>[t.id,t])),l=new Map((i.room_drafts||[]).map(t=>[t.id,t]));if(n("openings",e.openings),n("walls",e.walls),n("wall_segments",e.wall_segments),n("open_spans",e.open_spans),n("room_drafts",e.room_drafts),n("partitions",e.partitions),n("wall_columns",e.wall_columns),n("decor",e.decor),s){for(const t of i.openings||[]){const e=r.get(t.id);t.host||"wall"!==e?.host?.kind||(t.host=o(e.host))}for(const t of i.room_drafts||[]){const e=l.get(t.id);for(let s=0;s<(t.segments||[]).length;s++)!t.segments[s]?.id&&e?.segments?.[s]?.id&&(t.segments[s].id=e.segments[s].id)}}for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete i[t];return Object.assign(i,o(e.plan_transform||{})),!0}_restoreGeometryStateLocal(t){return!!this._restoreGeometryStateInConfig(this.host._serverCfg,t)&&(this.host._cfgEpoch++,this.host._modelCache=null,this.host._wallUnionCache=null,this.host._physicalBodiesCache=null,this.host._frame=null,this.host.requestUpdate(),!0)}_wallModelBlockerLabel(t){const e=t instanceof nn?t.reason:"invalid-room";return this.host._t(`wall_model.reason.${e}`)}_hasLegacyZeroWallFields(t=this.host._serverCfg){return(t?.spaces||[]).some(t=>Array.isArray(t?.open_spans)&&t.open_spans.length>0||(t?.rooms||[]).some(t=>Array.isArray(t?.open_to)&&t.open_to.length>0))}_showWallModelMigrationBlocked(t){const e=this._hasLegacyZeroWallFields()?"toast.zero_wall_migration_blocked":"toast.wall_model_migration_blocked";this.host._showToast(this.host._t(e,{reason:this._wallModelBlockerLabel(t)}))}_limitSegmentsOf(t){const e=[];for(const s of t?.wall_segments||[])s?.a&&s?.b&&e.push({id:String(s.id||""),a:s.a,b:s.b,cm:Number(s.cm)});for(const s of t?.partitions||[])s?.a&&s?.b&&e.push({id:String(s.id||""),a:s.a,b:s.b,cm:Number(s.cm)});for(const s of t?.room_drafts||[]){const t=Array.isArray(s?.points)?s.points:[],i=Array.isArray(s?.segments)?s.segments:[];for(let o=0;o+1t?.id===e);return o?function(t,e,s,i,o){const a=(t?.spaces||[]).find(t=>t?.id===e);if(!a)return[];const n=Number(a.cell_cm)>0?Number(a.cell_cm):5,r=[...br(s),...kr(s,n,E),...Sr(s,n,E)];let l=i?.multiWallNodes||null;if(!l)try{l=it(a.rooms||[],a.walls||[],[],E,n,E,1)}catch{l=null}const h=i&&"lightweight"!==i.status?i:null;let c="ok"===h?.status||"degraded-extra"===h?.status?h.roomGeom:null;const d=null===i||"lightweight"===i?.status;if(!c&&!d&&l?.nodes.length)try{const t=ot(a.rooms||[],a.walls||[],[],[],E,n,E,1);c="ok"===t?.status||"degraded-extra"===t?.status?t.roomGeom:null}catch{c=null}for(const t of a.rooms||[]){const e=String(t?.id||"");if(!e||o&&!o.has(e))continue;let s=null;try{s=at(a.rooms||[],e,a.walls||[],[],E,n,E,1,d?null:c??void 0,l)}catch{s=null}r.push(...Mr(e,s,n,E))}return r}(t,e,this._limitSegmentsOf(o),s,i):[]}_junctionLimitLabel(t){const e=t=>String(Math.round(10*t)/10);return this.host._t(`junction.limit_${t.rule}`,{actual:e(t.actual),limit:e(t.limit)})}_junctionLimitsIntroduced(t,e,s,i,o){const a=o?.length?new Set(o):void 0;let n;const r=(e.spaces||[]).find(t=>t?.id===s);let l="";try{l=Y(r)}catch{l=""}const h=!a&&e&&"object"==typeof e?this._junctionBaselineCache.get(e):void 0;if(h&&l&&h.fingerprint===l&&h.spaceId===s&&(n=h.violations),!n){try{const t=Number(e?.model_version||0)>=9?e:Tn(e).config;n=this.host._junctionLimitViolations(t,s,a?null:void 0,a)}catch{return[]}!a&&e&&"object"==typeof e&&l&&this._junctionBaselineCache.set(e,{spaceId:s,fingerprint:l,violations:n})}let c=[],d=n;try{c=this.host._junctionLimitViolations(t,s,i,a),a&&(d=n.filter(t=>"clearance"!==t.rule||a.has(t.subject)))}catch{return[{rule:"check_failed",subject:s,actual:0,limit:0}]}return Dr(c,d)}_commitPhysicalGeometry(t,e,s=[]){if(!e||!this.host._serverCfg)return!1;const i=this.host._serverCfg,o=this._geometrySnapshotFromConfig(i,e.spaceId),a=i.spaces.find(t=>t.id===e.spaceId);if(!a||Y(e)===Y(a))return!1;let n,r=!1;try{r=this.host._checkSpacePhysicalGeometry(i,e.spaceId).ok}catch{r=!1}if(!r)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;let l=e;try{if(Number(i.model_version||0)<9){const t=JSON.parse(JSON.stringify(i));if(!this._restoreGeometryStateInConfig(t,e))throw new nn("invalid-room",e.spaceId);const s=Tn(t).config;l=this._geometrySnapshotFromConfig(s,e.spaceId)||e;const a=JSON.parse(JSON.stringify(s));if(!o||!this._restoreGeometryStateInConfig(a,o,!0))throw new nn("invalid-room",e.spaceId);const r=s.spaces.find(t=>t.id===e.spaceId),h=a.spaces.find(t=>t.id===e.spaceId);if(!Array.isArray(o.wall_segments)&&JSON.stringify(e.rooms)===JSON.stringify(o.rooms))for(const t of h?.wall_segments||[])t.cm=J(o.walls,t.a,t.b,E,1);const c=((t,e,s)=>{const i=new Map,o=new Map((t?.rooms||[]).map(t=>[t.id,t])),a=new Map((e||[]).map(t=>[t.id,t])),{rooms:n}=Mn(s,xn(t));for(const t of n){const e=a.get(t.id),n=o.get(t.id),r=W(e),l=(s.rooms||[]).find(e=>e.id===t.id),h=W(l),c=W(n);if(r&&h&&c&&r.length===h.length&&c.length===n?.wall_ids?.length&&t.poly.length===t.wall_ids.length)for(let e=0;e{const o=[];for(let a=0;aan||fn(r,s,i)>an)continue;const l=gn(n,s,i),h=gn(r,s,i);l<-1e-9||h>1+an||h<=l+an||o.push({start:l,id:e[a]})}return o.sort((t,e)=>t.start-e.start)},o=s(c,n.wall_ids,r[e],r[(e+1)%r.length]),a=s(t.poly,t.wall_ids,h[e],h[(e+1)%h.length]);if(o.length&&o.length===a.length)for(let t=0;tt.id===e.spaceId),i=this.host._path.length>=2?this.host._path.map(t=>[t[0]/$c,t[1]/$c]):[];i.push(...s.map(t=>[t[0],t[1]])),h=mn(t)<=mn(l,i)&&this.host._checkSpacePhysicalGeometry(n,e.spaceId).ok}catch{h=!1}if(!h)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;const c=JSON.parse(JSON.stringify(i));this._restoreGeometryStateInConfig(c,e);const d=this._junctionLimitsIntroduced(n,c,e.spaceId);if(d.length)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this._junctionLimitLabel(d[0])),!1;Rn(i,n),this._recordGeometry(t,l);const p=i.spaces.find(t=>t.id===e.spaceId),u=this.host._pendingPhysicalWrites.get(e.spaceId);return this.host._pendingPhysicalWrites.set(e.spaceId,{before:u?.before||l,fingerprint:Y(p)}),this._saveConfig(),!0}_clearGeometryGesture(){this._clearFurniturePreview(),this.host._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this.host._mergeSel=null,this.host._mergeDialog=null,this.host._splitSel=null,this.host._pendingSplit=null,this.host._wallFaceBatch=null,this.host._wallRepairDiagnostic=null,this.host._roomDeleteDialog=null,this.host._wallDialog=null,this.host._physicalDialog=null,this.host._physicalSel=null,this.host._physicalDrag=null,this.host._physicalRotate=null,this.host._activeDraftId=null,this.host._draftSegmentCms=[],this.host._closingWallCm=null,this.host._openingDialog=null,this._rszResetController(),this.host._decorDraft=null,this.host._decorMove=null,this.host._dtDrag=null,this.host._bdDrag=null}_stagePointerCancel(t){return clearTimeout(this.host._kioskHoldTimer),this.host._swipeStart?.id===t.pointerId&&(this.host._swipeStart=null),this.host._furnTouchPending?.pid===t.pointerId?(this._clearFurniturePreview(),this.host._pointers.delete(t.pointerId),void this.host.requestUpdate()):this.host._physicalDrag?.pid!==t.pointerId&&this.host._physicalRotate?.pid!==t.pointerId?this.host._decorDraft?.pid===t.pointerId?(this.host._decorDraft=null,void this.host.requestUpdate()):void(this.host._decorMove?.pid!==t.pointerId&&this.host._dtDrag?.pid!==t.pointerId&&this.host._bdDrag?.pid!==t.pointerId?("opening"===this.host._tool?(this.host._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this.host._tool&&this._clearPlanSnapHover(),this.host._pointers.delete(t.pointerId),this.host._pointers.size<2&&(this.host._pinchStart=null),0===this.host._pointers.size&&(this.host._panStart=null,this.host._panLock=null),this.host._viewportGestureDirty&&0===this.host._pointers.size&&(this.host._viewportGestureDirty=!1,this.host.requestUpdate())):this._cancelDecorGesture()):void this._cancelPhysicalGesture()}_applyGeometryState(t,e=!1){if(!this.host._canCommitSpace(t.spaceId))return!1;const s=this._geometrySnapshot(t.spaceId);if(!s||!this._restoreGeometryStateLocal(t))return!1;const i=this.host._serverCfg,o=Y(s)!==Y(t);if(o){let o=!1;try{const s=i?this.host._checkSpacePhysicalGeometry(i,t.spaceId):null;o=!!s?.ok||!(!e||"wall-degraded-extra"!==s?.reason)}catch{o=!1}if(!o)return this._restoreGeometryStateLocal(s),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1}let a;try{a=Tn(i).config}catch(t){return this._restoreGeometryStateLocal(s),this._showWallModelMigrationBlocked(t),!1}if(o){let o=!1;try{const s=a?this.host._checkSpacePhysicalGeometry(a,t.spaceId):null;o=!!s?.ok||!(!e||"wall-degraded-extra"!==s?.reason)}catch{o=!1}if(!o)return this._restoreGeometryStateLocal(s),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;Rn(i,a);const n=i?.spaces.find(e=>e.id===t.spaceId),r=this.host._pendingPhysicalWrites.get(t.spaceId);this.host._pendingPhysicalWrites.set(t.spaceId,{before:r?.before||s,fingerprint:Y(n)})}else Rn(i,a);return this._clearGeometryGesture(),this.host._space!==t.spaceId&&(this.host._commitSpace(t.spaceId),this.host._saveNav(),this.host._restoreZoom()),this.host._modelCache=null,this.host._frame=null,this.host._regSignature="",this.host._maybeRebuildDevices(),this._saveConfig(),this.host.requestUpdate(),!0}_roomAt(t){return this.host._spaceModel()?.rooms.find(e=>{const s=W(e);return!!s&&ve(t,s)})}_overlapRoom(t){return this.host._spaceModel()?.rooms.find(e=>{const s=W(e);return!!s&&N(t,s)})}_pointInRoom(t,e){return e.poly?ye(t,e.poly):null!=e.x&&t[0]>=e.x&&t[0]<=e.x+e.w&&t[1]>=e.y&&t[1]<=e.y+e.h}_contourSelfIntersects(t){if(!ka(t))return!0;const e=t.length,s=.001;for(let i=0;i=500)return this.host._showToast(this.host._t("toast.physical_limit")),!1;const t=this.host._curSpaceCfg;return!(!this.host._activeDraftId&&(t?.room_drafts||[]).length>=200||this._draftSegmentCount(t)>=2e3||(t?.partitions||[]).length+this.host._path.length>wc)||(this.host._showToast(this.host._t("toast.physical_limit")),!1)}_markupClick(t){if(this.host._vacFit)return;if(!this.host._markup)return;const e=this.host._spaceModel();if(!e)return void this._clearGeometryGesture();if(this.host._suppressClick)return;if(this.host._drag||this.host._rlResize)return;const s=t.composedPath?.()||[];if(s.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(s.some(t=>t?.classList?.contains?.("physical-hit")))return;const i=this._svgPoint(t);if("select"===this.host._tool)return void(this.host._physicalSel=null);if("resize"===this.host._tool){if(this.host._resize.dragging||s.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(i,t));return this.host._resize.selectRoom(t?.id||null),void this.host.requestUpdate()}if("delroom"===this.host._tool)return void this._deleteRoomClick(i);if("opening"===this.host._tool)return void this._openingClick(i);if("merge"===this.host._tool)return void this._mergeClick(i);if("wallthick"===this.host._tool)return void this._wallThickClick(i);if("split"===this.host._tool)return void this._splitClick(i);if("column"===this.host._tool)return void this._columnClick(i);this.host._wallRepairDiagnostic=null;const o=this._resolvePlanDrawPoint(i,t.shiftKey);if(o.ambiguous)return this.host._planSnapHover={contextKey:o.contextKey,candidate:null,conflicts:o.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(o.conflicts),void this.host._showToast(this.host._t("toast.plan_snap_ambiguous"));let a=o.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this.host._path.length<3)return;a=ue(this.host._path[this.host._path.length-1],this.host._path[0])}if(!this.host._path.length){if(!t.shiftKey&&!o.candidate&&this._offerExistingWallFace(i))return;const e=this._draftEndAt(a);return e?(this.host._activeDraftId=e.draft.id,this.host._resumeDraftBySpace[this.host._space]=e.draft.id,this.host._path=e.reverse?[...e.draft.points].reverse().map(t=>[...t]):e.draft.points.map(t=>[...t]),void(this.host._draftSegmentCms=this._adoptDraftCms(this.host._path,e.reverse?[...e.draft.segments].reverse().map(t=>t.cm):e.draft.segments.map(t=>t.cm),e.draft.id))):(this.host._activeDraftId=null,this.host._draftSegmentCms=[],void(this.host._path=[a]))}const n=this.host._path[this.host._path.length-1];if(this._samePt(a,n))return;const r=this._draftEndAt(a,this.host._activeDraftId||void 0);if(r)return void this._mergeDraftEndpoint(r);if(!this._canAppendRoomDraftPoint())return;const l=this.host._drawWallCm;if(null==l)return void this._showPhysicalRange(100);const h=this.host._path.map(t=>[...t]);this.host._path=[...this.host._path,a],this.host._draftSegmentCms=[...this.host._draftSegmentCms,l],this._persistActiveDraftSegment(),this._offerWallFaces(h)}_draftEndAt(t,e){const s=this.host._spaceModel();if(!s)return null;const i=this.host._viewOr(this.host._baseVb()),o=Math.max(.15*this.host._gridPitch,this.host._stageEl?.clientWidth?i.w/this.host._stageEl.clientWidth*12:0);for(const i of s.room_drafts||[]){if(i.id===e)continue;if(i.points.length<2)continue;const s=i.points[0],a=i.points[i.points.length-1];if(Math.hypot(t[0]-a[0],t[1]-a[1])<=o)return{draft:i,reverse:!1};if(Math.hypot(t[0]-s[0],t[1]-s[1])<=o)return{draft:i,reverse:!0}}return null}_mergeDraftEndpoint(t){const e=this.host._curSpaceCfg;if(!e||!this.host._path.length)return;const s=this.host._path.map(t=>[...t]),i=this._wallGraphSources(s),o=Array.isArray(e.room_drafts)?e.room_drafts:[],a=this.host._activeDraftId?o.find(t=>t.id===this.host._activeDraftId):null,n=o.find(e=>e.id===t.draft.id);if(!n)return;const r=t.reverse?t.draft.points.map(t=>[...t]):[...t.draft.points].reverse().map(t=>[...t]),l=t.reverse?(n.segments||[]).map(t=>({...t})):[...n.segments||[]].reverse().map(t=>({...t})),h=this.host._path[this.host._path.length-1],c=this._samePt(h,r[0]),d=c?null:this.host._drawWallCm;if(!c&&null==d)return void this._showPhysicalRange(100);const p=this._draftSegmentsForPath(this.host._path,a,this.host._draftSegmentCms),u=[...this.host._path.map(t=>[...t]),...c?r.slice(1):r],_=[...p,...null==d?[]:[{cm:d}],...l],m=u.length>=4&&this._samePt(u[0],u[u.length-1]),g=u,f=_;if(g.length>500)return void this.host._showToast(this.host._t("toast.physical_limit"));const b=(a?.segments?.length||0)+(n.segments?.length||0);if(this._draftSegmentCount(e)-b+f.length>2e3)return void this.host._showToast(this.host._t("toast.physical_limit"));if(m){const t=g.slice(0,-1);if(this._contourSelfIntersects(t)||L(t)<=1e-6)return void this.host._showToast(this.host._t("toast.contour_cannot_close"));const e=this._overlapRoom(t);if(e)return void this.host._showToast(this.host._t("toast.room_overlap",{name:e.name||""}))}const v=this._geometrySnapshot(),y=this.host._activeDraftId||t.draft.id,$={...a||n,id:y,points:g.map(t=>[t[0]/$c,t[1]/$c]),segments:f};e.room_drafts=o.filter(e=>e.id!==t.draft.id&&(!this.host._activeDraftId||e.id!==this.host._activeDraftId)),e.room_drafts.push($),this.host._activeDraftId=y,this.host._resumeDraftBySpace[this.host._space]=y,this.host._path=g,this.host._draftSegmentCms=this._adoptDraftCms(g,f.map(t=>Number(t.cm)),y),this.host._physicalSel=null,this._commitPhysicalGeometry(this.host._t("history.draft_merge"),v),null!=d&&this._offerWallFaces(s,s.length-1,i)}_adoptDraftCms(t,e,s){const i=Math.max(0,t.length-1),o=sh(i,e,this.host._drawWallCm,dt);return e.length!==i&&console.debug(`[houseplan] draft ${s??"?"}: восстановлено толщин ${i-e.length} (#234)`),o}_draftSegmentsForPath(t,e,s){const i=Array.isArray(e?.points)?e.points.map(t=>[Number(t?.[0])*$c,Number(t?.[1])*$c]):[],o=Array.isArray(e?.segments)?e.segments:[];return sh(Math.max(0,t.length-1),s,this.host._drawWallCm,dt).map((e,s)=>{const a=t[s],n=t[s+1],r=i.findIndex((t,e)=>{if(e+1>=i.length)return!1;const s=i[e+1];return this._samePt(a,t)&&this._samePt(n,s)||this._samePt(a,s)&&this._samePt(n,t)});return{...r>=0?o[r]:{},cm:e}})}_persistActiveDraftSegment(){if(this.host._path.length<2||!this.host._curSpaceCfg)return;const t=this._geometrySnapshot(),e=this.host._curSpaceCfg;e.room_drafts||=[],this.host._activeDraftId||(this.host._activeDraftId="draft-"+Date.now().toString(36)),this.host._resumeDraftBySpace[this.host._space]=this.host._activeDraftId;const s=e.room_drafts.findIndex(t=>t.id===this.host._activeDraftId),i={...s>=0?e.room_drafts[s]:{},id:this.host._activeDraftId,points:this.host._path.map(t=>[t[0]/$c,t[1]/$c]),segments:this._draftSegmentsForPath(this.host._path,s>=0?e.room_drafts[s]:null,this.host._draftSegmentCms)};s>=0?e.room_drafts[s]=i:e.room_drafts.push(i),Zn(this,this.host._t("history.draft_segment"),t)}_activeWallSourceKey(t){return`active:${this.host._activeDraftId||"session"}:${t}`}_wallGraphSources(t){const e=this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}));for(let s=0;s+1t.key===s);if(i>=0){const[t]=this.host._wallFaceGraphCache.splice(i,1);return this.host._wallFaceGraphCache.push(t),t.value}const o=Sh(t,e);return this.host._wallFaceGraphCache.push({key:s,value:o}),this.host._wallFaceGraphCache.length>4&&this.host._wallFaceGraphCache.shift(),o}_offerWallFaces(t,e=this.host._path.length-2,s){if(this.host._path.length<2||this.host._wallFaceBatch||this.host._roomDialog)return;const i=this.host._spaceModel();if(!i)return;const o=this._activeWallSourceKey(e),a=2e-4*this.host._gridPitch;let n,r;try{const e=s||this._wallGraphSources(t);r=this._wallGraphSources(this.host._path),n=function(t,e,s){const i=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!i.has(t.key)&&t.sourceKeys.includes(s))}(this._wallFaceGraph(e,a),this._wallFaceGraph(r,a),o)}catch{return}if(!n.length){const t=Hh(r,{requiredSourceKey:o,maxDistance:$(2,this.host._cellCm,this.host._gridPitch),gridStep:this.host._gridPitch,epsilon:a});return"ambiguous"===t.kind?(this.host._wallRepairDiagnostic=t.proposals[0]||null,void this.host._showToast(this.host._t(0===this.host._drawWallCm?"toast.zero_wall_ambiguous":"toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of i.rooms){const e=W(t);if(!t.id||!e)continue;const s=$e(e,this.host._path,.02*this.host._gridPitch);if(!s)continue;const[i,o]=s,a=L(i)>=L(o)?i:o,r=a===i?o:i,l=[...n].sort((t,e)=>Math.abs(t.area-L(r))-Math.abs(e.area-L(r))||t.key.localeCompare(e.key))[0];if(!l)return;return void this._beginWallFaceBatch([{...l,ring:r.map(t=>[t[0],t[1]]),split:{roomId:t.id,mainPoly:a,newPoly:r},consumeAllActive:!0}])}const l=n.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this.host._wallRepairDiagnostic=null,this.host._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this.host._path.map(t=>[...t]),activeCms:[...this.host._draftSegmentCms],activeDraftId:this.host._activeDraftId},this._clearPlanSnapHover(),this.host._nameSel="",this.host._areaSel="",this._resetRoomDialogFields(),this.host._roomDialog=!0}_offerExistingWallFace(t){if(this.host._path.length||this.host._wallFaceBatch||this.host._roomDialog)return!1;const e=2e-4*this.host._gridPitch;try{let s,i=Mh(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!i){const o=Hh(this._wallGraphSources([]),{point:t,maxDistance:$(2,this.host._cellCm,this.host._gridPitch),gridStep:this.host._gridPitch,epsilon:e});if("ambiguous"===o.kind)return this.host._wallRepairDiagnostic=o.proposals[0]||null,this.host._showToast(this.host._t(0===this.host._drawWallCm?"toast.zero_wall_ambiguous":"toast.wall_repair_ambiguous")),!0;if("repair"===o.kind)i=o.face,s=o.proposal;else if("none"===o.kind){const s=Hh(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this.host._gridPitch,epsilon:e});if("repair"===s.kind)return this.host._wallRepairDiagnostic=s.proposal,this.host._showToast(this.host._t("toast.wall_repair_too_large")),!0}}return!(!i||i.ring.length<3||this._contourSelfIntersects(i.ring)||this._overlapRoom(i.ring))&&(this._beginWallFaceBatch([{...i,existing:!s,repair:s}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),s=this.host._drawWallCm;if(null==s)return void this._showPhysicalRange(Jt,1);if(!this.host._curSpaceCfg||this._limitReached("column"))return;const i=this.host._spaceModel();if(!i)return;const o={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:Zt(s),angle:0},a=(i.wall_columns||[]).find(t=>Yt(t,o,.02*this.host._gridPitch));if(a)return clearTimeout(this.host._duplicateColumnTimer),this.host._duplicateColumnId=a.id,this.host._duplicateColumnTimer=window.setTimeout(()=>{this.host._duplicateColumnId=null},900),void this.host._showToast(this.host._t("toast.column_duplicate"));const n=this._geometrySnapshot(),r=this.host._curSpaceCfg;r.wall_columns||=[],r.wall_columns.push({...o,center:[e[0]/$c,e[1]/$c]}),this._commitPhysicalGeometry(this.host._t("history.column_add"),n)}_openPhysicalDialog(t,e,s){const i=this.host._spaceModel();if(i)if("partition"===t){const s=i.partitions.find(t=>t.id===e);s&&(this.host._physicalDialog={kind:t,id:e,cm:he(s.cm,this.host._imperial),length:this.host._fmtLen(s.a,s.b)})}else if("column"===t){const s=i.wall_columns.find(t=>t.id===e);s&&(this.host._physicalDialog={kind:t,id:e,cm:he(s.cm,this.host._imperial),shape:s.shape,angle:this.host._angleField("square"===s.shape?_e(s.angle):0)})}else{const o=i.room_drafts.find(t=>t.id===e),a=Math.max(0,Math.min(o?.segments.length?o.segments.length-1:0,s||0));o?.segments[a]&&(this.host._physicalDialog={kind:t,id:e,segment:a,cm:he(o.segments[a].cm,this.host._imperial),length:this.host._fmtLen(o.points[a],o.points[a+1])})}}_physicalDown(t,e,s){const i=this.host._spaceModel();if(!i)return;t.stopPropagation(),kc(t);const o=this._svgPoint(t),a=[];for(const t of[...i.wall_columns].reverse())we(o,ke(t,this.host._cellCm,this.host._gridPitch))&&a.push({kind:"column",id:t.id});for(const t of[...i.partitions].reverse()){const e=xe(t.a,t.b,t.cm,this.host._cellCm,this.host._gridPitch);e&&we(o,e)&&a.push({kind:"partition",id:t.id})}a.some(t=>t.kind===e&&t.id===s)||a.unshift({kind:e,id:s});const n=a.map(t=>`${t.kind}:${t.id}`).sort().join("|"),r=performance.now(),l=this.host._physicalPickCycle,h=a.length>1&&l?.signature===n&&r-l.at>380&&r-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%a.length:Math.max(0,a.findIndex(t=>t.kind===e&&t.id===s));this.host._physicalPickCycle={signature:n,index:h,x:t.clientX,y:t.clientY,at:r},e=a[h].kind,s=a[h].id;const c="partition"===e?i.partitions.find(t=>t.id===s):i.wall_columns.find(t=>t.id===s);c&&(this.host._physicalSel={kind:e,id:s},this.host._physicalDrag={pid:t.pointerId,kind:e,id:s,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(c)),delta:[0,0]})}_clampPhysicalDelta(t,e,s){const i="partition"===t?[e.a,e.b]:[e.center],o=i.map(t=>t[0]),a=i.map(t=>t[1]);return[Math.max(-jt*$c-Math.min(...o),Math.min(jt*$c-Math.max(...o),s[0])),Math.max(-jt*$c-Math.min(...a),Math.min(jt*$c-Math.max(...a),s[1]))]}_physicalMove(t){t.stopPropagation(),Io(this.host,"physical",()=>this._physicalMoveNow(t))}_physicalMoveNow(t){const e=this.host._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const s=this._svgPoint(t),i="partition"===e.kind?e.base.a:e.base.center,o=this._snap([i[0]+s[0]-e.start[0],i[1]+s[1]-e.start[1]]),a=this._clampPhysicalDelta(e.kind,e.base,[o[0]-i[0],o[1]-i[1]]);this.host._physicalDrag={...e,delta:a,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){To(this.host,"physical");const e=this.host._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this.host._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const s=this.host._spaceModel();if(!this.host._curSpaceCfg||!s)return;const i=this.host._curSpaceCfg;if("partition"===e.kind){const t=(i.partitions||[]).find(t=>t.id===e.id),s=e.base;if(t){const o={...s,a:[s.a[0]+e.delta[0],s.a[1]+e.delta[1]],b:[s.b[0]+e.delta[0],s.b[1]+e.delta[1]]};t.a=[o.a[0]/$c,o.a[1]/$c],t.b=[o.b[0]/$c,o.b[1]/$c];for(const t of i.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const s=lt(t,[o],$c,this.host._cellCm,this.host._gridPitch).resolved;s&&Object.assign(t,ht(t,s,$c))}}}else{const t=(i.wall_columns||[]).find(t=>t.id===e.id),o=e.base,a={...o,center:[o.center[0]+e.delta[0],o.center[1]+e.delta[1]]};if(s.wall_columns.some(t=>t.id!==e.id&&Yt(t,a,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"));t&&(t.center=[(o.center[0]+e.delta[0])/$c,(o.center[1]+e.delta[1])/$c])}this._commitPhysicalGeometry(this.host._t("history.physical_move"),e.before)}_registerPhysicalTap(t,e,s){const i=performance.now(),o=this.host._physicalLastTap?.kind===t&&this.host._physicalLastTap.id===e&&this.host._physicalLastTap.segment===s&&i-this.host._physicalLastTap.at<=360;this.host._physicalLastTap={kind:t,id:e,segment:s,at:i},o&&(this.host._physicalLastTap=null,this._openPhysicalDialog(t,e,s))}_cancelPhysicalGesture(){zo(this.host,"physical"),zo(this.host,"physical-rotate"),this.host._physicalDrag=null,this.host._physicalRotate=null,this.host.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this.host._spaceModel())return;t.preventDefault(),t.stopPropagation(),kc(t);const s=this._svgPoint(t);this.host._physicalSel={kind:"column",id:e.id},this.host._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(s[1]-e.center[1],s[0]-e.center[0])/Math.PI,baseAngle:_e(e.angle),angle:_e(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){t.preventDefault(),t.stopPropagation(),Io(this.host,"physical-rotate",()=>this._physicalRotateMoveNow(t))}_physicalRotateMoveNow(t){const e=this.host._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const s=this._svgPoint(t),i=180*Math.atan2(s[1]-e.center[1],s[0]-e.center[0])/Math.PI,o=e.baseAngle+i-e.startAngle,a=_e(t.shiftKey?o:5*Math.round(o/5));this.host._physicalRotate={...e,angle:a,moved:e.moved||Math.abs(o-e.baseAngle)>=.5}}_physicalRotateUp(t){To(this.host,"physical-rotate");const e=this.host._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this.host._physicalRotate=null;const s=this.host._spaceModel();if(!e.moved||!this.host._curSpaceCfg||!s)return;const i=s.wall_columns.find(t=>t.id===e.id);if(!i||"square"!==i.shape)return;const o={...i,angle:e.angle};if(s.wall_columns.some(t=>t.id!==e.id&&Yt(t,o,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"));const a=this.host._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);a&&(a.angle=e.angle,this._commitPhysicalGeometry(this.host._t("history.physical_edit"),e.before))}_rszRooms(){const t=[],e=this.host._spaceModel();if(!e)return t;for(const s of e.rooms){const e=s.id?W(s):null;e&&t.push({id:s.id,poly:e,wall_ids:Array.isArray(s.wall_ids)?[...s.wall_ids]:void 0})}return s=t,i=Math.max(1e-12,1e-12*this.host._gridPitch),s.map(t=>{if(!Array.isArray(t.wall_ids)||t.wall_ids.length!==t.poly.length)return{...t,poly:t.poly.map(t=>[...t])};const e=t.poly.map(t=>[...t]);let s=!0;for(;s&&e.length>3;){s=!1;for(let t=0;t0){e.splice(t,1),s=!0;break}}}return{...t,poly:e}});var s,i}_rszOpenings(){return this.host._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen,hosted:!!t.host,angle:t.angle,type:t.type}))}_rszObstacles(){const t=this.host._spaceModel();if(!t)return[];const e=[];for(const s of t.partitions||[])e.push({kind:"segment",a:[...s.a],b:[...s.b],half:$(s.cm,this.host._cellCm,this.host._gridPitch)/2});for(const s of t.room_drafts||[])for(let t=0;t+1Array.isArray(t.a)&&Array.isArray(t.b)&&t.a.length>=2&&t.b.length>=2).map(t=>({wall:t,a:[t.a[0]*$c,t.a[1]*this.host._spaceH],b:[t.b[0]*$c,t.b[1]*this.host._spaceH]})),o=Math.abs(t[0]-e[0])<=.05*this.host._gridPitch?"v":Math.abs(t[1]-e[1])<=.05*this.host._gridPitch?"h":null,a=i.filter(s=>!!o&&("h"===o?!(Math.abs(s.a[1]-t[1])>.05*this.host._gridPitch||Math.abs(s.b[1]-t[1])>.05*this.host._gridPitch)&&Math.min(Math.max(t[0],e[0]),Math.max(s.a[0],s.b[0]))-Math.max(Math.min(t[0],e[0]),Math.min(s.a[0],s.b[0]))>.05*this.host._gridPitch:!(Math.abs(s.a[0]-t[0])>.05*this.host._gridPitch||Math.abs(s.b[0]-t[0])>.05*this.host._gridPitch)&&Math.min(Math.max(t[1],e[1]),Math.max(s.a[1],s.b[1]))-Math.max(Math.min(t[1],e[1]),Math.min(s.a[1],s.b[1]))>.05*this.host._gridPitch)),n=new Set(a.map(t=>Number(t.wall.cm)).filter(t=>t>0));return{minDim:this.host._cmToUnits(30),eps:.05*this.host._gridPitch,step:this.host._gridPitch,movingHalf:s>0?$(s,this.host._cellCm,this.host._gridPitch)/2:0,obstacles:this._rszObstacles(),thicknessConflict:n.size>1}}_rszResolution(t,e,s){const i=this.host._resize.snapshotIdentity||s||this._rszSnapshot(),o=`${this.host._space}|${this.host._cellCm}|${this.host._gridPitch}|${i}`,a=`${t}:${e}`;return this.host._resize.resolve(o,a,()=>{const s=[...this.host._resize.rooms||this._rszRooms()],i=s.find(e=>e.id===t),o=i?.poly?.[e]||[0,0],a=i?.poly?.[(e+1)%(i?.poly?.length||1)]||[0,0];return function(t,e,s,i,o){const{eps:a}=o,n=t.find(t=>t.id===s);if(!n||i<0||i>=(n.poly?.length||0)||n.poly.length<4||!ka(n.poly))return{enabled:!1,reason:"invalid-geometry"};const r=n.poly[i],l=n.poly[(i+1)%n.poly.length],h=Da(r,l,a);if(!h)return{enabled:!1,reason:"diagonal"};if(!Ta(n.poly,i,h,a))return{enabled:!1,reason:"side-angle"};if(o.thicknessConflict)return{enabled:!1,reason:"thickness-conflict"};for(const t of o.obstacles||[])if(Aa(t,r,l,o))return{enabled:!1,reason:"duplicate-physical-wall"};const c=va(ga(l,r)),d=[],p=new Set;let u=!1,_=!1;for(const e of t)if(e.id!==s)for(let t=0;t1||d.length>1)return{enabled:!1,reason:"multiple-rooms"};const m={[s]:i},g=[s];if(1===d.length){const t=d[0];if(!ka(t.room.poly))return{enabled:!1,reason:"invalid-geometry"};if(!Ta(t.room.poly,t.edge,h,a))return{enabled:!1,reason:"side-angle"};g.push(t.room.id),m[t.room.id]=t.edge}const f=[];for(const t of e)if(!($a([t.x,t.y],r,l)>2*a)){if(t.hosted||t.length>c+2*a)return{enabled:!1,reason:"opening-conflict"};f.push(t.id)}const b=Object.fromEntries(g.map(e=>[e,t.find(t=>t.id===e).poly.length])),v=[];for(const e of g){const s=t.find(t=>t.id===e),i=m[e],o=(i-1+s.poly.length)%s.poly.length,n=(i+1)%s.poly.length,r=Ha(t,e,o,1,a),l=Ha(t,e,n,0,a);if(!r||!l)return{enabled:!1,reason:"partial-shared"};v.push(r,l)}const y={roomId:s,edge:i,a:[...r],b:[...l],n:wa(n.poly,i),roomIds:g,edgeByRoom:m,topology:b,movingOpeningIds:f,sideOwnership:v};if(!ja(t,e,y,0,o))return{enabled:!1,reason:"invalid-geometry"};const $=Math.abs(Number(o.step));if(Number.isFinite($)&&$>a){const s=[-$,$];if(!s.some(s=>ja(t,e,y,s,o))){if(!s.some(s=>Oa(Ba(t,e,y,s),y,a)))return{enabled:!1,reason:"partial-shared"};const i={...o,obstacles:[]};return s.some(s=>ja(t,e,y,s,i))?{enabled:!1,reason:"duplicate-physical-wall"}:e.length&&s.some(e=>ja(t,[],y,e,o))?{enabled:!1,reason:"opening-conflict"}:{enabled:!1,reason:"invalid-geometry"}}}return{enabled:!0,plan:y}}(s,[...this.host._resize.openings||this._rszOpenings()],t,e,this._rszOptsFor(o,a))})}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this.host._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszResetController(){const t=null!==this.host._resize.preview;this.host._resize.reset(),t&&this.host._cfgEpoch++}_rszProjectPreview(t,e,s,i,o){this.host._rszLimitViolation=null;const a=this.host._serverCfg?.spaces.find(t=>t.id===this.host._space);if(!a||!this.host._serverCfg)return{ok:!1,reason:"missing-context"};const n=JSON.parse(t),r={...a,rooms:n.rooms,openings:n.openings||[]};for(const t of["walls","wall_segments","open_spans","room_drafts","partitions","wall_columns","decor"])void 0!==n[t]?r[t]=n[t]:delete r[t];for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==n.plan_transform?.[t]?r[t]=n.plan_transform[t]:delete r[t];const l=this.host._spaceH;for(const[t,s]of Object.entries(e)){const e=r.rooms.find(e=>e.id===t);e&&(e.poly=s.map(t=>[t[0]/$c,t[1]/l]),delete e.x,delete e.y,delete e.w,delete e.h)}for(const[t,e]of Object.entries(s)){const s=(r.openings||[]).find(e=>e.id===t);s&&(s.x=e[0]/$c,s.y=e[1]/l)}const h=[],c=[];for(const t of i){const e=o.find(e=>e.id===t),s=r.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const i=s.poly.map(t=>[t[0]*$c,t[1]*l]);if(e.poly.length!==i.length)continue;const a=Array.isArray(e.wall_ids)?e.wall_ids:[];for(let t=0;tt.id===s):null;o&&(o.a=[i[t][0]/$c,i[t][1]/$c],o.b=[i[(t+1)%i.length][0]/$c,i[(t+1)%i.length][1]/$c])}}if(h.length&&Array.isArray(r.walls)&&r.walls.length){const t=Se(r.walls,h,c,this.host._wallKeyPitch,$c,"fixed-topology");if(t.rejected)return{ok:!1,reason:"wall-metadata"};r.walls=t.walls}const d=[];for(const t of r.rooms||[]){const e=W(t);if(e&&!(e.length<2))for(let t=0;tJSON.stringify([t?.key,t?.cm,t?.a,t?.b]),u=new Map;for(const t of n.walls||[]){const e=p(t);u.set(e,(u.get(e)||0)+1)}const _=[];for(const t of r.walls||[]){const e=p(t),s=u.get(e)||0;s?u.set(e,s-1):_.push(t)}if(Me(_,d,this.host._wallKeyPitch,$c,n.walls||[]).length)return{ok:!1,reason:"wall-metadata"};const m=function(t,e,s=1e-8){const i=Za(t),o=new Set(e),a=i.flatMap(t=>{if(!o.has(String(t.id||"")))return[];const e=sn(en(t));return e?[e]:[]});return i.flatMap(t=>{const e=String(t.id||""),i=sn(en(t)),n=!!i&&a.some(t=>i.minX<=t.maxX+s&&i.maxX+s>=t.minX&&i.minY<=t.maxY+s&&i.maxY+s>=t.minY);return e&&(o.has(e)||n)?[e]:[]})}(r.rooms||[],i),g=on(r,m);if(!g||!this._rszSpaceCandidateGeometry(this.host._space,g).ok)return{ok:!1,reason:"physical-geometry"};const f={...this.host._serverCfg,spaces:(this.host._serverCfg?.spaces||[]).map(t=>t?.id===this.host._space?r:t)};try{this._resizePreviewNodes=it(g.rooms,g.walls,[],E,this.host._cellCm,this.host._gridPitch,$c)}catch{this._resizePreviewNodes=null}let b;try{const t=new Set(i),e=this.host._junctionLimitViolations(f,this.host._space,{status:"lightweight",multiWallNodes:this._resizePreviewNodes},t);b=Dr(e,this._resizeBaselineLimits.filter(e=>"clearance"!==e.rule||t.has(e.subject)))}catch{b=[{rule:"check_failed",subject:this.host._space,actual:0,limit:0}]}return b.length?(this.host._rszLimitViolation=b[0],{ok:!1,reason:"junction-limit"}):{ok:!0,value:{preview:{space:this.host._space,sp:r},beforeWalls:n.walls||[],afterWalls:r.walls||[],artifact:null}}}_rszAcceptPreview(t,e){if(this.host._cfgEpoch++,this.host._physicalBodiesCache&&(this.host._physicalBodiesCache.key=`${this.host._space}|${this.host._cfgEpoch}|${this.host._cellCm}|${this.host._gridPitch}`),!t||!e)return;const s=De(e);if(!s)return;const i=`${this.host._space}|${this.host._cfgEpoch}|${t.sp.rooms.length}`;Object.defineProperty(s,"sourceFingerprint",{value:d([t.sp,this.host._cellCm,this.host._gridPitch]),enumerable:!1});const o={key:i,value:s};yc(this.host._wallUnionPool,i,o,8),this.host._wallUnionCache=o}_rszSpaceCandidateGeometry(t,e){if(!this.host._serverCfg)return{ok:!1,wallGeometry:null};const s={...this.host._serverCfg,spaces:this.host._serverCfg.spaces.map(s=>s.id===t?e:s)};let i=null;try{return{ok:this.host._checkSpacePhysicalGeometry(s,t,t=>{i=t}).ok,wallGeometry:i}}catch{return{ok:!1,wallGeometry:null}}}_rszSpaceCandidateRenderable(t,e){if(!this.host._serverCfg)return!1;try{const s={...this.host._serverCfg,spaces:this.host._serverCfg.spaces.map(s=>s.id===t?e:s)};return this.host._checkSpacePhysicalGeometry(s,t).ok}catch{return!1}}_rszCandidateRenderable(t){return!!t&&t.space===this.host._space&&this._rszSpaceCandidateRenderable(t.space,t.sp)}_rszEdgeDown(t,e,s){if("resize"!==this.host._tool||this.host._resize.dragging)return;this._resizeBaseFrameStable=!0,t.stopPropagation(),t.preventDefault();const i=this._rszRooms(),o=this._rszResolution(e,s);if(!o.enabled)return void this.host._showToast(this._rszReasonText(o.reason));kc(t);const a=o.plan;try{this._resizeBaselineLimits=this.host._junctionLimitViolations(this.host._serverCfg,this.host._space,null,new Set(a.roomIds))}catch{this._resizeBaselineLimits=[]}const n=this._svgPoint(t),r=`${this.host._space}|${this.host._cfgEpoch}|${i.length}`,l=this.host._wallUnionCache?.key===r?this.host._wallUnionCache.value:null,h=this._rszSnapshot();this.host._resize.begin({pointerId:t.pointerId,start:[n[0],n[1]],roomId:e,plan:a,options:this._rszOptsFor(a.a,a.b),rooms:i,openings:this._rszOpenings(),snapshotIdentity:h,before:JSON.parse(h),wallUnionBefore:l,epochBefore:this.host._cfgEpoch})}_rszReasonText(t){return this.host._t(`resize.disabled.${t}`)}_rszDisabledActivate(t,e){t.stopPropagation(),t.preventDefault(),this.host._showToast(this._rszReasonText(e))}_rszDisabledKey(t,e){"Enter"!==t.key&&" "!==t.key||this._rszDisabledActivate(t,e)}_rszMove(t){this.host._resize.ownsPointer(t.pointerId)&&(t.stopPropagation(),Io(this.host,"resize",()=>this._rszMoveNow(t)))}_rszMoveNow(t){if(!this.host._resize.ownsPointer(t.pointerId))return;t.stopPropagation();const e=this._svgPoint(t),s=this.host._resize.move({pointerId:t.pointerId,point:[e[0],e[1]],step:this.host._gridPitch,snap:t=>{const e=this._snap(t);return[e[0],e[1]]},project:(t,e,s,i,o)=>this._rszProjectPreview(t,e,s,i,o),publish:(t,e)=>this._rszAcceptPreview(t,e),measure:(t,e)=>this._rszEdgeLabels(t,e)});if("rejected"===s.kind)return s.notify&&this.host._showToast(this.host._rszLimitViolation?`${this.host._t("resize.limit_stopped")} — `+this._junctionLimitLabel(this.host._rszLimitViolation):this.host._t("resize.preview_failed")),void this.host.requestUpdate();"accepted"===s.kind&&this.host.requestUpdate()}_rszUp(t){if(To(this.host,"resize"),!this.host._resize.ownsPointer(t.pointerId))return;t.stopPropagation();const e=this.host._resize.finish({pointerId:t.pointerId,currentSnapshotIdentity:this._rszSnapshot(),validatePreview:t=>this._rszCandidateRenderable(t)});if("no-op"===e.kind)return this.host._cfgEpoch++,void this.host.requestUpdate();if("rejected"===e.kind)return this.host._cfgEpoch++,this.host._showToast(this.host._t("resize.commit_failed")),void this.host.requestUpdate();const s=e.preview,i=this.host._serverCfg?.spaces.find(t=>t.id===s.space);i&&(i.rooms=s.sp.rooms,i.openings=s.sp.openings,Array.isArray(s.sp.walls)&&(s.sp.walls.length?i.walls=s.sp.walls:delete i.walls),Array.isArray(s.sp.wall_segments)&&(i.wall_segments=s.sp.wall_segments)),this.host._suppressClick=!0,setTimeout(()=>this.host._suppressClick=!1,0),this._commitPhysicalGeometry(this.host._t("history.resize_room"),e.before),this.host.requestUpdate()}_rszCancelDrag(t){zo(this.host,"resize");const e=this.host._resize.cancel(this._rszSnapshot(),t);if("no-op"!==e.kind){if(null!==e.restoreEpoch?this.host._cfgEpoch=e.restoreEpoch:this.host._cfgEpoch++,this.host._physicalBodiesCache&&(this.host._physicalBodiesCache.key=`${this.host._space}|${this.host._cfgEpoch}|${this.host._cellCm}|${this.host._gridPitch}`),e.restoreWallUnion){const t=this.host._spaceModel();if(t){const s=`${this.host._space}|${this.host._cfgEpoch}|${t.rooms.length}`,i={key:s,value:e.restoreWallUnion};yc(this.host._wallUnionPool,s,i,8),this.host._wallUnionCache=i}}null!==e.restoreEpoch&&"plan"===this.host._mode&&this._resizeBaseFrameStable&&(this.host._terminalFrame=1),this.host.requestUpdate()}}_rszPointerCancel(t){this.host._resize.ownsPointer(t.pointerId)&&(t.stopPropagation(),this._rszCancelDrag(t.pointerId))}_rszEdgeLabels(t,e,s=this.host._resize.rooms){const i=s,o=[],a=t.polys[e.roomId]||i?.find(t=>t.id===e.roomId).poly;if(!a||!i)return o;const n=a.length,r=this._rszInnerSpanCms(e.roomId,a,t.polys);for(const t of function(t,e){const s=t.length;return[(e-1+s)%s,(e+1)%s]}(a,e.edge)){const e=a[t],s=a[(t+1)%n],i=r?.[t];o.push({kind:"length",x:(e[0]+s[0])/2,y:(e[1]+s[1])/2,text:null==i?this.host._fmtLen(e,s):Ce(i,"mi"===this.host.hass?.config?.unit_system?.length),edge:{a:[e[0],e[1]],b:[s[0],s[1]]}})}const l="mi"===this.host.hass?.config?.unit_system?.length,h=e.roomIds,c=this.host._spaceWalls,d=this.host._physicalBodiesR(),p=this.host._baseVb(),u=this.host._view&&this.host._view.w>0&&this.host._view.h>0?this.host._view:{x:p[0],y:p[1],w:p[2],h:p[3]},[_,m]=this.host._lastValidStageSize||[u.w,u.h],g={...u,stageWidth:Math.max(1,_),stageHeight:Math.max(1,m)},f=this.host._spaceModel(),b=this.host._config?.icon_size??2.5,v=f?Pe(b>8?2.5:b,f,u.w,this.host._kiosk?this.host._kioskScale.icon:1)*g.stageWidth/100:24,y=Math.max(10,.77*v),$=this.host._t("room.settings_short"),w=y*(1.457+.66*Math.max(1,$.length)*.42);for(const s of h){const a=t.polys[s]||i.find(t=>t.id===s).poly,n=c.length&&f&&at(f.rooms,s,c,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,$c,null,this._resizePreviewNodes)||a,r=d.length?Ie(Te(n,d))*Math.pow(this.host._cellCm/this.host._gridPitch,2)/1e4:ze(n,this.host._gridPitch,this.host._cellCm),h=Re(r,l),p=tr({poly:a,edge:e.edgeByRoom[s],text:h,view:g,gearCenter:Ae(a),gearWidthPx:w,gearHeightPx:y});o.push({kind:"area",roomId:s,x:p.anchor[0],y:p.anchor[1],text:h,placement:p})}return o}_rszInnerSpanCms(t,e,s){const i=Object.keys(s).length?Object.entries(s).map(([t,e])=>({id:t,poly:e})):this.host._spaceModel()?.rooms;if(!i?.length)return null;const o=this.host._spaceWalls;if(!o.length)return null;const a=this.host._openCuts(),n=Fe(i,t,o,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,$c);if(!n||n.length!==e.length)return null;const r=this.host._cellCm/this.host._gridPitch;return e.map((t,s)=>Ne(e,s,n)*r)}_renderResizeMeasurements(){const t=this.host._resize.liveLabels;if(!t?.length)return l;const e=t.filter(t=>"length"===t.kind),s=t.filter(t=>"area"===t.kind);return _`
  • `}_discoveryFilterState(t){const e=this.host._settings,s=void 0!==t.draftGroupLights?t.draftGroupLights:!1!==e.group_lights,i=e.exclude_integrations,o=void 0!==t.draftExcluded?null===t.draftExcluded?[...wi]:t.draftExcluded:i?[...i]:[...wi],a=void 0!==t.draftExcluded?null===t.draftExcluded:!i,n=void 0!==t.draftGroupLights||void 0!==t.draftExcluded;return{groupLights:s,excluded:o.sort(),usesProductList:a,dirty:n}}_registryIntegrations(){const t=new Set,e=this.host._fullRegistryHass;for(const s of Object.values(e?.entities||{}))s?.platform&&t.add(String(s.platform));for(const s of Object.values(e?.devices||{})){const e=s?.identifiers?.[0],i=Array.isArray(e)?e[0]:null;i&&t.add(String(i))}return[...t].sort()}_discoveryFilterPreview(t){const e=this._discoveryFilterState(t),s=[e.groupLights?1:0,e.usesProductList?"p":e.excluded.join(","),this.host._cfgEpoch,this.host._regSignature].join("|");if(this._discoveryPreviewMemo?.key===s)return this._discoveryPreviewMemo.value;const i={hass:this.host.hass,registry:this.host._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this.host._areaToSpace).map(([t,e])=>[t,e.space])),markers:this.host._markers,showAll:this.host._showAll,firstSpaceId:this.host._model[0]?.id||"",loc:t=>this.host._t(t),iconRules:this.host._iconRules},o=(t,e)=>new Set(Xi({...i,settings:t,excluded:e})),a=(t,e)=>new Set(Zi({...i,settings:t,excluded:e}).map(t=>t.bindingRef||t.id)),n=ki(this.host._settings),r={...this.host._settings,group_lights:e.groupLights},l=new Set(e.excluded),h=o(this.host._settings,n),c=o(r,l),d=a(this.host._settings,n),p=a(r,l);let u=0,_=0,m=0;const g=t=>t.includes("light.");for(const t of h)c.has(t)||(u++,g(t)&&m++);for(const t of c)h.has(t)||(_++,g(t)&&m++);for(const t of p)d.has(t)||(u++,g(t)&&m++);for(const t of d)p.has(t)||(_++,g(t)&&m++);const f={appear:u,hide:_,lights:m};return this._discoveryPreviewMemo={key:s,value:f},f}async _saveDiscoveryFilters(t){const e=this.host._serverCfg;if(!e)return;const s=this._discoveryFilterState(t),i={...e.settings};s.groupLights?delete i.group_lights:i.group_lights=!1,s.usesProductList?delete i.exclude_integrations:i.exclude_integrations=s.excluded,this.host._serverCfg={...e,settings:i},this.host._deviceInboxMemo=null,this._discoveryPreviewMemo=null,this.host._regSignature="",this.host._deviceInbox&&(this.host._deviceInbox={...t,draftGroupLights:void 0,draftExcluded:void 0}),this._saveConfig(),this.host._maybeRebuildDevices(),this.host.requestUpdate()}_renderDiscoveryFilters(t){const e=this._discoveryFilterState(t),s=e=>this.host._deviceInbox={...t,...e},i=t.filtersOpen&&e.dirty?this._discoveryFilterPreview(t):null,o=this._registryIntegrations().filter(t=>!e.excluded.includes(t));return h`
    `}_discoveryFilterState(t){const e=this.host._settings,s=void 0!==t.draftGroupLights?t.draftGroupLights:!1!==e.group_lights,i=e.exclude_integrations,o=void 0!==t.draftExcluded?null===t.draftExcluded?[...ki]:t.draftExcluded:i?[...i]:[...ki],a=void 0!==t.draftExcluded?null===t.draftExcluded:!i,n=void 0!==t.draftGroupLights||void 0!==t.draftExcluded;return{groupLights:s,excluded:o.sort(),usesProductList:a,dirty:n}}_registryIntegrations(){const t=new Set,e=this.host._fullRegistryHass;for(const s of Object.values(e?.entities||{}))s?.platform&&t.add(String(s.platform));for(const s of Object.values(e?.devices||{})){const e=s?.identifiers?.[0],i=Array.isArray(e)?e[0]:null;i&&t.add(String(i))}return[...t].sort()}_discoveryFilterPreview(t){const e=this._discoveryFilterState(t),s=[e.groupLights?1:0,e.usesProductList?"p":e.excluded.join(","),this.host._cfgEpoch,this.host._regSignature].join("|");if(this._discoveryPreviewMemo?.key===s)return this._discoveryPreviewMemo.value;const i={hass:this.host.hass,registry:this.host._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this.host._areaToSpace).map(([t,e])=>[t,e.space])),markers:this.host._markers,showAll:this.host._showAll,firstSpaceId:this.host._model[0]?.id||"",loc:t=>this.host._t(t),iconRules:this.host._iconRules},o=(t,e)=>new Set(Zi({...i,settings:t,excluded:e})),a=(t,e)=>new Set(Qi({...i,settings:t,excluded:e}).map(t=>t.bindingRef||t.id)),n=xi(this.host._settings),r={...this.host._settings,group_lights:e.groupLights},l=new Set(e.excluded),h=o(this.host._settings,n),c=o(r,l),d=a(this.host._settings,n),p=a(r,l);let u=0,_=0,m=0;const g=t=>t.includes("light.");for(const t of h)c.has(t)||(u++,g(t)&&m++);for(const t of c)h.has(t)||(_++,g(t)&&m++);for(const t of p)d.has(t)||(u++,g(t)&&m++);for(const t of d)p.has(t)||(_++,g(t)&&m++);const f={appear:u,hide:_,lights:m};return this._discoveryPreviewMemo={key:s,value:f},f}async _saveDiscoveryFilters(t){const e=this.host._serverCfg;if(!e)return;const s=this._discoveryFilterState(t),i={...e.settings};s.groupLights?delete i.group_lights:i.group_lights=!1,s.usesProductList?delete i.exclude_integrations:i.exclude_integrations=s.excluded,this.host._serverCfg={...e,settings:i},this.host._deviceInboxMemo=null,this._discoveryPreviewMemo=null,this.host._regSignature="",this.host._deviceInbox&&(this.host._deviceInbox={...t,draftGroupLights:void 0,draftExcluded:void 0}),this._saveConfig(),this.host._maybeRebuildDevices(),this.host.requestUpdate()}_renderDiscoveryFilters(t){const e=this._discoveryFilterState(t),s=e=>this.host._deviceInbox={...t,...e},i=t.filtersOpen&&e.dirty?this._discoveryFilterPreview(t):null,o=this._registryIntegrations().filter(t=>!e.excluded.includes(t));return h`
    s({filtersOpen:t.target.open})}> ${this.host._t("device_inbox.filters_title")}
    - `}_markerValueBadgeFields(t){return xi({touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition})}_markerValueSourceFields(t){return Si({touched:t.valueSourceTouched,originalHas:t.originalHasValueSource,original:t.originalValueSource,source:t.valueSource})}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=Ps(t.room),s=$s(t.binding,t.devId,()=>"__hp_device_preview__"),i=this.host._markers.find(e=>e.id===s||e.id===t.devId),o=Ss(t.binding,t.controls,this.host._bindingEntities(t.binding)),a=this._effectiveStoredTapAction(t),n={id:s,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===a&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:o.length?o:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),...this._markerValueSourceFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=ao(t.glowRadius);return null==e||e<=0?null:Math.round(this.host._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:t.hideFromPlan,vacuum:i?.vacuum||null},r=!!i&&("string"==typeof i.area&&i.area.length>0||null===i.area&&!!i.space&&!!i.room_id);return"virtual"===t.binding||t.roomTouched?(n.space=e?.space||("virtual"===t.binding?this.host._space:null),n.area=e?.area||null,n.room_id=e?.roomId||null):r&&(n.space=i.space,n.area=i.area,n.room_id=i.room_id),n}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const s=`${this.host._haRegistry.revision}\n${d(this.host._markers)}\n${JSON.stringify(e)}`;if(this.host._markerPreviewMemo?.key===s)return this.host._markerPreviewMemo.device;const i=Mi({hass:this.host.hass,registry:this.host._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this.host._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,siblingMarkers:this.host._markers,settings:this.host._settings,excluded:this.host._excluded,showAll:this.host._showAll,firstSpaceId:this.host._model[0]?.id||this.host._space,loc:t=>this.host._t(t),iconRules:this.host._iconRules});return this.host._markerPreviewMemo={key:s,device:i},i}_markerPreviewDevices(t){const e=this.host._markerPreviewDevicesMemo;if(e?.base===this.host._devices&&e.preview===t)return e.devices;const s=[...this.host._devices.filter(e=>e.id!==t.id),t];return this.host._markerPreviewDevicesMemo={base:this.host._devices,preview:t,devices:s},s}_toggleIntent(t,e=this.host._devices){return this.host._toggleIntent(t,e)}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const s=this._markerPreviewDevices(e);return this._toggleIntent(e,s)}_toggleStateText(t,e){return this.host._toggleStateText(t,e)}_toggleConfirmationStateText(t){return this.host._toggleConfirmationStateText(t)}_toggleConfirmationLines(t){return this.host._toggleConfirmationLines(t)}_toggleHintLines(t){if(!t)return[];const e=t=>this.host._t(`marker.toggle_effect_${t.replace("-","_")}`),s=t=>this.host._t(`marker.toggle_skip_${t.replace("-","_")}`);return Di(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this.host._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),s=t.name||e;return this.host._t("marker.toggle_hint_single",{name:s,id:e})},group:t=>this.host._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,s)=>"virtual-light"===t.via?this.host._t("marker.virtual_light_current",{state:this.host._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(s)}):this.host._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(s)}),groupCurrentNext:(t,s)=>this.host._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(s)}),skipped:t=>this.host._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${s(t.reason)})`}).join(", ")}),none:t=>this.host._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:Ms(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),s=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},i="toggle"===s.tapAction?this._toggleHintLines(this._toggleIntentForDialog(s)).join(" "):"";return{...s,tapHintAnnouncement:i}}_valueBadgeForBinding(t,e){const s={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},i=this._markerPreviewDevice(s);if(!i)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const o=[...this.host._devices.filter(t=>t.id!==i.id),i],a=ks(this.host._planHass,i,o),n=xs(this.host._planHass,i,a);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!n,valueBadgeSource:n,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const s={...e,hidden:!1};return Ci(Pi(this.host._planHass,[...this.host._devices.filter(t=>t.id!==s.id),s],null,this.host._virtualLights).filter(t=>t.device.id===s.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},s=this._markerPreviewDevice(e);return!!s&&Ii(this.host._planHass,{...s})}_setMarkerLightRole(t){const e=this.host._markerDialog;e&&(this.host._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.host.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this.host._planEntityAvailable(t)};const e=t.slice(7),s=this.host._markers.find(t=>t.id===e),i=this.host._devices.find(t=>t.id===e);if(!s||s.removed||!0!==s.is_light)return{label:this.host._t("marker.control_missing_label"),sub:`${this.host._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const o=this.host._serverCfg?.spaces.find(t=>t.id===(i?.space||s.space)),a=!!i&&Ti(i).length>0;return{label:s.name||i?.name||e,sub:[o?.title||i?.space||s.space,s.room_id||i?.area,a?"":this.host._t("marker.control_passive")].filter(Boolean).join(" · "),icon:s.icon||i?.icon||"mdi:lightbulb-outline",warning:!0===s.hidden||!0===i?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this.host._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this.host._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this.host._t("marker.value_badge_state",{name:t.label});const s=this.host.hass.states[e.entity_id]?.attributes?.friendly_name||this.host._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this.host._t(`marker.value_badge_attr_${e.attribute}`,{name:s})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",s=[],i=new Set;for(const t of this.host._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this.host._bindingStatus(t.binding).kind)continue;const o=this.host._devices.find(e=>e.id===t.id);if(!o||o.hidden)continue;const a=this._controlRefInfo(`marker:${t.id}`);for(const t of Ti(o))i.add(t);s.push({value:`marker:${t.id}`,label:a.label,sub:a.sub,icon:a.icon,search:`${a.label} ${a.sub} ${t.id} ${Ti(o).join(" ")}`.toLowerCase()})}const o=Object.keys(this.host.hass.states||{}).filter(e=>zi(e)&&!i.has(e)&&Ri(t.binding,[e],this.host._bindingEntities(t.binding)).length>0&&this.host._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),a=t.controlsFilter.trim().toLowerCase();return[...s,...o].filter(e=>!t.controls.includes(e.value)&&(!a||e.search.includes(a))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const s=this._markerDraft(t)?.id||t.devId||"";if(!s)return void this.host._showToast(this.host._t("toast.marker_binding_required"));const i=e.slice(7),o=this._markerDraft(t),a=o?[...this.host._markers.filter(t=>t.id!==s),o]:this.host._markers;if(Ai(a,s,i))return void this.host._showToast(this.host._t("toast.marker_control_cycle"))}this.host._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this.host._markerDialog;if(!e)return;if("auto"===t)return void(this.host._markerDialog={...e,glowMode:t,glowTouched:!0});const s=this._markerSpatialSource(e),i=Fi(s?this.host._planHass.states[s.eid]:void 0,null,this.host._fillColors.glow_light.c),o=!e.glowColorDrafted,a="fixed"===t&&!e.glowBrightnessDrafted;this.host._markerDialog={...e,glowMode:t,glowColor:o?i.c:e.glowColor,glowBrightness:a?Math.max(1,Math.round(100*i.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this.host._markerDialog,e="virtual"===t.bindingMode,s=this._bindingCandidates();this.host._bindingEntities(t.binding);const i=e?null:this.host._bindingStatus(t.binding),o=!e&&this.host._bindingHasHaPage(t.binding),a=this._markerPreviewDevice(t),n=this._effectiveMarkerTapAction(t,a),r=a?Ns(this.host._serverCfg?.spaces.find(t=>t.id===a.space)):null,c=a?this._markerPreviewDevices(a):this.host._devices,d="toggle"===n&&a?this._toggleIntent(a,c):null,p=this._toggleHintLines(d),u=a?Ni(this.host._planHass,a,{liveStates:!1!==this.host._config?.live_states,showTemperature:!1!==this.host._config?.show_temperature,showSignal:r?.showLqi??!1!==this.host._config?.show_signal,designPreview:!0,activityRuntime:this.host._activityRt.get(a.id),lightDevices:c,registryHass:this.host._fullRegistryHass,reducedMotion:this.host._reducedMotion}):null,_=a?ks(this.host._planHass,a,c):[],m=a?xs(this.host._planHass,a,_):null,g=t.valueBadgeTouched?t.valueBadgeEnabled:!!u?.valueBadge,f=t.valueBadgeTouched?t.valueBadgeSource:u?.valueBadge?.source||t.valueBadgeSource,b=t.valueBadgeTouched?t.valueBadgePosition:u?.valueBadge?.position||t.valueBadgePosition,v=Hi(f),y=!!f&&!_.some(t=>t.key===v),$=_.find(t=>t.key===v),w=Hi(t.valueSource),k=!(!t.valueSource||w&&_.some(t=>t.key===w)),x=_.find(t=>t.key===w),S=u?.valueSource?.sourceKey||"",M=this._markerAutoHasSpatialSource(t),D=!!a&&Li(this.host._planHass,{...a}),C=Ei(t.lightRole,M,D,t.glowMode),P=!C.sourceExists,I=!C.fromSourceEnabled,T=C.passive,z=C.effectiveMode,R="never"===t.lightRole?this.host._t("marker.glow_disabled_never"):"auto"!==t.lightRole||M?T?this.host._t("marker.glow_passive_hint"):this.host._t("marker.glow_disabled_no_entity"):this.host._t("marker.glow_disabled_auto"),A=a?Ti(a):[],F=a&&Oi(a)||"",N=!!t.lightEntity&&!A.includes(t.lightEntity),H=a?Bi(a):[],L=!!t.toggleEntity&&!H.includes(t.toggleEntity),E="toggle"===n?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,O=E?[...E.targets,...E.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",B=(()=>{if(e)return null;const i=s.find(e=>e.value===t.binding);if(i)return i.label;const[o,a]=t.binding.split(":");return"device"===o?this.host._fullRegistryHass.devices[a]?.name_by_user||this.host._fullRegistryHass.devices[a]?.name||a:this.host._fullRegistryHass.entities[a]?.name||this.host.hass.states[a]?.attributes?.friendly_name||a})();return h``}_markerValueBadgeFields(t){return Si({touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition})}_markerValueSourceFields(t){return Mi({touched:t.valueSourceTouched,originalHas:t.originalHasValueSource,original:t.originalValueSource,source:t.valueSource})}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=Is(t.room),s=ws(t.binding,t.devId,()=>"__hp_device_preview__"),i=this.host._markers.find(e=>e.id===s||e.id===t.devId),o=Ms(t.binding,t.controls,this.host._bindingEntities(t.binding)),a=this._effectiveStoredTapAction(t),n={id:s,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===a&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:o.length?o:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),...this._markerValueSourceFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=ro(t.glowRadius);return null==e||e<=0?null:Math.round(this.host._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:t.hideFromPlan,vacuum:i?.vacuum||null},r=!!i&&("string"==typeof i.area&&i.area.length>0||null===i.area&&!!i.space&&!!i.room_id);return"virtual"===t.binding||t.roomTouched?(n.space=e?.space||("virtual"===t.binding?this.host._space:null),n.area=e?.area||null,n.room_id=e?.roomId||null):r&&(n.space=i.space,n.area=i.area,n.room_id=i.room_id),n}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const s=`${this.host._haRegistry.revision}\n${d(this.host._markers)}\n${JSON.stringify(e)}`;if(this.host._markerPreviewMemo?.key===s)return this.host._markerPreviewMemo.device;const i=Di({hass:this.host.hass,registry:this.host._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this.host._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,siblingMarkers:this.host._markers,settings:this.host._settings,excluded:this.host._excluded,showAll:this.host._showAll,firstSpaceId:this.host._model[0]?.id||this.host._space,loc:t=>this.host._t(t),iconRules:this.host._iconRules});return this.host._markerPreviewMemo={key:s,device:i},i}_markerPreviewDevices(t){const e=this.host._markerPreviewDevicesMemo;if(e?.base===this.host._devices&&e.preview===t)return e.devices;const s=[...this.host._devices.filter(e=>e.id!==t.id),t];return this.host._markerPreviewDevicesMemo={base:this.host._devices,preview:t,devices:s},s}_toggleIntent(t,e=this.host._devices){return this.host._toggleIntent(t,e)}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const s=this._markerPreviewDevices(e);return this._toggleIntent(e,s)}_toggleStateText(t,e){return this.host._toggleStateText(t,e)}_toggleConfirmationStateText(t){return this.host._toggleConfirmationStateText(t)}_toggleConfirmationLines(t){return this.host._toggleConfirmationLines(t)}_toggleHintLines(t){if(!t)return[];const e=t=>this.host._t(`marker.toggle_effect_${t.replace("-","_")}`),s=t=>this.host._t(`marker.toggle_skip_${t.replace("-","_")}`);return Ci(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this.host._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),s=t.name||e;return this.host._t("marker.toggle_hint_single",{name:s,id:e})},group:t=>this.host._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,s)=>"virtual-light"===t.via?this.host._t("marker.virtual_light_current",{state:this.host._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(s)}):this.host._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(s)}),groupCurrentNext:(t,s)=>this.host._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(s)}),skipped:t=>this.host._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${s(t.reason)})`}).join(", ")}),none:t=>this.host._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:Ds(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),s=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},i="toggle"===s.tapAction?this._toggleHintLines(this._toggleIntentForDialog(s)).join(" "):"";return{...s,tapHintAnnouncement:i}}_valueBadgeForBinding(t,e){const s={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},i=this._markerPreviewDevice(s);if(!i)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const o=[...this.host._devices.filter(t=>t.id!==i.id),i],a=xs(this.host._planHass,i,o),n=Ss(this.host._planHass,i,a);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!n,valueBadgeSource:n,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const s={...e,hidden:!1};return Pi(Ii(this.host._planHass,[...this.host._devices.filter(t=>t.id!==s.id),s],null,this.host._virtualLights).filter(t=>t.device.id===s.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},s=this._markerPreviewDevice(e);return!!s&&Ti(this.host._planHass,{...s})}_setMarkerLightRole(t){const e=this.host._markerDialog;e&&(this.host._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.host.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this.host._planEntityAvailable(t)};const e=t.slice(7),s=this.host._markers.find(t=>t.id===e),i=this.host._devices.find(t=>t.id===e);if(!s||s.removed||!0!==s.is_light)return{label:this.host._t("marker.control_missing_label"),sub:`${this.host._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const o=this.host._serverCfg?.spaces.find(t=>t.id===(i?.space||s.space)),a=!!i&&zi(i).length>0;return{label:s.name||i?.name||e,sub:[o?.title||i?.space||s.space,s.room_id||i?.area,a?"":this.host._t("marker.control_passive")].filter(Boolean).join(" · "),icon:s.icon||i?.icon||"mdi:lightbulb-outline",warning:!0===s.hidden||!0===i?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this.host._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this.host._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this.host._t("marker.value_badge_state",{name:t.label});const s=this.host.hass.states[e.entity_id]?.attributes?.friendly_name||this.host._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this.host._t(`marker.value_badge_attr_${e.attribute}`,{name:s})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",s=[],i=new Set;for(const t of this.host._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this.host._bindingStatus(t.binding).kind)continue;const o=this.host._devices.find(e=>e.id===t.id);if(!o||o.hidden)continue;const a=this._controlRefInfo(`marker:${t.id}`);for(const t of zi(o))i.add(t);s.push({value:`marker:${t.id}`,label:a.label,sub:a.sub,icon:a.icon,search:`${a.label} ${a.sub} ${t.id} ${zi(o).join(" ")}`.toLowerCase()})}const o=Object.keys(this.host.hass.states||{}).filter(e=>Ri(e)&&!i.has(e)&&Ai(t.binding,[e],this.host._bindingEntities(t.binding)).length>0&&this.host._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),a=t.controlsFilter.trim().toLowerCase();return[...s,...o].filter(e=>!t.controls.includes(e.value)&&(!a||e.search.includes(a))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const s=this._markerDraft(t)?.id||t.devId||"";if(!s)return void this.host._showToast(this.host._t("toast.marker_binding_required"));const i=e.slice(7),o=this._markerDraft(t),a=o?[...this.host._markers.filter(t=>t.id!==s),o]:this.host._markers;if(Fi(a,s,i))return void this.host._showToast(this.host._t("toast.marker_control_cycle"))}this.host._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this.host._markerDialog;if(!e)return;if("auto"===t)return void(this.host._markerDialog={...e,glowMode:t,glowTouched:!0});const s=this._markerSpatialSource(e),i=Ni(s?this.host._planHass.states[s.eid]:void 0,null,this.host._fillColors.glow_light.c),o=!e.glowColorDrafted,a="fixed"===t&&!e.glowBrightnessDrafted;this.host._markerDialog={...e,glowMode:t,glowColor:o?i.c:e.glowColor,glowBrightness:a?Math.max(1,Math.round(100*i.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this.host._markerDialog,e="virtual"===t.bindingMode,s=this._bindingCandidates();this.host._bindingEntities(t.binding);const i=e?null:this.host._bindingStatus(t.binding),o=!e&&this.host._bindingHasHaPage(t.binding),a=this._markerPreviewDevice(t),n=this._effectiveMarkerTapAction(t,a),r=a?Hs(this.host._serverCfg?.spaces.find(t=>t.id===a.space)):null,c=a?this._markerPreviewDevices(a):this.host._devices,d="toggle"===n&&a?this._toggleIntent(a,c):null,p=this._toggleHintLines(d),u=a?Hi(this.host._planHass,a,{liveStates:!1!==this.host._config?.live_states,showTemperature:!1!==this.host._config?.show_temperature,showSignal:r?.showLqi??!1!==this.host._config?.show_signal,designPreview:!0,activityRuntime:this.host._activityRt.get(a.id),lightDevices:c,registryHass:this.host._fullRegistryHass,reducedMotion:this.host._reducedMotion}):null,_=a?xs(this.host._planHass,a,c):[],m=a?Ss(this.host._planHass,a,_):null,g=t.valueBadgeTouched?t.valueBadgeEnabled:!!u?.valueBadge,f=t.valueBadgeTouched?t.valueBadgeSource:u?.valueBadge?.source||t.valueBadgeSource,b=t.valueBadgeTouched?t.valueBadgePosition:u?.valueBadge?.position||t.valueBadgePosition,v=Li(f),y=!!f&&!_.some(t=>t.key===v),$=_.find(t=>t.key===v),w=Li(t.valueSource),k=!(!t.valueSource||w&&_.some(t=>t.key===w)),x=_.find(t=>t.key===w),S=u?.valueSource?.sourceKey||"",M=this._markerAutoHasSpatialSource(t),D=!!a&&Ei(this.host._planHass,{...a}),C=Oi(t.lightRole,M,D,t.glowMode),P=!C.sourceExists,I=!C.fromSourceEnabled,T=C.passive,z=C.effectiveMode,R="never"===t.lightRole?this.host._t("marker.glow_disabled_never"):"auto"!==t.lightRole||M?T?this.host._t("marker.glow_passive_hint"):this.host._t("marker.glow_disabled_no_entity"):this.host._t("marker.glow_disabled_auto"),A=a?zi(a):[],F=a&&Bi(a)||"",N=!!t.lightEntity&&!A.includes(t.lightEntity),H=a?Wi(a):[],L=!!t.toggleEntity&&!H.includes(t.toggleEntity),E="toggle"===n?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,O=E?[...E.targets,...E.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",B=(()=>{if(e)return null;const i=s.find(e=>e.value===t.binding);if(i)return i.label;const[o,a]=t.binding.split(":");return"device"===o?this.host._fullRegistryHass.devices[a]?.name_by_user||this.host._fullRegistryHass.devices[a]?.name||a:this.host._fullRegistryHass.entities[a]?.name||this.host.hass.states[a]?.attributes?.friendly_name||a})();return h`this._closeMarkerDialog()}>
    @@ -2272,7 +2272,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    @@ -2297,7 +2297,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e @input=${e=>this.host._markerDialog={...t,bindingFilter:e.target.value}} />
    ${s.map(e=>h`
    {if(e.value===t.binding)return void(this.host._markerDialog={...t,bindingOpen:!1});const s={...t,binding:e.value,bindingOpen:!1,controls:Ss(e.value,t.controls,this.host._bindingEntities(e.value)),autoIcon:this.host._autoIconForBinding(e.value)};this.host._markerDialog=this._announceToggleDraft({...s,...this._valueBadgeForBinding(s,e.value),valueSource:null,valueSourceTouched:!0})}}> + @click=${()=>{if(e.value===t.binding)return void(this.host._markerDialog={...t,bindingOpen:!1});const s={...t,binding:e.value,bindingOpen:!1,controls:Ms(e.value,t.controls,this.host._bindingEntities(e.value)),autoIcon:this.host._autoIconForBinding(e.value)};this.host._markerDialog=this._announceToggleDraft({...s,...this._valueBadgeForBinding(s,e.value),valueSource:null,valueSourceTouched:!0})}}> ${e.label}${e.sub}
    `)} ${s.length?l:h`
    ${this.host._t("marker.nothing_found")}
    `} @@ -2320,7 +2320,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e @@ -2495,19 +2495,19 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e -

    ${this.host._t(fc[t.display])}

    +

    ${this.host._t($c[t.display])}

    ${"value"===t.display?h`
    ${this._help("marker.value_source.help")}
    this.host._markerDialog={...t,valueBadgeSource:ji(e.target.value),valueBadgeEnabled:!0,valueBadgeTouched:!0}}> + @change=${e=>this.host._markerDialog={...t,valueBadgeSource:qi(e.target.value),valueBadgeEnabled:!0,valueBadgeTouched:!0}}> ${y?h``:l} @@ -2629,7 +2629,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e
    ${t.pdfs.map(t=>h` - ${t.name} + ${t.name} this._removeMarkerPdf(t.url)}>`)}
    this.host._spaceDialog={...t,fillMode:e}} /> ${this.host._t(s)} ${"temp"===e&&"temp"===t.fillMode?h` {const s=ao(e.target.value);null!=s&&(this.host._spaceDialog={...t,tempMin:s})}} /> + @input=${e=>{const s=ro(e.target.value);null!=s&&(this.host._spaceDialog={...t,tempMin:s})}} /> – {const s=ao(e.target.value);null!=s&&(this.host._spaceDialog={...t,tempMax:s})}} /> + @input=${e=>{const s=ro(e.target.value);null!=s&&(this.host._spaceDialog={...t,tempMax:s})}} /> °C `:l} @@ -2847,8 +2847,8 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e .label=${this.host._t("space.custom_fill")} .opacityLabel=${this.host._t("space.opacity")} .pickerLabels=${this.host._colorPickerLabels} - .color=${(t.customFill||Ls).c} - .opacity=${(t.customFill||Ls).a} + .color=${(t.customFill||Es).c} + .opacity=${(t.customFill||Es).a} @hp-color-opacity-change=${e=>{this.host._spaceDialog={...t,customFill:{c:e.detail.color,a:e.detail.opacity}}}}> ${t.customFill?h`
    `)}
    -
    `:l}`:l}`}_renderRoomDialog(){const t=!!this.host._roomEditId,e=t?null:this.host._wallFaceBatch,s=e&&e.candidates.length>1?this.host._t("room.queue_progress",{current:e.index+1,total:e.candidates.length}):"",i=!!this.host._areaSel||!!this.host._nameSel.trim(),o=Ns(this.host._curSpaceCfg),a=this.host._roomFill||o.fill,n=this.host._roomCustomFill||o.customFill,r=[...this.host._freeAreas];if(t&&this.host._areaSel&&!r.some(t=>t.area_id===this.host._areaSel)){const t=this.host.hass.areas[this.host._areaSel];t&&r.unshift(t)}return h``:l}`:l}`}_renderRoomDialog(){const t=!!this.host._roomEditId,e=t?null:this.host._wallFaceBatch,s=e&&e.candidates.length>1?this.host._t("room.queue_progress",{current:e.index+1,total:e.candidates.length}):"",i=!!this.host._areaSel||!!this.host._nameSel.trim(),o=Hs(this.host._curSpaceCfg),a=this.host._roomFill||o.fill,n=this.host._roomCustomFill||o.customFill,r=[...this.host._freeAreas];if(t&&this.host._areaSel&&!r.some(t=>t.area_id===this.host._areaSel)){const t=this.host.hass.areas[this.host._areaSel];t&&r.unshift(t)}return h`this._roomDialogCancel()}>
    @@ -2947,7 +2947,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e - ${[["","fill.inherit"],...Vi.map(t=>[t,"fill."+t])].map(([t,e])=>h`
    - ${this.host._renderCardPreview(Ns(this.host._curSpaceCfg).cardFontScale,this.host._roomNameScale,this.host._roomLabelScale)} + ${this.host._renderCardPreview(Hs(this.host._curSpaceCfg).cardFontScale,this.host._roomNameScale,this.host._roomLabelScale)}
    @@ -2991,4 +2991,4 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e ${this.host._t("btn.save")} `}
    - `}}export{xc as EDITOR_RUNTIME_FINGERPRINT,Sc as HouseplanEditorRuntime}; + `}}export{Cc as EDITOR_RUNTIME_FINGERPRINT,Pc as HouseplanEditorRuntime}; diff --git a/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js b/dist/houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js similarity index 98% rename from custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js rename to dist/houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js index 038c6afa..39ec3d62 100644 --- a/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BjgK4V8E.js +++ b/dist/houseplan-assets/houseplan-onboarding-runtime-THgxWVEp.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{l as t,aZ as s,A as e,x as o,b as a,cg as l,ch as i,ci as h,cj as c,aW as n,ck as r,cp as p,cl as d,cm as _,cn as u,co as g,dg as m,aV as b,aX as $,dh as v}from"./houseplan-card-CODdCIWj.js";import{i as f,c as y,e as w,r as D,a as k,b as S,g as C,t as M}from"./backdrop-pick-BnsHKWaS.js";const F=1e3,x=t=>{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";class L{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_help(l){const i=`${l}.aria`,h=t(this.host.hass,this.host._config?.language);return s(h,l)&&s(h,i)?a`{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";class L{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_help(l){const i=`${l}.aria`,h=t(this.host.hass,this.host._config?.language);return s(h,l)&&s(h,i)?a``:e}_openSpaceDialog(t,s){if(!this.host._serverStorage||!this.host._serverCfg)return void this.host._showToast(this.host._t("toast.integration_missing"));if("edit"===t){const e=this.host._serverCfg.spaces.find(t=>t.id===s);if(!e)return;const o=l(e),a=e.settings?.custom_fill&&"object"==typeof e.settings.custom_fill?i(e.settings.custom_fill):null,p="none"===o.fill?{...a||h,a:0}:a;return void(this.host._spaceDialog={mode:t,spaceId:s,title:e.title,planUrl:e.plan_url||null,planFile:null,source:e.plan_url?"file":"draw",showBorders:o.showBorders,showNames:o.showNames,zeroWallStyle:r(e),displayTouched:!0,hideDecor:o.hideDecor,hideOpenings:o.hideOpenings,roomColor:o.color,roomOpacity:o.opacity,fillMode:"none"===o.fill?"custom":o.fill,customFill:p,glowEnabled:o.glow,bgColor:o.bgColor,bgMode:"static"===e.settings?.bg_mode||"daynight"===e.settings?.bg_mode?e.settings.bg_mode:null,northDeg:n({},e.settings),sunRays:"boolean"==typeof e.settings?.sun_rays?e.settings.sun_rays:null,tempMin:o.tempMin,tempMax:o.tempMax,showLqi:o.showLqi??this.host._config?.show_signal??!0,cardFontScale:o.cardFontScale,labelTemp:o.labelTemp,labelHum:o.labelHum,labelLqi:o.labelLqi,labelLight:o.labelLight,cellCm:Number(e.cell_cm)>0?Number(e.cell_cm):5,cellCmInput:c(Number(e.cell_cm)>0?Number(e.cell_cm):5,this.host._imperial),cellCmTouched:!1,busy:!1})}const e=p(this.host._imperial);this.host._spaceDialog={mode:t,title:"",planUrl:null,planFile:null,...f(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:g,roomOpacity:u,fillMode:"custom",customFill:{...h,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:_,tempMax:d,showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:e,cellCmInput:c(e,this.host._imperial),cellCmTouched:!1,busy:!1}}async _pickPlanFile(t){const s=t.target,e=s.files?.[0];if(!e||!this.host._spaceDialog)return;s.value="";const o=await y(e);if("reject"===o.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===o.kind)return void(this.host._backdropGuard=o.state);const a=await w(e,o.ext,e.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:a})}_renderBackdropGuard(){return D(this.host,t=>{this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:t})},()=>{this.host._backdropGuard=null},this.host.hass)??e}_useServerPlan(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this.host._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let s=0;s<40;s++){const s=this.host._display(t);if(s){const e=await new Promise(t=>{const e=new Image;e.onload=()=>t(e.naturalWidth&&e.naturalHeight?e.naturalWidth/e.naturalHeight:0),e.onerror=()=>t(0),e.src=s}),o=this.host._spaceDialog;return o&&o.planUrl===t&&Number.isFinite(e)&&e>0?(this.host._spaceDialog={...o,savedAspect:e},e):0}if(await new Promise(t=>setTimeout(t,150)),this.host._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){const s=this.host._spaceDialog,e=s?.saved?.find(s=>s.name===t);if(!s||!e||e.used_by.length||e.url===s.planUrl)return;const o=await this.host._confirmDanger({key:"delete-plan",kind:"destructive",title:this.host._t("confirm.delete_plan_title"),message:this.host._t("confirm.delete_plan_body"),objectName:t,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),a=this.host._spaceDialog,l=a?.saved?.find(s=>s.name===t);if(o&&a&&l&&l.url===e.url&&l.modified===e.modified&&!l.used_by.length&&l.url!==a.planUrl)try{await this.host.hass.callWS({type:"houseplan/plans/delete",name:t});const s=this.host._spaceDialog;s?.saved&&(this.host._spaceDialog={...s,saved:s.saved.filter(s=>s.name!==t)})}catch(t){this.host._showToast(this.host._t("toast.plan_delete_failed",{err:this.host._errText(t)}))}}_renderServerPlans(t){if(t.savedBusy)return a`
    ${this.host._t("space.loading")}
    `;const s=t.saved||[];if(!s.length)return a`
    ${this.host._t("space.no_saved")}
    `;return a`
    ${s.map(s=>{return a`
    diff --git a/dist/houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js b/dist/houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js similarity index 93% rename from dist/houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js rename to dist/houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js index a71173c1..3b8b6ac1 100644 --- a/dist/houseplan-assets/hp-zigbee-topology-overlay-CKKJLQ66.js +++ b/dist/houseplan-assets/hp-zigbee-topology-overlay-CI1RuCwl.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{t as e,l as t,A as i,dO as r,w as o,b as s,q as n}from"./houseplan-card-CODdCIWj.js";import{t as a,a as h,r as d}from"./zigbee-topology-BUFPOnoy.js";import{zigbeeTopologyRuntimeSnapshot as p,subscribeZigbeeTopology as l}from"./zigbee-topology-runtime-Jy73PIeo.js";function c(e,t,i,r,o,s=9,n=4.5){const a=t.x-e.x,h=t.y-e.y,d=Math.hypot(a,h),p=d-Math.max(0,i)-Math.max(0,r);if(!Number.isFinite(d)||d<=0||p<4)return null;const l=a/d,c=h/d,_="toward-neighbor"===o,u=_?{x:t.x-l*Math.max(0,r),y:t.y-c*Math.max(0,r)}:{x:e.x+l*Math.max(0,i),y:e.y+c*Math.max(0,i)},m=Math.min(s,Math.max(4,.45*p)),v=Math.min(n,.5*m),b=_?-1:1,g=u.x+l*m*b,y=u.y+c*m*b,x=-c;return{tip:u,points:[u,{x:g+x*v,y:y+l*v},{x:g-x*v,y:y-l*v}]}}const _={revision:0,topologies:[],states:{}},u="data-hp-zigbee-topology-endpoint";class m extends e{constructor(){super(...arguments),this.devices=[],this.currentSpace="",this._runtime=_,this._hovered="",this._desiredEndpointIds=new Set,this._endpointSetDirty=!1,this._endpointElements=new Set,this._pointerOver=e=>{if(!this._mouseAllowed(e))return void this._clear();const t=this._deviceFromEvent(e),i=t?.dataset.id||"";i&&i!==this._hovered&&(this._hovered=i,this.requestUpdate())},this._pointerOut=e=>{const t=this._deviceFromEvent(e);if(!t||t.dataset.id!==this._hovered)return;const i=e.relatedTarget instanceof Element?e.relatedTarget.closest('[data-hp="device"]'):null;i?.dataset.id!==this._hovered&&this._clear()},this._pointerDown=e=>{"mouse"!==e.pointerType&&this._clear()}}connectedCallback(){super.connectedCallback();const e=this.getRootNode();e.host&&"undefined"!=typeof MutationObserver&&(this._hoverGateObserver=new MutationObserver(()=>{e.host.hasAttribute("data-pointer-hover")||this._clear()}),this._hoverGateObserver.observe(e.host,{attributes:!0,attributeFilter:["data-pointer-hover"]})),queueMicrotask(()=>this._connectParent())}disconnectedCallback(){this._release?.(),this._release=void 0,this._disconnectParent(),this._hoverGateObserver?.disconnect(),this._hoverGateObserver=void 0,this._hovered="",this._desiredEndpointIds.clear(),super.disconnectedCallback()}updated(e){e.has("hass")&&(this._release?.(),this._acceptRuntime(p(this.hass)),this._release=l(this.hass,()=>{this._acceptRuntime(p(this.hass))}));const t=e.has("currentSpace")||e.has("devices")||e.has("registry");t&&(this._mappedMemo=void 0,this.devices.some(e=>e.id===this._hovered&&e.space===this.currentSpace)||this._clear()),this._connectParent(),(this._endpointSetDirty||t)&&this._syncEndpointOwnership()}_acceptRuntime(e){e.revision===this._runtime.revision&&e.topologies===this._runtime.topologies&&e.states===this._runtime.states||(this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._runtime=e,this._mappedMemo=void 0,this.requestUpdate())}_connectParent(){const e=this.parentElement;e&&e!==this._parent&&(this._disconnectParent(),this._parent=e,e.addEventListener("pointerover",this._pointerOver),e.addEventListener("pointerout",this._pointerOut),e.addEventListener("pointerdown",this._pointerDown,!0),"undefined"!=typeof MutationObserver&&(this._markerObserver=new MutationObserver(()=>this._syncEndpointOwnership()),this._markerObserver.observe(e,{childList:!0})),this._syncEndpointOwnership())}_disconnectParent(){this._parent?.removeEventListener("pointerover",this._pointerOver),this._parent?.removeEventListener("pointerout",this._pointerOut),this._parent?.removeEventListener("pointerdown",this._pointerDown,!0),this._markerObserver?.disconnect(),this._markerObserver=void 0,this._clearEndpointOwnership(),this._parent=void 0}_deviceFromEvent(e){for(const t of e.composedPath())if(t instanceof HTMLElement&&"device"===t.dataset.hp)return t;return null}_mouseAllowed(e){const t=this.getRootNode();return"mouse"===e.pointerType&&t.host?.hasAttribute?.("data-pointer-hover")}_clear(){this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._hovered&&(this._hovered="",this.requestUpdate())}_setDesiredEndpointIds(e){const t=new Set(e);t.size===this._desiredEndpointIds.size&&[...t].every(e=>this._desiredEndpointIds.has(e))||(this._desiredEndpointIds=t,this._endpointSetDirty=!0)}_marker(e){return[...this._parent?.querySelectorAll('.dev[data-hp="device"][data-id]')||[]].find(t=>t.dataset.id===e)||null}_clearEndpointOwnership(){for(const e of this._endpointElements)e.removeAttribute(u);for(const e of this._parent?.querySelectorAll(`[${u}]`)||[])e.removeAttribute(u);this._endpointElements.clear()}_syncEndpointOwnership(){const e=new Set;for(const t of this._desiredEndpointIds){const i=this._marker(t);i&&e.add(i)}for(const t of this._endpointElements)e.has(t)||t.removeAttribute(u);for(const t of this._parent?.querySelectorAll(`[${u}]`)||[])e.has(t)||t.removeAttribute(u);for(const t of e)this._endpointElements.has(t)&&t.hasAttribute(u)||t.setAttribute(u,"");this._endpointElements=e,this._endpointSetDirty=!1}_position(e,t,i){const r=this._marker(e);if(!r)return null;const o=Number.parseFloat(r.style.left),s=Number.parseFloat(r.style.top),n=r.getBoundingClientRect();return Number.isFinite(o)&&Number.isFinite(s)?{x:o*t/100,y:s*i/100,width:n.width,height:n.height}:null}_targetText(e){if("remote-space"===e.kind){const i=this.spaces?.find(t=>t.id===e.spaceId)?.title;return"string"==typeof i&&i.trim()||a(t(this.hass),"route_other_space")}return a(t(this.hass),"unplaced-coordinator"===e.kind?"route_coordinator_not_on_plan":"route_device_not_on_plan")}_markerClearance(e){return.61*Math.max(e.width,e.height)+3}_points(e){return e.map(e=>`${e.x.toFixed(2)},${e.y.toFixed(2)}`).join(" ")}render(){if(!this._hovered||!this.registry||!this._runtime.topologies.length)return this._setDesiredEndpointIds([]),i;const e=this._mappedMemo,n=e&&e.runtime===this._runtime&&e.devices===this.devices&&e.registry===this.registry?e.mapped:h(this._runtime.topologies,this.devices,this.registry);e&&n===e.mapped||(this._mappedMemo={runtime:this._runtime,devices:this.devices,registry:this.registry,mapped:n});const p=d(n,this.currentSpace,this._hovered),l=this.clientWidth||this._parent?.clientWidth||1,_=this.clientHeight||this._parent?.clientHeight||1,u=this._position(this._hovered,l,_);if(!u)return this._setDesiredEndpointIds([]),i;const m=p.lines.map(e=>({...e,point:this._position(e.neighborMarkerId,l,_)})).filter(e=>!!e.point).map(e=>{const t=void 0===e.lqi?"rgba(145,155,165,.85)":r(e.lqi),i=e.routeDirection?c(u,e.point,this._markerClearance(u),this._markerClearance(e.point),e.routeDirection):null;return{...e,color:t,arrow:i}}),v=u.x>l/2,b=this._markerClearance(u)+18,g=p.parentTargets.map((e,t)=>{const i=30*(t-(p.parentTargets.length-1)/2),r={x:u.x+(v?-b:b),y:Math.max(14,Math.min(_-14,u.y+i))};return{target:e,point:r,arrow:c(u,r,this._markerClearance(u),0,"toward-neighbor")}});return this._setDesiredEndpointIds(m.length||g.length||p.remoteCount?[this._hovered,...m.map(e=>e.neighborMarkerId)]:[]),s` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{t as e,l as t,A as i,dQ as r,w as o,b as s,q as n}from"./houseplan-card-Bhpi71t0.js";import{t as a,a as h,r as d}from"./zigbee-topology-B-C5QCCD.js";import{zigbeeTopologyRuntimeSnapshot as p,subscribeZigbeeTopology as l}from"./zigbee-topology-runtime-C4ZtGWbD.js";function c(e,t,i,r,o,s=9,n=4.5){const a=t.x-e.x,h=t.y-e.y,d=Math.hypot(a,h),p=d-Math.max(0,i)-Math.max(0,r);if(!Number.isFinite(d)||d<=0||p<4)return null;const l=a/d,c=h/d,_="toward-neighbor"===o,u=_?{x:t.x-l*Math.max(0,r),y:t.y-c*Math.max(0,r)}:{x:e.x+l*Math.max(0,i),y:e.y+c*Math.max(0,i)},m=Math.min(s,Math.max(4,.45*p)),b=Math.min(n,.5*m),v=_?-1:1,g=u.x+l*m*v,y=u.y+c*m*v,x=-c;return{tip:u,points:[u,{x:g+x*b,y:y+l*b},{x:g-x*b,y:y-l*b}]}}const _={revision:0,topologies:[],states:{}},u="data-hp-zigbee-topology-endpoint";class m extends e{constructor(){super(...arguments),this.devices=[],this.currentSpace="",this._runtime=_,this._hovered="",this._desiredEndpointIds=new Set,this._endpointSetDirty=!1,this._endpointElements=new Set,this._pointerOver=e=>{if(!this._mouseAllowed(e))return void this._clear();const t=this._deviceFromEvent(e),i=t?.dataset.id||"";i&&i!==this._hovered&&(this._hovered=i,this.requestUpdate())},this._pointerOut=e=>{const t=this._deviceFromEvent(e);if(!t||t.dataset.id!==this._hovered)return;const i=e.relatedTarget instanceof Element?e.relatedTarget.closest('[data-hp="device"]'):null;i?.dataset.id!==this._hovered&&this._clear()},this._pointerDown=e=>{"mouse"!==e.pointerType&&this._clear()}}connectedCallback(){super.connectedCallback();const e=this.getRootNode();e.host&&"undefined"!=typeof MutationObserver&&(this._hoverGateObserver=new MutationObserver(()=>{e.host.hasAttribute("data-pointer-hover")||this._clear()}),this._hoverGateObserver.observe(e.host,{attributes:!0,attributeFilter:["data-pointer-hover"]})),queueMicrotask(()=>this._connectParent())}disconnectedCallback(){this._release?.(),this._release=void 0,this._disconnectParent(),this._hoverGateObserver?.disconnect(),this._hoverGateObserver=void 0,this._hovered="",this._desiredEndpointIds.clear(),super.disconnectedCallback()}updated(e){e.has("hass")&&(this._release?.(),this._acceptRuntime(p(this.hass)),this._release=l(this.hass,()=>{this._acceptRuntime(p(this.hass))}));const t=e.has("currentSpace")||e.has("devices")||e.has("registry");t&&(this._mappedMemo=void 0,this.devices.some(e=>e.id===this._hovered&&e.space===this.currentSpace)||this._clear()),this._connectParent(),(this._endpointSetDirty||t)&&this._syncEndpointOwnership()}_acceptRuntime(e){e.revision===this._runtime.revision&&e.topologies===this._runtime.topologies&&e.states===this._runtime.states||(this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._runtime=e,this._mappedMemo=void 0,this.requestUpdate())}_connectParent(){const e=this.parentElement;e&&e!==this._parent&&(this._disconnectParent(),this._parent=e,e.addEventListener("pointerover",this._pointerOver),e.addEventListener("pointerout",this._pointerOut),e.addEventListener("pointerdown",this._pointerDown,!0),"undefined"!=typeof MutationObserver&&(this._markerObserver=new MutationObserver(()=>this._syncEndpointOwnership()),this._markerObserver.observe(e,{childList:!0})),this._syncEndpointOwnership())}_disconnectParent(){this._parent?.removeEventListener("pointerover",this._pointerOver),this._parent?.removeEventListener("pointerout",this._pointerOut),this._parent?.removeEventListener("pointerdown",this._pointerDown,!0),this._markerObserver?.disconnect(),this._markerObserver=void 0,this._clearEndpointOwnership(),this._parent=void 0}_deviceFromEvent(e){for(const t of e.composedPath())if(t instanceof HTMLElement&&"device"===t.dataset.hp)return t;return null}_mouseAllowed(e){const t=this.getRootNode();return"mouse"===e.pointerType&&t.host?.hasAttribute?.("data-pointer-hover")}_clear(){this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._hovered&&(this._hovered="",this.requestUpdate())}_setDesiredEndpointIds(e){const t=new Set(e);t.size===this._desiredEndpointIds.size&&[...t].every(e=>this._desiredEndpointIds.has(e))||(this._desiredEndpointIds=t,this._endpointSetDirty=!0)}_marker(e){return[...this._parent?.querySelectorAll('.dev[data-hp="device"][data-id]')||[]].find(t=>t.dataset.id===e)||null}_clearEndpointOwnership(){for(const e of this._endpointElements)e.removeAttribute(u);for(const e of this._parent?.querySelectorAll(`[${u}]`)||[])e.removeAttribute(u);this._endpointElements.clear()}_syncEndpointOwnership(){const e=new Set;for(const t of this._desiredEndpointIds){const i=this._marker(t);i&&e.add(i)}for(const t of this._endpointElements)e.has(t)||t.removeAttribute(u);for(const t of this._parent?.querySelectorAll(`[${u}]`)||[])e.has(t)||t.removeAttribute(u);for(const t of e)this._endpointElements.has(t)&&t.hasAttribute(u)||t.setAttribute(u,"");this._endpointElements=e,this._endpointSetDirty=!1}_position(e,t,i){const r=this._marker(e);if(!r)return null;const o=Number.parseFloat(r.style.left),s=Number.parseFloat(r.style.top),n=r.getBoundingClientRect();return Number.isFinite(o)&&Number.isFinite(s)?{x:o*t/100,y:s*i/100,width:n.width,height:n.height}:null}_targetText(e){if("remote-space"===e.kind){const i=this.spaces?.find(t=>t.id===e.spaceId)?.title;return"string"==typeof i&&i.trim()||a(t(this.hass),"route_other_space")}return a(t(this.hass),"unplaced-coordinator"===e.kind?"route_coordinator_not_on_plan":"route_device_not_on_plan")}_markerClearance(e){return.61*Math.max(e.width,e.height)+3}_points(e){return e.map(e=>`${e.x.toFixed(2)},${e.y.toFixed(2)}`).join(" ")}render(){if(!this._hovered||!this.registry||!this._runtime.topologies.length)return this._setDesiredEndpointIds([]),i;const e=this._mappedMemo,n=e&&e.runtime===this._runtime&&e.devices===this.devices&&e.registry===this.registry?e.mapped:h(this._runtime.topologies,this.devices,this.registry);e&&n===e.mapped||(this._mappedMemo={runtime:this._runtime,devices:this.devices,registry:this.registry,mapped:n});const p=d(n,this.currentSpace,this._hovered),l=this.clientWidth||this._parent?.clientWidth||1,_=this.clientHeight||this._parent?.clientHeight||1,u=this._position(this._hovered,l,_);if(!u)return this._setDesiredEndpointIds([]),i;const m=p.lines.map(e=>({...e,point:this._position(e.neighborMarkerId,l,_)})).filter(e=>!!e.point).map(e=>{const t=void 0===e.lqi?"rgba(145,155,165,.85)":r(e.lqi),i=e.routeDirection?c(u,e.point,this._markerClearance(u),this._markerClearance(e.point),e.routeDirection):null;return{...e,color:t,arrow:i}}),b=u.x>l/2,v=this._markerClearance(u)+18,g=p.parentTargets.map((e,t)=>{const i=30*(t-(p.parentTargets.length-1)/2),r={x:u.x+(b?-v:v),y:Math.max(14,Math.min(_-14,u.y+i))};return{target:e,point:r,arrow:c(u,r,this._markerClearance(u),0,"toward-neighbor")}});return this._setDesiredEndpointIds(m.length||g.length||p.remoteCount?[this._hovered,...m.map(e=>e.neighborMarkerId)]:[]),s` ${m.length||g.length?o`
    `)} - ${g.map(e=>s`
    s`
    ${this._targetText(e.target)}
    `)} ${p.remoteCount?s`
    `${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function j(e){let t=0;for(let n=0;nArray.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])).map(e=>[Number(e[0]),Number(e[1])]),n=t[t.length-1];return t.length>1&&t[0][0]===n[0]&&t[0][1]===n[1]&&t.pop(),t}(e);if(n.length<3)return[];const o=!t;return j(n)>0===o?n:[...n].reverse()}function O(e,t,o){return e.length?`M ${e.map(e=>C(n(e,o,t))).join(" L ")} Z`:""}function A(e,t,n){const o=t[1]-e[1],a=-(t[0]-e[0]),i=n.rotDeg*Math.PI/180;return o*Math.sin(i)+a*Math.cos(i)}function B(t,o,a=e){if(!Number.isFinite(o)||o<0)throw new Error("invalid floor edge height");const i=(t||[]).map(e=>(e||[]).map((e,t)=>function(e,t){const n=N(e,t);if(!n.length)return n;let o=0;for(let e=1;e0)).filter(e=>e.length>=3&&Math.abs(j(e))>=1e-9)).filter(e=>e.length&&j(e[0])>0);i.sort((e,t)=>{const n=e[0][0],o=t[0][0];return n[0]-o[0]||n[1]-o[1]||Math.abs(j(t[0]))-Math.abs(j(e[0]))});const r=[],s=[];let l=0;for(let e=0;ee.depth-t.depth||e.component-t.component||e.edge-t.edge),{footprintPath:r.join(" "),sides:s,componentCount:i.length,edgeCount:l}}function R(e,t){return e^=Math.round(64*(Number.isFinite(t)?t:0)),Math.imul(e,16777619)>>>0}const F=Object.freeze({revision:1,leafThicknessRatio:.04,frameThicknessRatio:.055,gateTurnDeg:10,gateTopRatio:.88,windowBottomRatio:.27,windowTopRatio:.78,doorTopRatio:.92});F.leafThicknessRatio,F.frameThicknessRatio;const H=e=>e.every(Number.isFinite);function T(e,t){return Object.freeze([Object.is(e,-0)?0:e,Object.is(t,-0)?0:t])}function L(e,t){return[e[0]+t[0],e[1]+t[1]]}function V(e,t){return[e[0]-t[0],e[1]-t[1]]}function G(e,t){return[e[0]*t,e[1]*t]}function W(e,t,n,o){const a=e[0]*n,i=e[1]*o,r=t*Math.PI/180;return[a*Math.cos(r)-i*Math.sin(r),a*Math.sin(r)+i*Math.cos(r)]}function E(e,t,n,a,i,r,s){const l=e.flipH?-1:1,c="gate"===e.type?1:e.flipV?-1:1,d=o(e.type,e.flipV,e.angle,e.face);return{leaf:t,hinge:L([e.x+d.ox,e.y+d.oy],W(n,e.angle,l,c)),closedVector:W(a,e.angle,l,c),quarterVector:W([-a[1],a[0]],e.angle,l,c),turnDeg:i,bottom:r,top:s}}const q=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function D(e,t,o,a,i={}){const r=o.map(e=>n(e.point,e.z,a));return Object.freeze({kind:e,material:t,d:`M ${r.map(q).join(" L ")} Z`,depth:Math.max(...r.map(e=>e[1])),...i})}function _(e,t,n,o,a,i,r,s={}){return D(e,t,[{point:n,z:a},{point:o,z:a},{point:o,z:i},{point:n,z:i}],r,s)}function U(t,o,a=e){const i=Math.max(0,Math.min(1,Number.isFinite(o)?o:0));return t.leaves.map(e=>{const o=function(e,t){const n=e.turnDeg*t*Math.PI/180;return[e.hinge[0]+e.closedVector[0]*Math.cos(n)+e.quarterVector[0]*Math.sin(n),e.hinge[1]+e.closedVector[1]*Math.cos(n)+e.quarterVector[1]*Math.sin(n)]}(e,i),r=n(e.hinge,e.bottom,a),s=n(o,e.bottom,a),l=n(o,e.top,a),c=n(e.hinge,e.top,a),d="window"===t.type?"light-window":"matte-leaf",u="window"===t.type?Object.freeze([_("window-insert","light-window",e.hinge,o,e.bottom,e.top,a)]):function(e,t,n,o){const a=V(t,e.hinge),i=Math.hypot(a[0],a[1]);if(!(i>1e-9&&n>0))return Object.freeze([]);const r=T(-a[1]*n/(2*i),a[0]*n/(2*i)),s=L(e.hinge,r),l=L(t,r),c=V(e.hinge,r),d=V(t,r),u=[_("leaf-back","matte-leaf",d,c,e.bottom,e.top,o),_("leaf-front","matte-leaf",s,l,e.bottom,e.top,o),_("leaf-edge","matte-leaf",c,s,e.bottom,e.top,o,{edge:"hinge"}),_("leaf-edge","matte-leaf",l,d,e.bottom,e.top,o,{edge:"tip"}),D("leaf-top","matte-leaf",[{point:s,z:e.top},{point:c,z:e.top},{point:d,z:e.top},{point:l,z:e.top}],o)];return Object.freeze(u.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||String(e.edge||"").localeCompare(String(t.edge||""))))}(e,o,t.leafThickness,a);return Object.freeze({id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${q(r)} L ${q(s)} L ${q(l)} L ${q(c)} Z`,shadowD:`M ${q(n(e.hinge,0,a))} L ${q(n(o,0,a))}`,depth:Math.max(r[1],s[1]),material:d,thickness:"window"===t.type?0:t.leafThickness,surfaces:u})})}const K=1e-9,Z=e=>e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function Q(e){let t=0;for(let n=0;n=3&&e.every(Z)&&Math.abs(Q(e))>K}function X(e,t,n){const o=n[0]-t[0],a=n[1]-t[1],i=o*o+a*a,r=i?Math.max(0,Math.min(1,((e[0]-t[0])*o+(e[1]-t[1])*a)/i)):0;return Math.hypot(e[0]-t[0]-r*o,e[1]-t[1]-r*a)}function Y(e,t,n=1e-7){for(let o=0;oe[1]!=r[1]>e[1]&&e[0]<(r[0]-i[0])*(e[1]-i[1])/(r[1]-i[1])+i[0]&&(n=!n)}return n}function te(e){return Math.max(0,Math.abs(Q(e.outer))-(e.holes||[]).reduce((e,t)=>e+Math.abs(Q(t)),0))}function ne(e){return!!e.id&&J(e.outer)&&(e.holes||[]).every(J)&&te(e)>K}function oe(e,t){if(!ne(t)||Y(e,t.outer)||!ee(e,t.outer))return!1;for(const n of t.holes||[])if(Y(e,n)||ee(e,n))return!1;return!0}function ae(e){if(!ne(e))return null;if(e.safePoint&&oe(e.safePoint,e))return[e.safePoint[0],e.safePoint[1]];const t=e.outer.map(e=>e[0]),n=e.outer.map(e=>e[1]),o=Math.min(...t),a=Math.max(...t),i=Math.min(...n),r=Math.max(...n),s=[[(o+a)/2,(i+r)/2],[t.reduce((e,t)=>e+t,0)/t.length,n.reduce((e,t)=>e+t,0)/n.length]];for(let t=0;t{if(!oe(t,e))return;const n=function(e,t){let n=1/0;for(const o of[t.outer,...t.holes||[]])for(let t=0;tc+K&&(l=t,c=n)};s.forEach(d);for(let e=1;e<16;e++)for(let t=1;t<16;t++)d([o+(a-o)*e/16,i+(r-i)*t/16]);return l}function ie(e){if(!Z(e.floorAnchor))return null;const t=e.roomsValidated?e.rooms:e.rooms.filter(ne),n=e.preferredRoomId&&t.find(t=>t.id===e.preferredRoomId)||null;let o=null;return"device"===e.kind?(n&&oe(e.floorAnchor,n)&&(o=n),o||(o=t.filter(t=>oe(e.floorAnchor,t)).sort((e,t)=>te(e)-te(t)||((e,t)=>et?1:0)(e.id,t.id))[0]||null)):o=n,o?{id:o.id,area:te(o),safePoint:e.roomsValidated&&o.safePoint?[o.safePoint[0],o.safePoint[1]]:ae(o)}:null}function re(t,o,a,i=e,r=[0,0]){if(!Z(t)||!Z(o)||o[0]<0||o[1]<0||!Number.isFinite(a)||!Z(r))throw new Error("invalid isometric overlay footprint");return[[t[0]-o[0],t[1]-o[1]],[t[0]+o[0],t[1]-o[1]],[t[0]+o[0],t[1]+o[1]],[t[0]-o[0],t[1]+o[1]]].map(e=>{const t=n(e,a,i);return[t[0]+r[0],t[1]+r[1]]})}function se(e,t,n){return(t[0]-e[0])*(n[1]-e[1])-(t[1]-e[1])*(n[0]-e[0])}function le(e,t,n,o){const a=se(e,t,n),i=se(e,t,o),r=se(n,o,e),s=se(n,o,t);return(a>K&&i<-K||a<-K&&i>K)&&(r>K&&s<-K||r<-K&&s>K)||(Math.abs(a)<=K&&X(n,e,t)<=K||Math.abs(i)<=K&&X(o,e,t)<=K||Math.abs(r)<=K&&X(e,n,o)<=K||Math.abs(s)<=K&&X(t,n,o)<=K)}function ce(e,t,n,o){return le(e,t,n,o)?0:Math.min(X(e,n,o),X(t,n,o),X(n,e,t),X(o,e,t))}const de=new WeakMap;function ue(e){if(!e.length)return null;let t=1/0,n=1/0,o=-1/0,a=-1/0;for(const i of e){if(!Z(i))return null;t=Math.min(t,i[0]),n=Math.min(n,i[1]),o=Math.max(o,i[0]),a=Math.max(a,i[1])}return[t,n,o,a]}function he(e,t){if(!t)return ue(e.outer);if(de.has(e))return de.get(e)??null;const n=ue(e.outer);return de.set(e,n),n}function fe(e,t,n){return e[0]<=t[2]+n&&e[2]>=t[0]-n&&e[1]<=t[3]+n&&e[3]>=t[1]-n}function pe(e,t,n,o){return Math.min(t[0],n[0])<=e[2]+o&&Math.max(t[0],n[0])>=e[0]-o&&Math.min(t[1],n[1])<=e[3]+o&&Math.max(t[1],n[1])>=e[1]-o}function me(e,t,n,o,a){const i=he(n,a);if(!i||!fe(t,i,o))return!1;if(e.some(e=>function(e,t){return!!ee(e,t.outer)&&!(t.holes||[]).some(t=>ee(e,t))}(e,n)))return!0;if(n.outer.some(n=>n[0]>=t[0]&&n[0]<=t[2]&&n[1]>=t[1]&&n[1]<=t[3]&&ee(n,e)))return!0;for(const a of[n.outer,...n.holes||[]])for(let n=0;n"wall-side"===e.layer?0:"wall-top"===e.layer?1:2,Me=e=>{if("wall-side"===e.layer)return`${e.face.polygon}:${e.face.ring}:${e.face.edge}`;if("wall-top"===e.layer)return String(e.face.component);const t=e.surface;return`${t.sourceIndex}:${t.leaf??-1}:${t.kind}:${t.jamb??-1}:${t.edge??""}:${t.id}:${t.material}`};function be(e,t){const n=[...e.sides.map(e=>({layer:"wall-side",depth:e.depth,face:e})),...e.topFaces.map(e=>({layer:"wall-top",depth:e.depth,face:e})),...t.map(e=>({layer:"opening",depth:e.depth,surface:e}))];return n.sort((e,t)=>e.depth-t.depth||xe(e)-xe(t)||Me(e).localeCompare(Me(t))),Object.freeze(n)}const Se=Object.freeze({textLatinAdvance:.72,textWideAsciiAdvance:1,textWideAdvance:1.1,textSpaceAdvance:.4,textWidthSafety:1.08,deviceShellInset:.134375,deviceShellGap:.1,deviceSectionGap:.08,deviceBadgeMinWidth:.7875,deviceBadgeHeight:.7875,deviceBadgeInlinePadding:.28,deviceValueInlinePadding:.32,deviceAuxiliaryExtent:.7,deviceLqiFontSize:.38,deviceLqiTop:.734375,deviceLqiBelowBottomBadgeTop:1.571875,devicePadding:.08,roomNameLineHeight:1.25,roomAreaLinkWidth:1.1,roomMetricsTopGap:.15,roomMetricFontSize:.75,roomMetricLineHeight:1.25,roomMetricIconWidth:1.05,roomMetricInnerGap:.12,roomMetricRowGap:.55,roomMetricMinWidth:11,roomPadding:.4,openingLockHalfSize:.62,roomMetricTextCharacters:Object.freeze({temperature:10,humidity:8,lqi:6,light:24})});function $e(e){return[...String(e)].reduce((e,t)=>/\s/.test(t)?e+Se.textSpaceAdvance:/[MW@#%&]/.test(t)?e+Se.textWideAsciiAdvance:e+(t.codePointAt(0)>255?Se.textWideAdvance:Se.textLatinAdvance),0)*Se.textWidthSafety}function ke(e,t){return $e(e)*z(t||e)}function ze(e,t){return[Math.max(Math.abs(e.left),Math.abs(e.right))+t,Math.max(Math.abs(e.top),Math.abs(e.bottom))+t]}function Ie(e){if("opening-lock"===e.kind){const t=(Number.isFinite(e.size)&&e.size>0?e.size:0)*Se.openingLockHalfSize;return[t,t]}if("room-label"===e.kind){const t=Number.isFinite(e.font)&&e.font>0?e.font:0,n=v(e.room.settings?.name_scale),o=v(e.room.settings?.label_scale),a=($e(e.room.name||"")+(e.room.area?Se.roomAreaLinkWidth:0))*n,i=Se.roomNameLineHeight*n,r=[e.display.labelTemp?Se.roomMetricTextCharacters.temperature:0,e.display.labelHum?Se.roomMetricTextCharacters.humidity:0,e.display.labelLqi&&e.room.area?Se.roomMetricTextCharacters.lqi:0,e.display.labelLight?Se.roomMetricTextCharacters.light:0].filter(e=>e>0),s=Se.roomMetricFontSize*o,l=r.length?Math.max(Se.roomMetricMinWidth,r.reduce((e,t)=>e+Se.roomMetricIconWidth+Se.roomMetricInnerGap+t*Se.textLatinAdvance*Se.textWidthSafety,0)+(r.length-1)*Se.roomMetricRowGap)*s:0,c=r.length?s*Se.roomMetricLineHeight:0,d=ze({left:-Math.max(a,l)/2,right:Math.max(a,l)/2,top:-i/2,bottom:r.length?i/2+Se.roomMetricsTopGap+c:i/2},Se.roomPadding);return[d[0]*t,d[1]*t]}const t=Number.isFinite(e.core)&&e.core>0?e.core:0,n=e.presentation,o=null==n.valueText?1:Math.max(1,ke(n.valueText,n.valueFullText||n.valueText)+Se.deviceValueInlinePadding),a=[];n.valueBadge&&a.push(Math.max(Se.deviceBadgeMinWidth,ke(n.valueBadge.text,n.valueBadge.fullText||n.valueBadge.text)+Se.deviceBadgeInlinePadding));for(const e of x(n)){const t=e.text+e.suffix;a.push(Math.max(Se.deviceBadgeMinWidth,ke(t,t)+Se.deviceBadgeInlinePadding))}const i=n.valueBadge?.position||"right";let r;if(!a.length||"left"!==i&&"right"!==i)if(a.length){const e=a.reduce((e,t)=>e+t,0)+(a.length-1)*Se.deviceSectionGap,t=Math.max(o,e),n=1+Se.deviceShellGap+Se.deviceBadgeHeight;r="bottom"===i?{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:-.5+n+Se.deviceShellInset}:{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:.5-n-Se.deviceShellInset,bottom:.5+Se.deviceShellInset}}else r={left:-.5-Se.deviceShellInset,right:-.5+o+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:.5+Se.deviceShellInset};else{const e=Math.max(...a),t=a.length*Se.deviceBadgeHeight+(a.length-1)*Se.deviceSectionGap,n=o+Se.deviceShellGap+e,s=Math.max(1,t);r="right"===i?{left:-.5-Se.deviceShellInset,right:-.5+n+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}:{left:.5-n-Se.deviceShellInset,right:.5+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}}const s=Se.deviceAuxiliaryExtent;if(r.left=Math.min(r.left,-s),r.right=Math.max(r.right,s),r.top=Math.min(r.top,-s),r.bottom=Math.max(r.bottom,s),n.pulse.animated){const e=Math.max(1,n.pulse.diameterScale)/2;r.left=Math.min(r.left,-e),r.right=Math.max(r.right,e),r.top=Math.min(r.top,-e),r.bottom=Math.max(r.bottom,e)}if(null!=n.lqiText){const e="bottom"===n.valueBadge?.position?Se.deviceLqiBelowBottomBadgeTop:Se.deviceLqiTop,t=$e(n.lqiText)*Se.deviceLqiFontSize/2;r.left=Math.min(r.left,-t),r.right=Math.max(r.right,t),r.bottom=Math.max(r.bottom,e+Se.deviceLqiFontSize)}const l=ze(r,Se.devicePadding);return[l[0]*t,l[1]*t]}function Pe(e,t){return e.flatMap((e,n)=>e.orphanReason?[]:[{id:String(e.id||n),sourceIndex:n,type:e.type,x:e.rx,y:e.ry,angle:Number(e.angle)||0,length:e.rlen>0?e.rlen:.9*t,flipH:!!e.flip_h,flipV:!!e.flip_v}])}function Ce(e){return{id:e.id,x:e.x,y:e.y,w:e.w,h:e.h,poly:e.poly,wall_ids:e.wall_ids}}function je(e,t){const n=e?.partitionHost;if(!n)return null;const o="gate"===t.type?!t.flipV:t.flipV;return{sourceIndex:t.sourceIndex,hostId:n.host.id,t:n.t,depth:n.depth,face:p(n,o)}}function Ne(n,o=F){const a=Pe(n.openings,n.coordinateScale),r=a.map(e=>je(n.openings[e.sourceIndex],e)),p=i(t,n.cellCm),m=i(s,n.cellCm),g=i(l,n.cellCm);return{key:`${n.space.id}|${function(e){let t=2166136261;const n=e=>{if("number"!=typeof e)if("string"!=typeof e)if("boolean"!=typeof e)if(Array.isArray(e)){t=R(t,e.length);for(const t of e)n(t)}else{if(e&&"object"==typeof e){const t=e;for(const e of Object.keys(t).sort())n(e),n(t[e]);return}t=R(t,-1)}else t=R(t,e?1:0);else for(const n of e)t=R(t,n.codePointAt(0)||0);else t=R(t,e)};return n(e),t.toString(36)}({rooms:n.space.rooms.map(Ce),walls:n.walls,openCuts:n.openCuts,openings:a,openingHosts:r,openingGeometryPolicy:o,partitions:n.space.partitions,roomDrafts:n.space.room_drafts,columns:n.space.wall_columns,cellCm:n.cellCm,gridPitch:n.gridPitch,wallKeyPitch:n.wallKeyPitch,camera:e,wallHeight:p,raisedHeight:g,floorEdgeHeight:m,algorithm:4})}`,build:()=>{n.onBuild();const i=c(n.space,n.cellCm,n.gridPitch,2e-4*n.gridPitch,n.partitionCuts()).all,s=n.roomOpenings(),l=n.walls.length||i.length?d(n.space.rooms,n.walls,n.openCuts,s,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale,i):null;if(l&&("failed-core"===l.status||"not-applicable"===l.status))throw new Error("wall boolean geometry failed");const m=l?.paperGeom??u(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale);if(!m)throw new Error("floor boolean geometry failed");const g=l?.openingIndex||h(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale),w=a.map((e,a)=>{const i=r[a],s="gate"===e.type?!e.flipV:e.flipV,l=i?i.face:n.walls.length||"gate"===e.type?f(g,{x:e.x,y:e.y,angle:e.angle,length:e.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(e,n=t,o=F){const a=e.face.cm??0;if(!H([e.x,e.y,e.angle,e.length,e.face.ox,e.face.oy,a,n])||!(e.length>0)||!(n>0)||-1!==e.face.side&&1!==e.face.side||a<0)throw new Error("invalid isometric opening input");const i=e.length/2,r=e.angle*Math.PI/180,s=T(Math.cos(r),Math.sin(r)),l=T(-Math.sin(r),Math.cos(r)),c=T(e.x,e.y),d=T(e.x-s[0]*i,e.y-s[1]*i),u=T(e.x+s[0]*i,e.y+s[1]*i),h=T(e.face.ox,e.face.oy),f=T(d[0]+h[0],d[1]+h[1]),p=T(u[0]+h[0],u[1]+h[1]),m=T(d[0]-h[0],d[1]-h[1]),g=T(u[0]-h[0],u[1]-h[1]),w=Object.freeze({center:c,tangent:s,normal:l,start:d,end:u}),y=Object.freeze({side:e.face.side,cm:a,depth:2*Math.hypot(e.face.ox,e.face.oy),offset:h,selectedStart:f,selectedEnd:p,oppositeStart:m,oppositeEnd:g}),v="passage"===e.type?[]:[Object.freeze({jamb:0,center:d,selected:f,opposite:m}),Object.freeze({jamb:1,center:u,selected:p,opposite:g})];let x;if("passage"===e.type)x=[];else if("gate"===e.type){const t=e.face.side*o.gateTurnDeg;x=[E(e,0,[-i,0],[i,0],t,0,n*o.gateTopRatio),E(e,1,[i,0],[-i,0],-t,0,n*o.gateTopRatio)]}else x="window"===e.type?[E(e,0,[-i,0],[i,0],-90,n*o.windowBottomRatio,n*o.windowTopRatio),E(e,1,[i,0],[-i,0],90,n*o.windowBottomRatio,n*o.windowTopRatio)]:[E(e,0,[-i,0],[e.length,0],-90,0,n*o.doorTopRatio)];return Object.freeze({id:e.id,sourceIndex:e.sourceIndex,type:e.type,wallHeight:n,leafThickness:n*o.leafThicknessRatio,frameThickness:n*o.frameThicknessRatio,axis:w,face:y,reveals:Object.freeze(v),leaves:Object.freeze(x.map(e=>Object.freeze({...e,hinge:T(e.hinge[0],e.hinge[1]),closedVector:T(e.closedVector[0],e.closedVector[1]),quarterVector:T(e.quarterVector[0],e.quarterVector[1])})))})}({...e,face:l},p,o)}),y=Object.freeze(w);return{walls:l?.components.flatMap(e=>e.geom)||[],floor:m,openings:y,openingSurfaces:Object.freeze(y.flatMap(t=>function(t,n=e){if("passage"===t.type)return Object.freeze([]);const o=[];if(t.face.depth>1e-9)for(const e of t.reveals)o.push(_("jamb-reveal","reveal",e.selected,e.opposite,0,t.wallHeight,n,{jamb:e.jamb}));if("window"!==t.type||!t.leaves.length)return Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)));const a=Math.min(...t.leaves.map(e=>e.bottom)),i=Math.max(...t.leaves.map(e=>e.top)),r=Math.min(t.frameThickness,Math.hypot(t.axis.end[0]-t.axis.start[0],t.axis.end[1]-t.axis.start[1])/4,(i-a)/4),s=L(t.axis.start,G(t.axis.tangent,r)),l=V(t.axis.end,G(t.axis.tangent,r)),c=t.face.depth>1e-9?[t.face.offset,T(-t.face.offset[0],-t.face.offset[1])]:[t.face.offset];for(const e of c){const c=L(t.axis.start,e),d=L(t.axis.end,e),u=L(s,e),h=L(l,e);o.push(_("window-frame-side","light-frame",c,u,a,i,n,{jamb:0}),_("window-frame-side","light-frame",h,d,a,i,n,{jamb:1}),_("window-frame-top","light-frame",u,h,Math.max(a,i-r),i,n))}return t.face.depth>1e-9&&o.push(D("window-sill","light-sill",[{point:t.face.selectedStart,z:a},{point:t.face.selectedEnd,z:a},{point:t.face.oppositeEnd,z:a},{point:t.face.oppositeStart,z:a}],n)),Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)))}(t).map(e=>Object.freeze({...e,id:t.id,sourceIndex:t.sourceIndex,type:t.type}))))}}}}const Oe=e=>Array.isArray(e)?e:[];function Ae(e,t){const o=e=>Oe(e).flatMap(e=>Array.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])?[n([Number(e[0]),Number(e[1])],t)]:[]);return Oe(e).flatMap(e=>{const t=Oe(e);if(!t.length)return[];const n=o(t[0]);if(n.length<3)return[];return[{outer:n,holes:t.slice(1).map(o).filter(e=>e.length>=3)}]})}function Be(o){const a=i(t,o.cellCm),r=i(s,o.cellCm),c=i(l,o.cellCm),d=S(o.cache,o.source.key);let u=d.hit?d.value:void 0;if(!u){const i=o.source.build(),s=function(o,a=e,i=t){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const r=[],s=[],l=[],c=[];let d=0;for(let e=0;e<(o||[]).length;e++){const t=o[e],u=[];let h=-1/0;for(let o=0;o<(t||[]).length;o++){const s=N(t[o],o>0);if(s.length<3||Math.abs(j(s))<1e-9)continue;const f=O(s,a,i);r.push(f),u.push(f),h=Math.max(h,...s.map(e=>n(e,i,a)[1])),d+=s.length;for(let t=0;te.depth-t.depth||e.polygon-t.polygon||e.ring-t.ring||e.edge-t.edge),s.sort((e,t)=>e.depth-t.depth||e.component-t.component),{topPath:r.join(" "),topFaces:s,sides:l,contactPath:c.join(" "),edgeCount:d}}(i.walls,e,a),l=Ae(i.walls,a);u={geometry:s,floor:B(i.floor,r),wallSilhouettes:Object.freeze([...l,...s.sides.map(e=>({outer:e.points}))]),openings:i.openings,openingSurfaces:i.openingSurfaces},$(o.cache,o.source.key,u,8)}const h=function(e){let t=1/0,n=1/0,o=-1/0,a=-1/0;const i=(e,i=0)=>{t=Math.min(t,e[0]-i),n=Math.min(n,e[1]-i),o=Math.max(o,e[0]+i),a=Math.max(a,e[1]+i)};for(const t of e)if("passage"!==t.type){i(t.axis.start),i(t.axis.end),i(t.face.selectedStart),i(t.face.selectedEnd),i(t.face.oppositeStart),i(t.face.oppositeEnd);for(const e of t.leaves){const n=Math.hypot(e.closedVector[0],e.closedVector[1])+t.leafThickness/2;i(e.hinge,n)}}return H([t,n,o,a])?{x:t,y:n,w:o-t,h:a-n}:null}(u.openings),f=h?Re(o.liveFrame,h):o.liveFrame,p=k({rect:f,wallHeight:a,openingHeight:a,floorDepth:r,raisedHeight:c});return{key:o.source.key,...u,frame:p}}const Re=(e,t)=>{const n=Math.min(e.x,t.x),o=Math.min(e.y,t.y);return{x:n,y:o,w:Math.max(e.x+e.w,t.x+t.w)-n,h:Math.max(e.y+e.h,t.y+t.h)-o}},Fe=e=>{if(!e.length||!e.every(e=>Number.isFinite(e[0])&&Number.isFinite(e[1])))return null;const t=e.map(e=>e[0]),n=e.map(e=>e[1]),o=Math.min(...t),a=Math.min(...n);return{x:o,y:a,w:Math.max(...t)-o,h:Math.max(...n)-a}},He=(e,t)=>{const n=e.placement,o=t?n.visualScene:n.raisedScene,[a,i]=e.screenHalfSize,r=t?n.footprint:n.footprint.map(e=>[e[0]-n.nudgeScene[0],e[1]-n.nudgeScene[1]]);return[n.floorScene,...r,[o[0]-a,o[1]-i],[o[0]+a,o[1]-i],[o[0]+a,o[1]+i],[o[0]-a,o[1]+i]]},Te=(e,t)=>void 0===t?e:e.filter(e=>e.placement.owner?.id===t);function Le(e,t){return e?Fe(Te(e.entries,t).flatMap(e=>He(e,!0))):null}function Ve(e){const t=Te(e.entries,e.ownerId),n=Fe(t.flatMap(e=>He(e,!1))),o=n?Re(e.baseBounds,n):e.baseBounds,a=e.targetView(o);if(!(a&&a.w>0&&a.h>0&&[a.x,a.y,a.w,a.h].every(Number.isFinite)))return null;const i=e.stageSize;if(!(n&&i&&i.width>0&&i.height>0))return{bounds:o,view:a};const r=e=>Math.max(e.w/i.width,e.h/i.height),s=t=>{const o=48*t,a={x:n.x-o,y:n.y-o,w:n.w+2*o,h:n.h+2*o},i=Re(e.baseBounds,a),r=e.targetView(i);return r&&[r.x,r.y,r.w,r.h].every(Number.isFinite)&&r.w>0&&r.h>0?{bounds:i,view:r}:null};let l=0,c=Math.max(r(a),Number.EPSILON),d=s(c);for(let e=0;d&&r(d.view)>c*(1+1e-10)&&e<24;e++)l=c,c*=2,d=s(c);if(!d)return null;for(let e=0;e<40;e++){const e=(l+c)/2,t=s(e);if(!t)return null;r(t.view)<=e?(c=e,d=t):l=e}return d}const Ge=new WeakMap,We=2048,Ee=new WeakMap,qe=new WeakMap,De=new WeakMap;function _e(e,t){if(e.size!==t.size)return!1;for(const[n,o]of t)if(e.get(n)!==o)return!1;return!0}function Ue(e){const t=Ge.get(e.rooms);if(t)return t;const n=e.rooms.flatMap((e,t)=>{const n=w(e);return n&&n.length>=3?[{room:e,index:t,poly:n}]:[]}),o=Object.freeze(n.map(({room:e,index:t,poly:o})=>{const a=y(o,n.filter(e=>e.index!==t).map(e=>e.poly)),i={id:e.id||`room-index-${t}`,outer:o.map(e=>[e[0],e[1]]),holes:a.map(e=>e.map(e=>[e[0],e[1]]))};return{room:e,overlayRoom:{...i,safePoint:ae(i)||void 0}}}));return Ge.set(e.rooms,o),o}function Ke(o){const s=o.stageSize&&o.stageSize.width>0&&o.stageSize.height>0?Math.max(o.view.w/o.stageSize.width,o.view.h/o.stageSize.height):Math.max(o.view.w,o.view.h)/1e3,l=Ue(o.space),c=l.map(e=>e.overlayRoom),d=i(t,o.cellCm),u=i(a,o.cellCm),h=new Map,f=new Map,p=new Map,m=[];let g=Ee.get(o.wallSilhouettes);g||(g=new Map,Ee.set(o.wallSilhouettes,g));let w=qe.get(l);w||(w=new Map,qe.set(l,w));const y=o.iconPct*r(o.space)*o.kioskIconScale/100,v=o.deviceBasePct*r(o.space)*o.kioskIconScale/100,x=(i,r,l,h,f,p=!1)=>{const m=`${!1===o.resolveCollisions?"fit":"live"}\0${i}\0${r}`,y=[l[0],l[1],h[0],h[1],f||"",d,u,o.layers.shadows?1:0,p?1:0].join("|"),v=`${y}|${s}`,x=S(g,m);if(x.hit&&x.value.signature===v)return x.value.placement;if(x.hit&&x.value.shapeSignature===y&&s<=x.value.unitsPerPixel){const e=x.value.placement,t=e.nudgeDistanceCss*x.value.unitsPerPixel/s;if(!e.nearWallBefore||e.cleared&&t<=48)return e}const M=`${i}\0${r}`,b=[l[0],l[1],f||""].join("|"),k=S(w,M),z=k.hit&&k.value.signature===b?k.value.owner:ie({kind:i,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:f});k.hit&&k.value.signature===b||$(w,M,{signature:b,owner:z},We);const I=function(o){const i=o.camera||e,r=o.wallHeight??t,s=o.visualOffset??a,l=o.sceneUnitsPerCssPixel??1,c=o.safetyGapCssPx??4,d=o.maxNudgeCssPx??48;if(!Z(o.floorAnchor)||!Z(o.footprintHalfSize)||o.footprintHalfSize[0]<0||o.footprintHalfSize[1]<0||!Number.isFinite(r)||r<0||!Number.isFinite(s)||s<0||!Number.isFinite(l)||l<=0||!Number.isFinite(c)||c<0||!Number.isFinite(d)||d<0)throw new Error("invalid isometric overlay input");const u=[o.floorAnchor[0],o.floorAnchor[1]],h=n(u,0,i),f=(p=o.kind,!o.showBorders||"device"!==p&&"room-label"!==p&&"opening-lock"!==p?"floor":"raised");var p;if("floor"===f)return{plane:f,owner:null,floorAnchor:u,floorScene:h,raisedScene:h,visualScene:h,footprint:[],nudgeScene:[0,0],nudgeCss:[0,0],nudgeDistanceCss:0,nudged:!1,nearWallBefore:!1,nearWallAfter:!1,cleared:!0,capped:!1,grounding:{center:h,visible:!1},tether:ye(h,h,!1),status:"ok",reason:null};const m=r+s,g=n(u,m,i),w=o.ownerAlreadyResolved?o.resolvedOwner??null:ie(o),y=o.wallGeometryValidated??o.wallSilhouettes.every(ge),v=c*l,x=re(u,o.footprintHalfSize,m,i),M=e=>{const t=ue(e);return!!t&&o.wallSilhouettes.some(n=>me(e,t,n,v,!0===o.wallGeometryValidated))},b=!y||M(x);let S=0,$=[0,0],k=null,z=!1,I=y?"ok":"degraded",P=y?null:"invalid-wall-geometry";if(y&&b)if(w)if(w.safePoint){const e=o.rooms.find(e=>e.id===w.id)||null,t=n(w.safePoint,m,i),a=t[0]-g[0],r=t[1]-g[1],s=Math.hypot(a,r);if(s<=K)I="degraded",P="invalid-safe-point";else{const t=a/s,n=r/s,i=Math.min(d,s/l),c=i*l/s,h=[u[0]+(w.safePoint[0]-u[0])*c,u[1]+(w.safePoint[1]-u[1])*c],f=[t*i*l,n*i*l],p=ue([...x,...x.map(e=>[e[0]+f[0],e[1]+f[1]])]),m=p?o.wallSilhouettes.filter(e=>{const t=he(e,!0===o.wallGeometryValidated);return!!t&&fe(p,t,v)}):o.wallSilhouettes,g=!!e&&we(u,h,e),y=e=>{const a=[t*e*l,n*e*l],i=x.map(e=>[e[0]+a[0],e[1]+a[1]]),r=ue(i);return!!r&&m.some(e=>me(i,r,e,v,!0===o.wallGeometryValidated))},M=o.nudgeHintCss;if(Number.isFinite(M)&&M>=0&&M<=i){const t=M*l/s,n=[u[0]+(w.safePoint[0]-u[0])*t,u[1]+(w.safePoint[1]-u[1])*t];(g||e&&we(u,n,e))&&!y(M)&&(S=M,k=!1)}if(null===k){let t=null,n=0,o=!1;const a=Math.ceil(i);for(let r=1;r<=a;r++){const a=Math.min(i,r),c=a*l/s,d=[u[0]+(w.safePoint[0]-u[0])*c,u[1]+(w.safePoint[1]-u[1])*c];if(!(g||e&&we(u,d,e))){o=!0;break}if(!y(a)){t=a;break}n=a}if(null!==t){let e=n,o=t;for(let t=0;t<14;t++){const t=(e+o)/2;y(t)?e=t:o=t}S=o}else S=n,z=!0,I="degraded",P=o?"owner-boundary":"nudge-cap"}$=[t*S*l,n*S*l]}}else I="degraded",P="invalid-safe-point";else I="degraded",P="missing-owner";const C=[g[0]+$[0],g[1]+$[1]],j=re(u,o.footprintHalfSize,m,i,$),N=!y||(k??M(j)),O=S>K,A=O||b||N||!!o.hovered||!!o.focused||!!o.selected;return{plane:f,owner:w,floorAnchor:u,floorScene:h,raisedScene:g,visualScene:C,footprint:j,nudgeScene:$,nudgeCss:[$[0]/l,$[1]/l],nudgeDistanceCss:S,nudged:O,nearWallBefore:b,nearWallAfter:N,cleared:!N,capped:z,grounding:{center:h,visible:!1!==o.filtersSupported},tether:ye(h,C,A),status:I,reason:P}}({kind:i,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:f,ownerAlreadyResolved:!0,resolvedOwner:z,nudgeHintCss:x.hit&&x.value.shapeSignature===y?x.value.placement.nudgeDistanceCss*x.value.unitsPerPixel/s:void 0,showBorders:!0,wallSilhouettes:!1===o.resolveCollisions?[]:o.wallSilhouettes,wallGeometryValidated:!0,footprintHalfSize:h,wallHeight:d,visualOffset:u,sceneUnitsPerCssPixel:s,filtersSupported:o.layers.shadows,hovered:!0,selected:p});return $(g,m,{signature:v,shapeSignature:y,unitsPerPixel:s,placement:I},We),I};for(const e of o.devices){const t=o.positionOf(e),n=o.presentationOf(e,o.showLqi),a=v*n.scale,i=Ie({kind:"device",core:a,presentation:n}),r=e.marker?.room_id||l.find(t=>!!e.area&&t.room.area===e.area)?.overlayRoom.id||null,s=x("device",e.id,[t.x,t.y],i,r,o.selectedDeviceId===e.id);h.set(e.id,s),m.push({id:e.id,kind:"device",placement:s,groundRadius:Math.max(.32*a,2),screenHalfSize:i})}for(const{room:e,overlayRoom:t}of l){if(!o.display.showNames||!e.name)continue;const n=o.labelPositionOf(e,o.space.id),a=.5*y*(o.labelScaleOf(e)*o.kioskFontScale*o.display.cardFontScale),i=Ie({kind:"room-label",font:a,room:e,display:o.display}),r=x("room-label",t.id,[n.x,n.y],i,t.id,o.focusedRoomId===e.id);f.set(e,r),m.push({id:t.id,kind:"room-label",placement:r,groundRadius:Math.max(.75*a,2),screenHalfSize:i})}const M=o.openings.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&"string"==typeof e.lock&&!!e.lock&&o.openingEntityAvailable(e.lock));if(M.length){const e=o.openingWallIndex();for(const t of M){const n=Qe(t,e,o.cellCm),a=n.floorAnchor,i=.62*y,r=Ie({kind:"opening-lock",size:i}),s=x("opening-lock",String(t.id),a,r,n.preferredRoomId,o.selectedOpeningId===t.id);p.set(String(t.id),s),m.push({id:String(t.id),kind:"opening-lock",placement:s,groundRadius:Math.max(.28*i,2),screenHalfSize:r})}}const b={devices:h,rooms:f,locks:p,entries:Object.freeze(m)},k=!1===o.resolveCollisions?"fit":"live";let z=De.get(o.wallSilhouettes);z||(z=new Map,De.set(o.wallSilhouettes,z));const I=z.get(k);return I&&function(e,t){return e.length===t.length&&t.every((t,n)=>{const o=e[n];return o.id===t.id&&o.kind===t.kind&&o.placement===t.placement&&o.groundRadius===t.groundRadius&&o.screenHalfSize[0]===t.screenHalfSize[0]&&o.screenHalfSize[1]===t.screenHalfSize[1]})}(I.entries,b.entries)&&_e(I.devices,b.devices)&&_e(I.rooms,b.rooms)&&_e(I.locks,b.locks)?I:(z.set(k,b),b)}function Ze(e,t,n){return Qe(e,t,n).floorAnchor}function Qe(e,t,n){const o=!e.flip_v,a="gate"===e.type?e.partitionHost?p(e.partitionHost,o):f(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen,flip_v:o}):null,[i,r]=m({x:e.rx,y:e.ry,angle:e.angle,flipV:!!e.flip_v,gateFace:a},n);if(e.partitionHost)return{floorAnchor:i,preferredRoomId:null};const s=g(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen},!0),l=r?"negative":"positive";return{floorAnchor:i,preferredRoomId:s[l]?.roomId||null}}function Je(e){let t=!1;try{t="undefined"!=typeof CSS&&"function"==typeof CSS.supports&&CSS.supports("filter","blur(1px)")}catch{t=!1}let n=!1;try{n="function"==typeof matchMedia&&matchMedia("(forced-colors: active)").matches}catch{n=!0}return function(e){const t=!!e.showBorders;return{structural:t,panels:t&&!e.hideOpenings,shadows:t&&e.filtersSupported&&!e.forcedColors,materialNuance:t&&e.filtersSupported&&!e.forcedColors,floorSymbols:!e.hideOpenings&&!t}}({showBorders:e.showBorders,hideOpenings:e.hideOpenings,filtersSupported:t,forcedColors:n})}function Xe(e,t,n,o){if(!e.panels||!t)return[];return t.openings.flatMap(e=>{const t=n[e.sourceIndex];return t?U(e,o(t)):[]}).sort((e,t)=>e.depth-t.depth||e.sourceIndex-t.sourceIndex||e.leaf-t.leaf)}function Ye(e){const t=Je(e.display),n=t.panels?Xe(t,e.scene,e.openings,e.amountOf):[],o=e.overlays(t),a=t=>({layers:t,panels:n,overlays:o,underlay:it(t,e.scene?.floor,e.cellCm),shadows:rt(t,n,e.scene?.geometry,e.cellCm),walls:st(e.projection,t,e.scene,n,e.cellCm),grounds:ot(o,t,e.cellCm),raised:at(o)});try{return a(t)}catch(e){if(!t.shadows&&!t.materialNuance)throw e;return a({...t,shadows:!1,materialNuance:!1})}}const et=()=>b``;function tt(e){return`translate(${i(4,e)} ${i(8,e)})`}function nt(e,t,n){const o=I(n);return b` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{ds as e,dt as t,a$ as n,du as o,dv as a,m as i,dw as r,dx as s,dy as l,dz as c,a4 as d,dA as f,ah as u,bS as h,bR as p,dB as m,ai as g,Q as w,dC as y,cL as v,dD as x,A as M,w as b,dE as S,dF as $,dG as k,dH as z,dI as I}from"./houseplan-card-Bhpi71t0.js";import{i as P}from"./guard-BgTQLSGB.js";const C=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function j(e){let t=0;for(let n=0;nArray.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])).map(e=>[Number(e[0]),Number(e[1])]),n=t[t.length-1];return t.length>1&&t[0][0]===n[0]&&t[0][1]===n[1]&&t.pop(),t}(e);if(n.length<3)return[];const o=!t;return j(n)>0===o?n:[...n].reverse()}function O(e,t,o){return e.length?`M ${e.map(e=>C(n(e,o,t))).join(" L ")} Z`:""}function A(e,t,n){const o=t[1]-e[1],a=-(t[0]-e[0]),i=n.rotDeg*Math.PI/180;return o*Math.sin(i)+a*Math.cos(i)}function B(t,o,a=e){if(!Number.isFinite(o)||o<0)throw new Error("invalid floor edge height");const i=(t||[]).map(e=>(e||[]).map((e,t)=>function(e,t){const n=N(e,t);if(!n.length)return n;let o=0;for(let e=1;e0)).filter(e=>e.length>=3&&Math.abs(j(e))>=1e-9)).filter(e=>e.length&&j(e[0])>0);i.sort((e,t)=>{const n=e[0][0],o=t[0][0];return n[0]-o[0]||n[1]-o[1]||Math.abs(j(t[0]))-Math.abs(j(e[0]))});const r=[],s=[];let l=0;for(let e=0;ee.depth-t.depth||e.component-t.component||e.edge-t.edge),{footprintPath:r.join(" "),sides:s,componentCount:i.length,edgeCount:l}}function R(e,t){return e^=Math.round(64*(Number.isFinite(t)?t:0)),Math.imul(e,16777619)>>>0}const H=Object.freeze({revision:1,leafThicknessRatio:.04,frameThicknessRatio:.055,gateTurnDeg:10,gateTopRatio:.88,windowBottomRatio:.27,windowTopRatio:.78,doorTopRatio:.92});H.leafThicknessRatio,H.frameThicknessRatio;const F=e=>e.every(Number.isFinite);function T(e,t){return Object.freeze([Object.is(e,-0)?0:e,Object.is(t,-0)?0:t])}function L(e,t){return[e[0]+t[0],e[1]+t[1]]}function V(e,t){return[e[0]-t[0],e[1]-t[1]]}function G(e,t){return[e[0]*t,e[1]*t]}function W(e,t,n,o){const a=e[0]*n,i=e[1]*o,r=t*Math.PI/180;return[a*Math.cos(r)-i*Math.sin(r),a*Math.sin(r)+i*Math.cos(r)]}function E(e,t,n,a,i,r,s){const l=e.flipH?-1:1,c="gate"===e.type?1:e.flipV?-1:1,d=o(e.type,e.flipV,e.angle,e.face);return{leaf:t,hinge:L([e.x+d.ox,e.y+d.oy],W(n,e.angle,l,c)),closedVector:W(a,e.angle,l,c),quarterVector:W([-a[1],a[0]],e.angle,l,c),turnDeg:i,bottom:r,top:s}}const q=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function D(e,t,o,a,i={}){const r=o.map(e=>n(e.point,e.z,a));return Object.freeze({kind:e,material:t,d:`M ${r.map(q).join(" L ")} Z`,depth:Math.max(...r.map(e=>e[1])),...i})}function _(e,t,n,o,a,i,r,s={}){return D(e,t,[{point:n,z:a},{point:o,z:a},{point:o,z:i},{point:n,z:i}],r,s)}function U(t,o,a=e){const i=Math.max(0,Math.min(1,Number.isFinite(o)?o:0));return t.leaves.map(e=>{const o=function(e,t){const n=e.turnDeg*t*Math.PI/180;return[e.hinge[0]+e.closedVector[0]*Math.cos(n)+e.quarterVector[0]*Math.sin(n),e.hinge[1]+e.closedVector[1]*Math.cos(n)+e.quarterVector[1]*Math.sin(n)]}(e,i),r=n(e.hinge,e.bottom,a),s=n(o,e.bottom,a),l=n(o,e.top,a),c=n(e.hinge,e.top,a),d="window"===t.type?"light-window":"matte-leaf",f="window"===t.type?Object.freeze([_("window-insert","light-window",e.hinge,o,e.bottom,e.top,a)]):function(e,t,n,o){const a=V(t,e.hinge),i=Math.hypot(a[0],a[1]);if(!(i>1e-9&&n>0))return Object.freeze([]);const r=T(-a[1]*n/(2*i),a[0]*n/(2*i)),s=L(e.hinge,r),l=L(t,r),c=V(e.hinge,r),d=V(t,r),f=[_("leaf-back","matte-leaf",d,c,e.bottom,e.top,o),_("leaf-front","matte-leaf",s,l,e.bottom,e.top,o),_("leaf-edge","matte-leaf",c,s,e.bottom,e.top,o,{edge:"hinge"}),_("leaf-edge","matte-leaf",l,d,e.bottom,e.top,o,{edge:"tip"}),D("leaf-top","matte-leaf",[{point:s,z:e.top},{point:c,z:e.top},{point:d,z:e.top},{point:l,z:e.top}],o)];return Object.freeze(f.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||String(e.edge||"").localeCompare(String(t.edge||""))))}(e,o,t.leafThickness,a);return Object.freeze({id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${q(r)} L ${q(s)} L ${q(l)} L ${q(c)} Z`,shadowD:`M ${q(n(e.hinge,0,a))} L ${q(n(o,0,a))}`,depth:Math.max(r[1],s[1]),material:d,thickness:"window"===t.type?0:t.leafThickness,surfaces:f})})}const K=1e-9,Z=e=>e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function Q(e){let t=0;for(let n=0;n=3&&e.every(Z)&&Math.abs(Q(e))>K}function X(e,t,n){const o=n[0]-t[0],a=n[1]-t[1],i=o*o+a*a,r=i?Math.max(0,Math.min(1,((e[0]-t[0])*o+(e[1]-t[1])*a)/i)):0;return Math.hypot(e[0]-t[0]-r*o,e[1]-t[1]-r*a)}function Y(e,t,n=1e-7){for(let o=0;oe[1]!=r[1]>e[1]&&e[0]<(r[0]-i[0])*(e[1]-i[1])/(r[1]-i[1])+i[0]&&(n=!n)}return n}function te(e){return Math.max(0,Math.abs(Q(e.outer))-(e.holes||[]).reduce((e,t)=>e+Math.abs(Q(t)),0))}function ne(e){return!!e.id&&J(e.outer)&&(e.holes||[]).every(J)&&te(e)>K}function oe(e,t){if(!ne(t)||Y(e,t.outer)||!ee(e,t.outer))return!1;for(const n of t.holes||[])if(Y(e,n)||ee(e,n))return!1;return!0}function ae(e){if(!ne(e))return null;if(e.safePoint&&oe(e.safePoint,e))return[e.safePoint[0],e.safePoint[1]];const t=e.outer.map(e=>e[0]),n=e.outer.map(e=>e[1]),o=Math.min(...t),a=Math.max(...t),i=Math.min(...n),r=Math.max(...n),s=[[(o+a)/2,(i+r)/2],[t.reduce((e,t)=>e+t,0)/t.length,n.reduce((e,t)=>e+t,0)/n.length]];for(let t=0;t{if(!oe(t,e))return;const n=function(e,t){let n=1/0;for(const o of[t.outer,...t.holes||[]])for(let t=0;tc+K&&(l=t,c=n)};s.forEach(d);for(let e=1;e<16;e++)for(let t=1;t<16;t++)d([o+(a-o)*e/16,i+(r-i)*t/16]);return l}function ie(e){if(!Z(e.floorAnchor))return null;const t=e.roomsValidated?e.rooms:e.rooms.filter(ne),n=e.preferredRoomId&&t.find(t=>t.id===e.preferredRoomId)||null;let o=null;return"device"===e.kind?(n&&oe(e.floorAnchor,n)&&(o=n),o||(o=t.filter(t=>oe(e.floorAnchor,t)).sort((e,t)=>te(e)-te(t)||((e,t)=>et?1:0)(e.id,t.id))[0]||null)):o=n,o?{id:o.id,area:te(o),safePoint:e.roomsValidated&&o.safePoint?[o.safePoint[0],o.safePoint[1]]:ae(o)}:null}function re(t,o,a,i=e,r=[0,0]){if(!Z(t)||!Z(o)||o[0]<0||o[1]<0||!Number.isFinite(a)||!Z(r))throw new Error("invalid isometric overlay footprint");return[[t[0]-o[0],t[1]-o[1]],[t[0]+o[0],t[1]-o[1]],[t[0]+o[0],t[1]+o[1]],[t[0]-o[0],t[1]+o[1]]].map(e=>{const t=n(e,a,i);return[t[0]+r[0],t[1]+r[1]]})}function se(e,t,n){return(t[0]-e[0])*(n[1]-e[1])-(t[1]-e[1])*(n[0]-e[0])}function le(e,t,n,o){const a=se(e,t,n),i=se(e,t,o),r=se(n,o,e),s=se(n,o,t);return(a>K&&i<-K||a<-K&&i>K)&&(r>K&&s<-K||r<-K&&s>K)||(Math.abs(a)<=K&&X(n,e,t)<=K||Math.abs(i)<=K&&X(o,e,t)<=K||Math.abs(r)<=K&&X(e,n,o)<=K||Math.abs(s)<=K&&X(t,n,o)<=K)}function ce(e,t,n,o){return le(e,t,n,o)?0:Math.min(X(e,n,o),X(t,n,o),X(n,e,t),X(o,e,t))}const de=new WeakMap;function fe(e){if(!e.length)return null;let t=1/0,n=1/0,o=-1/0,a=-1/0;for(const i of e){if(!Z(i))return null;t=Math.min(t,i[0]),n=Math.min(n,i[1]),o=Math.max(o,i[0]),a=Math.max(a,i[1])}return[t,n,o,a]}function ue(e,t){if(!t)return fe(e.outer);if(de.has(e))return de.get(e)??null;const n=fe(e.outer);return de.set(e,n),n}function he(e,t,n){return e[0]<=t[2]+n&&e[2]>=t[0]-n&&e[1]<=t[3]+n&&e[3]>=t[1]-n}function pe(e,t,n,o){return Math.min(t[0],n[0])<=e[2]+o&&Math.max(t[0],n[0])>=e[0]-o&&Math.min(t[1],n[1])<=e[3]+o&&Math.max(t[1],n[1])>=e[1]-o}function me(e,t,n,o,a){const i=ue(n,a);if(!i||!he(t,i,o))return!1;if(e.some(e=>function(e,t){return!!ee(e,t.outer)&&!(t.holes||[]).some(t=>ee(e,t))}(e,n)))return!0;if(n.outer.some(n=>n[0]>=t[0]&&n[0]<=t[2]&&n[1]>=t[1]&&n[1]<=t[3]&&ee(n,e)))return!0;for(const a of[n.outer,...n.holes||[]])for(let n=0;n"wall-side"===e.layer?0:"wall-top"===e.layer?1:2,Me=e=>{if("wall-side"===e.layer)return`${e.face.polygon}:${e.face.ring}:${e.face.edge}`;if("wall-top"===e.layer)return String(e.face.component);const t=e.surface;return`${t.sourceIndex}:${t.leaf??-1}:${t.kind}:${t.jamb??-1}:${t.edge??""}:${t.id}:${t.material}`};function be(e,t){const n=[...e.sides.map(e=>({layer:"wall-side",depth:e.depth,face:e})),...e.topFaces.map(e=>({layer:"wall-top",depth:e.depth,face:e})),...t.map(e=>({layer:"opening",depth:e.depth,surface:e}))];return n.sort((e,t)=>e.depth-t.depth||xe(e)-xe(t)||Me(e).localeCompare(Me(t))),Object.freeze(n)}const Se=Object.freeze({textLatinAdvance:.72,textWideAsciiAdvance:1,textWideAdvance:1.1,textSpaceAdvance:.4,textWidthSafety:1.08,deviceShellInset:.134375,deviceShellGap:.1,deviceSectionGap:.08,deviceBadgeMinWidth:.7875,deviceBadgeHeight:.7875,deviceBadgeInlinePadding:.28,deviceValueInlinePadding:.32,deviceAuxiliaryExtent:.7,deviceLqiFontSize:.38,deviceLqiTop:.734375,deviceLqiBelowBottomBadgeTop:1.571875,devicePadding:.08,roomNameLineHeight:1.25,roomAreaLinkWidth:1.1,roomMetricsTopGap:.15,roomMetricFontSize:.75,roomMetricLineHeight:1.25,roomMetricIconWidth:1.05,roomMetricInnerGap:.12,roomMetricRowGap:.55,roomMetricMinWidth:11,roomPadding:.4,openingLockHalfSize:.62,roomMetricTextCharacters:Object.freeze({temperature:10,humidity:8,lqi:6,light:24})});function $e(e){return[...String(e)].reduce((e,t)=>/\s/.test(t)?e+Se.textSpaceAdvance:/[MW@#%&]/.test(t)?e+Se.textWideAsciiAdvance:e+(t.codePointAt(0)>255?Se.textWideAdvance:Se.textLatinAdvance),0)*Se.textWidthSafety}function ke(e,t){return $e(e)*z(t||e)}function ze(e,t){return[Math.max(Math.abs(e.left),Math.abs(e.right))+t,Math.max(Math.abs(e.top),Math.abs(e.bottom))+t]}function Ie(e){if("opening-lock"===e.kind){const t=(Number.isFinite(e.size)&&e.size>0?e.size:0)*Se.openingLockHalfSize;return[t,t]}if("room-label"===e.kind){const t=Number.isFinite(e.font)&&e.font>0?e.font:0,n=v(e.room.settings?.name_scale),o=v(e.room.settings?.label_scale),a=($e(e.room.name||"")+(e.room.area?Se.roomAreaLinkWidth:0))*n,i=Se.roomNameLineHeight*n,r=[e.display.labelTemp?Se.roomMetricTextCharacters.temperature:0,e.display.labelHum?Se.roomMetricTextCharacters.humidity:0,e.display.labelLqi&&e.room.area?Se.roomMetricTextCharacters.lqi:0,e.display.labelLight?Se.roomMetricTextCharacters.light:0].filter(e=>e>0),s=Se.roomMetricFontSize*o,l=r.length?Math.max(Se.roomMetricMinWidth,r.reduce((e,t)=>e+Se.roomMetricIconWidth+Se.roomMetricInnerGap+t*Se.textLatinAdvance*Se.textWidthSafety,0)+(r.length-1)*Se.roomMetricRowGap)*s:0,c=r.length?s*Se.roomMetricLineHeight:0,d=ze({left:-Math.max(a,l)/2,right:Math.max(a,l)/2,top:-i/2,bottom:r.length?i/2+Se.roomMetricsTopGap+c:i/2},Se.roomPadding);return[d[0]*t,d[1]*t]}const t=Number.isFinite(e.core)&&e.core>0?e.core:0,n=e.presentation,o=null==n.valueText?1:Math.max(1,ke(n.valueText,n.valueFullText||n.valueText)+Se.deviceValueInlinePadding),a=[];n.valueBadge&&a.push(Math.max(Se.deviceBadgeMinWidth,ke(n.valueBadge.text,n.valueBadge.fullText||n.valueBadge.text)+Se.deviceBadgeInlinePadding));for(const e of x(n)){const t=e.text+e.suffix;a.push(Math.max(Se.deviceBadgeMinWidth,ke(t,t)+Se.deviceBadgeInlinePadding))}const i=n.valueBadge?.position||"right";let r;if(!a.length||"left"!==i&&"right"!==i)if(a.length){const e=a.reduce((e,t)=>e+t,0)+(a.length-1)*Se.deviceSectionGap,t=Math.max(o,e),n=1+Se.deviceShellGap+Se.deviceBadgeHeight;r="bottom"===i?{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:-.5+n+Se.deviceShellInset}:{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:.5-n-Se.deviceShellInset,bottom:.5+Se.deviceShellInset}}else r={left:-.5-Se.deviceShellInset,right:-.5+o+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:.5+Se.deviceShellInset};else{const e=Math.max(...a),t=a.length*Se.deviceBadgeHeight+(a.length-1)*Se.deviceSectionGap,n=o+Se.deviceShellGap+e,s=Math.max(1,t);r="right"===i?{left:-.5-Se.deviceShellInset,right:-.5+n+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}:{left:.5-n-Se.deviceShellInset,right:.5+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}}const s=Se.deviceAuxiliaryExtent;if(r.left=Math.min(r.left,-s),r.right=Math.max(r.right,s),r.top=Math.min(r.top,-s),r.bottom=Math.max(r.bottom,s),n.pulse.animated){const e=Math.max(1,n.pulse.diameterScale)/2;r.left=Math.min(r.left,-e),r.right=Math.max(r.right,e),r.top=Math.min(r.top,-e),r.bottom=Math.max(r.bottom,e)}if(null!=n.lqiText){const e="bottom"===n.valueBadge?.position?Se.deviceLqiBelowBottomBadgeTop:Se.deviceLqiTop,t=$e(n.lqiText)*Se.deviceLqiFontSize/2;r.left=Math.min(r.left,-t),r.right=Math.max(r.right,t),r.bottom=Math.max(r.bottom,e+Se.deviceLqiFontSize)}const l=ze(r,Se.devicePadding);return[l[0]*t,l[1]*t]}function Pe(e,t){return e.flatMap((e,n)=>e.orphanReason?[]:[{id:String(e.id||n),sourceIndex:n,type:e.type,x:e.rx,y:e.ry,angle:Number(e.angle)||0,length:e.rlen>0?e.rlen:.9*t,flipH:!!e.flip_h,flipV:!!e.flip_v}])}function Ce(e){return{id:e.id,x:e.x,y:e.y,w:e.w,h:e.h,poly:e.poly,wall_ids:e.wall_ids}}function je(e,t){const n=e?.partitionHost;if(!n)return null;const o="gate"===t.type?!t.flipV:t.flipV;return{sourceIndex:t.sourceIndex,hostId:n.host.id,t:n.t,depth:n.depth,face:p(n,o)}}function Ne(n,o=H){const a=Pe(n.openings,n.coordinateScale),r=a.map(e=>je(n.openings[e.sourceIndex],e)),p=i(t,n.cellCm),m=i(s,n.cellCm),g=i(l,n.cellCm);return{key:`${n.space.id}|${function(e){let t=2166136261;const n=e=>{if("number"!=typeof e)if("string"!=typeof e)if("boolean"!=typeof e)if(Array.isArray(e)){t=R(t,e.length);for(const t of e)n(t)}else{if(e&&"object"==typeof e){const t=e;for(const e of Object.keys(t).sort())n(e),n(t[e]);return}t=R(t,-1)}else t=R(t,e?1:0);else for(const n of e)t=R(t,n.codePointAt(0)||0);else t=R(t,e)};return n(e),t.toString(36)}({rooms:n.space.rooms.map(Ce),walls:n.walls,openCuts:n.openCuts,openings:a,openingHosts:r,openingGeometryPolicy:o,partitions:n.space.partitions,roomDrafts:n.space.room_drafts,columns:n.space.wall_columns,cellCm:n.cellCm,gridPitch:n.gridPitch,wallKeyPitch:n.wallKeyPitch,camera:e,wallHeight:p,raisedHeight:g,floorEdgeHeight:m,algorithm:4})}`,build:()=>{n.onBuild();const i=c(n.space,n.cellCm,n.gridPitch,2e-4*n.gridPitch,n.partitionCuts()).all,s=n.roomOpenings(),l=n.walls.length||i.length?d(n.space.rooms,n.walls,n.openCuts,s,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale,i):null;if(l&&("failed-core"===l.status||"not-applicable"===l.status))throw new Error("wall boolean geometry failed");const m=l?.paperGeom??f(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale);if(!m)throw new Error("floor boolean geometry failed");const g=l?.openingIndex||u(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale),w=a.map((e,a)=>{const i=r[a],s="gate"===e.type?!e.flipV:e.flipV,l=i?i.face:n.walls.length||"gate"===e.type?h(g,{x:e.x,y:e.y,angle:e.angle,length:e.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(e,n=t,o=H){const a=e.face.cm??0;if(!F([e.x,e.y,e.angle,e.length,e.face.ox,e.face.oy,a,n])||!(e.length>0)||!(n>0)||-1!==e.face.side&&1!==e.face.side||a<0)throw new Error("invalid isometric opening input");const i=e.length/2,r=e.angle*Math.PI/180,s=T(Math.cos(r),Math.sin(r)),l=T(-Math.sin(r),Math.cos(r)),c=T(e.x,e.y),d=T(e.x-s[0]*i,e.y-s[1]*i),f=T(e.x+s[0]*i,e.y+s[1]*i),u=T(e.face.ox,e.face.oy),h=T(d[0]+u[0],d[1]+u[1]),p=T(f[0]+u[0],f[1]+u[1]),m=T(d[0]-u[0],d[1]-u[1]),g=T(f[0]-u[0],f[1]-u[1]),w=Object.freeze({center:c,tangent:s,normal:l,start:d,end:f}),y=Object.freeze({side:e.face.side,cm:a,depth:2*Math.hypot(e.face.ox,e.face.oy),offset:u,selectedStart:h,selectedEnd:p,oppositeStart:m,oppositeEnd:g}),v="passage"===e.type?[]:[Object.freeze({jamb:0,center:d,selected:h,opposite:m}),Object.freeze({jamb:1,center:f,selected:p,opposite:g})];let x;if("passage"===e.type)x=[];else if("gate"===e.type){const t=e.face.side*o.gateTurnDeg;x=[E(e,0,[-i,0],[i,0],t,0,n*o.gateTopRatio),E(e,1,[i,0],[-i,0],-t,0,n*o.gateTopRatio)]}else x="window"===e.type?[E(e,0,[-i,0],[i,0],-90,n*o.windowBottomRatio,n*o.windowTopRatio),E(e,1,[i,0],[-i,0],90,n*o.windowBottomRatio,n*o.windowTopRatio)]:[E(e,0,[-i,0],[e.length,0],-90,0,n*o.doorTopRatio)];return Object.freeze({id:e.id,sourceIndex:e.sourceIndex,type:e.type,wallHeight:n,leafThickness:n*o.leafThicknessRatio,frameThickness:n*o.frameThicknessRatio,axis:w,face:y,reveals:Object.freeze(v),leaves:Object.freeze(x.map(e=>Object.freeze({...e,hinge:T(e.hinge[0],e.hinge[1]),closedVector:T(e.closedVector[0],e.closedVector[1]),quarterVector:T(e.quarterVector[0],e.quarterVector[1])})))})}({...e,face:l},p,o)}),y=Object.freeze(w);return{walls:l?.components.flatMap(e=>e.geom)||[],floor:m,openings:y,openingSurfaces:Object.freeze(y.flatMap(t=>function(t,n=e){if("passage"===t.type)return Object.freeze([]);const o=[];if(t.face.depth>1e-9)for(const e of t.reveals)o.push(_("jamb-reveal","reveal",e.selected,e.opposite,0,t.wallHeight,n,{jamb:e.jamb}));if("window"!==t.type||!t.leaves.length)return Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)));const a=Math.min(...t.leaves.map(e=>e.bottom)),i=Math.max(...t.leaves.map(e=>e.top)),r=Math.min(t.frameThickness,Math.hypot(t.axis.end[0]-t.axis.start[0],t.axis.end[1]-t.axis.start[1])/4,(i-a)/4),s=L(t.axis.start,G(t.axis.tangent,r)),l=V(t.axis.end,G(t.axis.tangent,r)),c=t.face.depth>1e-9?[t.face.offset,T(-t.face.offset[0],-t.face.offset[1])]:[t.face.offset];for(const e of c){const c=L(t.axis.start,e),d=L(t.axis.end,e),f=L(s,e),u=L(l,e);o.push(_("window-frame-side","light-frame",c,f,a,i,n,{jamb:0}),_("window-frame-side","light-frame",u,d,a,i,n,{jamb:1}),_("window-frame-top","light-frame",f,u,Math.max(a,i-r),i,n))}return t.face.depth>1e-9&&o.push(D("window-sill","light-sill",[{point:t.face.selectedStart,z:a},{point:t.face.selectedEnd,z:a},{point:t.face.oppositeEnd,z:a},{point:t.face.oppositeStart,z:a}],n)),Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)))}(t).map(e=>Object.freeze({...e,id:t.id,sourceIndex:t.sourceIndex,type:t.type}))))}}}}const Oe=e=>Array.isArray(e)?e:[];function Ae(e,t){const o=e=>Oe(e).flatMap(e=>Array.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])?[n([Number(e[0]),Number(e[1])],t)]:[]);return Oe(e).flatMap(e=>{const t=Oe(e);if(!t.length)return[];const n=o(t[0]);if(n.length<3)return[];return[{outer:n,holes:t.slice(1).map(o).filter(e=>e.length>=3)}]})}function Be(o){const a=i(t,o.cellCm),r=i(s,o.cellCm),c=i(l,o.cellCm),d=S(o.cache,o.source.key);let f=d.hit?d.value:void 0;if(!f){const i=o.source.build(),s=function(o,a=e,i=t){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const r=[],s=[],l=[],c=[];let d=0;for(let e=0;e<(o||[]).length;e++){const t=o[e],f=[];let u=-1/0;for(let o=0;o<(t||[]).length;o++){const s=N(t[o],o>0);if(s.length<3||Math.abs(j(s))<1e-9)continue;const h=O(s,a,i);r.push(h),f.push(h),u=Math.max(u,...s.map(e=>n(e,i,a)[1])),d+=s.length;for(let t=0;te.depth-t.depth||e.polygon-t.polygon||e.ring-t.ring||e.edge-t.edge),s.sort((e,t)=>e.depth-t.depth||e.component-t.component),{topPath:r.join(" "),topFaces:s,sides:l,contactPath:c.join(" "),edgeCount:d}}(i.walls,e,a),l=Ae(i.walls,a);f={geometry:s,floor:B(i.floor,r),wallSilhouettes:Object.freeze([...l,...s.sides.map(e=>({outer:e.points}))]),openings:i.openings,openingSurfaces:i.openingSurfaces},$(o.cache,o.source.key,f,8)}const u=function(e){let t=1/0,n=1/0,o=-1/0,a=-1/0;const i=(e,i=0)=>{t=Math.min(t,e[0]-i),n=Math.min(n,e[1]-i),o=Math.max(o,e[0]+i),a=Math.max(a,e[1]+i)};for(const t of e)if("passage"!==t.type){i(t.axis.start),i(t.axis.end),i(t.face.selectedStart),i(t.face.selectedEnd),i(t.face.oppositeStart),i(t.face.oppositeEnd);for(const e of t.leaves){const n=Math.hypot(e.closedVector[0],e.closedVector[1])+t.leafThickness/2;i(e.hinge,n)}}return F([t,n,o,a])?{x:t,y:n,w:o-t,h:a-n}:null}(f.openings),h=u?Re(o.liveFrame,u):o.liveFrame,p=k({rect:h,wallHeight:a,openingHeight:a,floorDepth:r,raisedHeight:c});return{key:o.source.key,...f,frame:p}}const Re=(e,t)=>{const n=Math.min(e.x,t.x),o=Math.min(e.y,t.y);return{x:n,y:o,w:Math.max(e.x+e.w,t.x+t.w)-n,h:Math.max(e.y+e.h,t.y+t.h)-o}},He=e=>{if(!e.length||!e.every(e=>Number.isFinite(e[0])&&Number.isFinite(e[1])))return null;const t=e.map(e=>e[0]),n=e.map(e=>e[1]),o=Math.min(...t),a=Math.min(...n);return{x:o,y:a,w:Math.max(...t)-o,h:Math.max(...n)-a}},Fe=(e,t)=>{const n=e.placement,o=t?n.visualScene:n.raisedScene,[a,i]=e.screenHalfSize,r=t?n.footprint:n.footprint.map(e=>[e[0]-n.nudgeScene[0],e[1]-n.nudgeScene[1]]);return[n.floorScene,...r,[o[0]-a,o[1]-i],[o[0]+a,o[1]-i],[o[0]+a,o[1]+i],[o[0]-a,o[1]+i]]},Te=(e,t)=>void 0===t?e:e.filter(e=>e.placement.owner?.id===t);function Le(e,t){return e?He(Te(e.entries,t).flatMap(e=>Fe(e,!0))):null}function Ve(e){const t=Te(e.entries,e.ownerId),n=He(t.flatMap(e=>Fe(e,!1))),o=n?Re(e.baseBounds,n):e.baseBounds,a=e.targetView(o);if(!(a&&a.w>0&&a.h>0&&[a.x,a.y,a.w,a.h].every(Number.isFinite)))return null;const i=e.stageSize;if(!(n&&i&&i.width>0&&i.height>0))return{bounds:o,view:a};const r=e=>Math.max(e.w/i.width,e.h/i.height),s=t=>{const o=48*t,a={x:n.x-o,y:n.y-o,w:n.w+2*o,h:n.h+2*o},i=Re(e.baseBounds,a),r=e.targetView(i);return r&&[r.x,r.y,r.w,r.h].every(Number.isFinite)&&r.w>0&&r.h>0?{bounds:i,view:r}:null};let l=0,c=Math.max(r(a),Number.EPSILON),d=s(c);for(let e=0;d&&r(d.view)>c*(1+1e-10)&&e<24;e++)l=c,c*=2,d=s(c);if(!d)return null;for(let e=0;e<40;e++){const e=(l+c)/2,t=s(e);if(!t)return null;r(t.view)<=e?(c=e,d=t):l=e}return d}const Ge=new WeakMap,We=2048,Ee=new WeakMap,qe=new WeakMap,De=new WeakMap;function _e(e,t){if(e.size!==t.size)return!1;for(const[n,o]of t)if(e.get(n)!==o)return!1;return!0}function Ue(e){const t=Ge.get(e.rooms);if(t)return t;const n=e.rooms.flatMap((e,t)=>{const n=w(e);return n&&n.length>=3?[{room:e,index:t,poly:n}]:[]}),o=Object.freeze(n.map(({room:e,index:t,poly:o})=>{const a=y(o,n.filter(e=>e.index!==t).map(e=>e.poly)),i={id:e.id||`room-index-${t}`,outer:o.map(e=>[e[0],e[1]]),holes:a.map(e=>e.map(e=>[e[0],e[1]]))};return{room:e,overlayRoom:{...i,safePoint:ae(i)||void 0}}}));return Ge.set(e.rooms,o),o}function Ke(o){const s=o.stageSize&&o.stageSize.width>0&&o.stageSize.height>0?Math.max(o.view.w/o.stageSize.width,o.view.h/o.stageSize.height):Math.max(o.view.w,o.view.h)/1e3,l=Ue(o.space),c=l.map(e=>e.overlayRoom),d=i(t,o.cellCm),f=i(a,o.cellCm),u=new Map,h=new Map,p=new Map,m=[];let g=Ee.get(o.wallSilhouettes);g||(g=new Map,Ee.set(o.wallSilhouettes,g));let w=qe.get(l);w||(w=new Map,qe.set(l,w));const y=o.iconPct*r(o.space)*o.kioskIconScale/100,v=o.deviceBasePct*r(o.space)*o.kioskIconScale/100,x=(i,r,l,u,h,p=!1)=>{const m=`${!1===o.resolveCollisions?"fit":"live"}\0${i}\0${r}`,y=[l[0],l[1],u[0],u[1],h||"",d,f,o.layers.shadows?1:0,p?1:0].join("|"),v=`${y}|${s}`,x=S(g,m);if(x.hit&&x.value.signature===v)return x.value.placement;if(x.hit&&x.value.shapeSignature===y&&s<=x.value.unitsPerPixel){const e=x.value.placement,t=e.nudgeDistanceCss*x.value.unitsPerPixel/s;if(!e.nearWallBefore||e.cleared&&t<=48)return e}const M=`${i}\0${r}`,b=[l[0],l[1],h||""].join("|"),k=S(w,M),z=k.hit&&k.value.signature===b?k.value.owner:ie({kind:i,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:h});k.hit&&k.value.signature===b||$(w,M,{signature:b,owner:z},We);const I=function(o){const i=o.camera||e,r=o.wallHeight??t,s=o.visualOffset??a,l=o.sceneUnitsPerCssPixel??1,c=o.safetyGapCssPx??4,d=o.maxNudgeCssPx??48;if(!Z(o.floorAnchor)||!Z(o.footprintHalfSize)||o.footprintHalfSize[0]<0||o.footprintHalfSize[1]<0||!Number.isFinite(r)||r<0||!Number.isFinite(s)||s<0||!Number.isFinite(l)||l<=0||!Number.isFinite(c)||c<0||!Number.isFinite(d)||d<0)throw new Error("invalid isometric overlay input");const f=[o.floorAnchor[0],o.floorAnchor[1]],u=n(f,0,i),h=(p=o.kind,!o.showBorders||"device"!==p&&"room-label"!==p&&"opening-lock"!==p?"floor":"raised");var p;if("floor"===h)return{plane:h,owner:null,floorAnchor:f,floorScene:u,raisedScene:u,visualScene:u,footprint:[],nudgeScene:[0,0],nudgeCss:[0,0],nudgeDistanceCss:0,nudged:!1,nearWallBefore:!1,nearWallAfter:!1,cleared:!0,capped:!1,grounding:{center:u,visible:!1},tether:ye(u,u,!1),status:"ok",reason:null};const m=r+s,g=n(f,m,i),w=o.ownerAlreadyResolved?o.resolvedOwner??null:ie(o),y=o.wallGeometryValidated??o.wallSilhouettes.every(ge),v=c*l,x=re(f,o.footprintHalfSize,m,i),M=e=>{const t=fe(e);return!!t&&o.wallSilhouettes.some(n=>me(e,t,n,v,!0===o.wallGeometryValidated))},b=!y||M(x);let S=0,$=[0,0],k=null,z=!1,I=y?"ok":"degraded",P=y?null:"invalid-wall-geometry";if(y&&b)if(w)if(w.safePoint){const e=o.rooms.find(e=>e.id===w.id)||null,t=n(w.safePoint,m,i),a=t[0]-g[0],r=t[1]-g[1],s=Math.hypot(a,r);if(s<=K)I="degraded",P="invalid-safe-point";else{const t=a/s,n=r/s,i=Math.min(d,s/l),c=i*l/s,u=[f[0]+(w.safePoint[0]-f[0])*c,f[1]+(w.safePoint[1]-f[1])*c],h=[t*i*l,n*i*l],p=fe([...x,...x.map(e=>[e[0]+h[0],e[1]+h[1]])]),m=p?o.wallSilhouettes.filter(e=>{const t=ue(e,!0===o.wallGeometryValidated);return!!t&&he(p,t,v)}):o.wallSilhouettes,g=!!e&&we(f,u,e),y=e=>{const a=[t*e*l,n*e*l],i=x.map(e=>[e[0]+a[0],e[1]+a[1]]),r=fe(i);return!!r&&m.some(e=>me(i,r,e,v,!0===o.wallGeometryValidated))},M=o.nudgeHintCss;if(Number.isFinite(M)&&M>=0&&M<=i){const t=M*l/s,n=[f[0]+(w.safePoint[0]-f[0])*t,f[1]+(w.safePoint[1]-f[1])*t];(g||e&&we(f,n,e))&&!y(M)&&(S=M,k=!1)}if(null===k){let t=null,n=0,o=!1;const a=Math.ceil(i);for(let r=1;r<=a;r++){const a=Math.min(i,r),c=a*l/s,d=[f[0]+(w.safePoint[0]-f[0])*c,f[1]+(w.safePoint[1]-f[1])*c];if(!(g||e&&we(f,d,e))){o=!0;break}if(!y(a)){t=a;break}n=a}if(null!==t){let e=n,o=t;for(let t=0;t<14;t++){const t=(e+o)/2;y(t)?e=t:o=t}S=o}else S=n,z=!0,I="degraded",P=o?"owner-boundary":"nudge-cap"}$=[t*S*l,n*S*l]}}else I="degraded",P="invalid-safe-point";else I="degraded",P="missing-owner";const C=[g[0]+$[0],g[1]+$[1]],j=re(f,o.footprintHalfSize,m,i,$),N=!y||(k??M(j)),O=S>K,A=O||b||N||!!o.hovered||!!o.focused||!!o.selected;return{plane:h,owner:w,floorAnchor:f,floorScene:u,raisedScene:g,visualScene:C,footprint:j,nudgeScene:$,nudgeCss:[$[0]/l,$[1]/l],nudgeDistanceCss:S,nudged:O,nearWallBefore:b,nearWallAfter:N,cleared:!N,capped:z,grounding:{center:u,visible:!1!==o.filtersSupported},tether:ye(u,C,A),status:I,reason:P}}({kind:i,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:h,ownerAlreadyResolved:!0,resolvedOwner:z,nudgeHintCss:x.hit&&x.value.shapeSignature===y?x.value.placement.nudgeDistanceCss*x.value.unitsPerPixel/s:void 0,showBorders:!0,wallSilhouettes:!1===o.resolveCollisions?[]:o.wallSilhouettes,wallGeometryValidated:!0,footprintHalfSize:u,wallHeight:d,visualOffset:f,sceneUnitsPerCssPixel:s,filtersSupported:o.layers.shadows,hovered:!0,selected:p});return $(g,m,{signature:v,shapeSignature:y,unitsPerPixel:s,placement:I},We),I};for(const e of o.devices){const t=o.positionOf(e),n=o.presentationOf(e,o.showLqi),a=v*n.scale,i=Ie({kind:"device",core:a,presentation:n}),r=e.marker?.room_id||l.find(t=>!!e.area&&t.room.area===e.area)?.overlayRoom.id||null,s=x("device",e.id,[t.x,t.y],i,r,o.selectedDeviceId===e.id);u.set(e.id,s),m.push({id:e.id,kind:"device",placement:s,groundRadius:Math.max(.32*a,2),screenHalfSize:i})}for(const{room:e,overlayRoom:t}of l){if(!o.display.showNames||!e.name)continue;const n=o.labelPositionOf(e,o.space.id),a=.5*y*(o.labelScaleOf(e)*o.kioskFontScale*o.display.cardFontScale),i=Ie({kind:"room-label",font:a,room:e,display:o.display}),r=x("room-label",t.id,[n.x,n.y],i,t.id,o.focusedRoomId===e.id);h.set(e,r),m.push({id:t.id,kind:"room-label",placement:r,groundRadius:Math.max(.75*a,2),screenHalfSize:i})}const M=o.openings.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&"string"==typeof e.lock&&!!e.lock&&o.openingEntityAvailable(e.lock));if(M.length){const e=o.openingWallIndex();for(const t of M){const n=Qe(t,e,o.cellCm),a=n.floorAnchor,i=.62*y,r=Ie({kind:"opening-lock",size:i}),s=x("opening-lock",String(t.id),a,r,n.preferredRoomId,o.selectedOpeningId===t.id);p.set(String(t.id),s),m.push({id:String(t.id),kind:"opening-lock",placement:s,groundRadius:Math.max(.28*i,2),screenHalfSize:r})}}const b={devices:u,rooms:h,locks:p,entries:Object.freeze(m)},k=!1===o.resolveCollisions?"fit":"live";let z=De.get(o.wallSilhouettes);z||(z=new Map,De.set(o.wallSilhouettes,z));const I=z.get(k);return I&&function(e,t){return e.length===t.length&&t.every((t,n)=>{const o=e[n];return o.id===t.id&&o.kind===t.kind&&o.placement===t.placement&&o.groundRadius===t.groundRadius&&o.screenHalfSize[0]===t.screenHalfSize[0]&&o.screenHalfSize[1]===t.screenHalfSize[1]})}(I.entries,b.entries)&&_e(I.devices,b.devices)&&_e(I.rooms,b.rooms)&&_e(I.locks,b.locks)?I:(z.set(k,b),b)}function Ze(e,t,n){return Qe(e,t,n).floorAnchor}function Qe(e,t,n){const o=!e.flip_v,a="gate"===e.type?e.partitionHost?p(e.partitionHost,o):h(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen,flip_v:o}):null,[i,r]=m({x:e.rx,y:e.ry,angle:e.angle,flipV:!!e.flip_v,gateFace:a},n);if(e.partitionHost)return{floorAnchor:i,preferredRoomId:null};const s=g(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen},!0),l=r?"negative":"positive";return{floorAnchor:i,preferredRoomId:s[l]?.roomId||null}}function Je(e){let t=!1;try{t="undefined"!=typeof CSS&&"function"==typeof CSS.supports&&CSS.supports("filter","blur(1px)")}catch{t=!1}let n=!1;try{n="function"==typeof matchMedia&&matchMedia("(forced-colors: active)").matches}catch{n=!0}return function(e){const t=!!e.showBorders;return{structural:t,panels:t&&!e.hideOpenings,shadows:t&&e.filtersSupported&&!e.forcedColors,materialNuance:t&&e.filtersSupported&&!e.forcedColors,floorSymbols:!e.hideOpenings&&!t}}({showBorders:e.showBorders,hideOpenings:e.hideOpenings,filtersSupported:t,forcedColors:n})}function Xe(e,t,n,o){if(!e.panels||!t)return[];return t.openings.flatMap(e=>{const t=n[e.sourceIndex];return t?U(e,o(t)):[]}).sort((e,t)=>e.depth-t.depth||e.sourceIndex-t.sourceIndex||e.leaf-t.leaf)}function Ye(e){const t=Je(e.display),n=t.panels?Xe(t,e.scene,e.openings,e.amountOf):[],o=e.overlays(t),a=t=>({layers:t,panels:n,overlays:o,underlay:it(t,e.scene?.floor,e.cellCm),shadows:rt(t,n,e.scene?.geometry,e.cellCm),walls:st(e.projection,t,e.scene,n,e.cellCm),grounds:ot(o,t,e.cellCm),raised:at(o)});try{return a(t)}catch(e){if(!t.shadows&&!t.materialNuance)throw e;return a({...t,shadows:!1,materialNuance:!1})}}const et=()=>b``;function tt(e){return`translate(${i(4,e)} ${i(8,e)})`}function nt(e,t,n){const o=I(n);return b` ${"walls"===t&&e.materialNuance?b` diff --git a/dist/houseplan-assets/live-interaction-runtime-D5KHv4hp.js b/dist/houseplan-assets/live-interaction-runtime-DNx7W_iY.js similarity index 80% rename from dist/houseplan-assets/live-interaction-runtime-D5KHv4hp.js rename to dist/houseplan-assets/live-interaction-runtime-DNx7W_iY.js index 1b95ecdf..5b5893e6 100644 --- a/dist/houseplan-assets/live-interaction-runtime-D5KHv4hp.js +++ b/dist/houseplan-assets/live-interaction-runtime-DNx7W_iY.js @@ -1 +1 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{dO as e}from"./houseplan-card-CODdCIWj.js";const t=new WeakMap,n=e=>{let n=t.get(e);return n||(n={painted:null,pending:null,raf:0},t.set(e,n)),n},o=e=>`${e.x} ${e.y} ${e.w} ${e.h}`;const r=e=>0===e.translateXPercent&&0===e.translateYPercent&&1===e.scaleX&&1===e.scaleY,a=e=>[e.x,e.y,e.w,e.h].every(Number.isFinite)&&e.w>0&&e.h>0,s=(e,t)=>{if(!t)return e.style.removeProperty("transform"),e.style.removeProperty("transform-origin"),void e.style.removeProperty("will-change");e.style.transformOrigin="0 0",e.style.willChange="transform",e.style.transform=`translate(${t.translateXPercent}%,${t.translateYPercent}%) scale(${t.scaleX},${t.scaleY})`};function i(e,t,n){if(!a(t.view)||!a(n.view)||!a(n.floor))return;const i=o(n.view),l=o(n.floor);for(const t of e.querySelectorAll('[data-hp-live-viewbox="camera"]'))t.setAttribute("viewBox",i);for(const t of e.querySelectorAll('[data-hp-live-viewbox="floor"]'))t.setAttribute("viewBox",l);const c=(f=t.view,u=n.view,{translateXPercent:(f.x-u.x)/u.w*100,translateYPercent:(f.y-u.y)/u.h*100,scaleX:f.w/u.w,scaleY:f.h/u.h});var f,u;for(const t of e.querySelectorAll('[data-hp-live-layer="camera"]'))s(t,r(c)?null:c);const d=e.querySelector("[data-hp-live-zoom]");if(d){d.hidden=n.zoom<=1;const e=d.querySelector("[data-hp-live-zoom-value]");e&&(e.textContent=`${Math.round(100*n.zoom)}%`)}}const l=e=>{const t=e._viewOr(e._baseVb());return{view:{...t},floor:{...e._floorView(t)},zoom:e._zoom}};const c=new WeakMap,f=(e,t,n,o)=>{if(!n)return;const r=document.createElement("span");if(r.className="m",t){r.append(`${t} `);const e=document.createElement("b");e.textContent=n,o&&(e.style.color=o),r.append(e)}else r.textContent=n;e.append(r)},u=(e,t,n)=>{const o=e.querySelector(t);o&&(o.setAttribute("d",n),o.toggleAttribute("hidden",!n))};function d(t){const n=t,o=n.renderRoot;if(!o)return;((t,n)=>{const o=n.querySelector("[data-hp-live-tip]");if(!o)return;const r=t._tip;if(!r)return o.hidden=!0,void o.replaceChildren();o.style.left=`${r.x+12}px`,o.style.top=`${r.y+12}px`,o.replaceChildren();const a=document.createElement("b");a.textContent=r.title,o.append(a),f(o,"",r.meta),f(o,t._t("tip.temp_avg"),null==r.temp?"":`${r.temp}°`),f(o,t._t("tip.hum_avg"),null==r.hum?"":`${r.hum}%`),f(o,t._t("tip.lqi"),null==r.lqi?"":String(r.lqi),null==r.lqi?void 0:e(r.lqi)),o.hidden=!1})(n,o);const r=n._hoverRoom,a=c.get(t),s=r?.space||"",i=r?.room||null;if(a?.room===i&&a?.space===s)return;c.set(t,{room:i,space:s});const l=r&&n._spaceModel(),d=l?n._roomHoverPaths(l):null;u(o,'[data-hp-live-room-hover="fill"]',d?.fillD||""),u(o,'[data-hp-live-room-hover="halo"]',d?.outlineD||""),u(o,'[data-hp-live-room-hover="outline"]',d?.outlineD||"")}function m(e){c.delete(e)}class p{constructor(e){this.host=e,this.deferredHass=!1}hass(e,t,n,o){const r=function(e,t,n){if(e===t)return"none";if(!e||!t||!n)return"structural";if(e.connection!==t.connection||e.entities!==t.entities||e.devices!==t.devices||e.areas!==t.areas||e.themes!==t.themes||e.user!==t.user||e.config!==t.config||e.floors!==t.floors||e.services!==t.services||e.panels!==t.panels||e.language!==t.language||e.locale?.language!==t.locale?.language||e.locale?.number_format!==t.locale?.number_format||e.locale?.time_format!==t.locale?.time_format||e.locale?.date_format!==t.locale?.date_format)return"structural";const o=new Set(["states","connection","entities","devices","areas","themes","user","config","floors","services","panels","language","locale"]);for(const n of new Set([...Object.keys(e),...Object.keys(t)]))if(!o.has(n)&&e[n]!==t[n])return"structural";for(const o of n.entityIds)if(e.states?.[o]!==t.states?.[o])return"state";return"none"}(e,t,n),a="state"===r&&this.active();a&&(this.deferredHass=!0);const s="none"!==r&&!a;return s||this.host._renderLife.observe(e,t,n,o),s}clear(){this.deferredHass=!1}take(){const e=this.deferredHass;return this.deferredHass=!1,e}viewport(e=!1){!function(e,t=!1){const o=e,r=n(e),a=l(o);if(t)return r.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(r.raf),r.raf=0,r.pending=null,r.painted||(r.painted=a),void i(o.renderRoot,r.painted,a);r.pending=a,r.raf||"function"!=typeof requestAnimationFrame||(r.raf=requestAnimationFrame(()=>{r.raf=0;const e=r.pending;r.pending=null;const t=o.renderRoot;e&&t&&(r.painted||(r.painted=e),i(t,r.painted,e))}))}(this.host,e)}hover(){d(this.host)}active(){const e=this.host;return e._pointers.size>0||e._cameraTransition.active||!!e._deviceDrag||!!e._physicalDrag||!!e._physicalRotate||!!e._decorMove||!!e._decorDraft||!!e._dtDrag||!!e._bdDrag||!!e._opDrag||!!e._resize?.dragging}commit(){!function(e){const t=e,o=n(e);o.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(o.raf),o.raf=0,o.pending=null,o.painted=l(t);const r=t.renderRoot;if(r){for(const e of r.querySelectorAll('[data-hp-live-layer="camera"]'))s(e,null);i(r,o.painted,o.painted)}}(this.host),m(this.host),d(this.host)}dispose(){!function(e){const n=t.get(e);n?.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(n.raf),t.delete(e)}(this.host),m(this.host)}}export{p as LiveRuntime}; +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{dQ as e}from"./houseplan-card-Bhpi71t0.js";const t=new WeakMap,n=e=>{let n=t.get(e);return n||(n={painted:null,pending:null,raf:0},t.set(e,n)),n},o=e=>`${e.x} ${e.y} ${e.w} ${e.h}`;const r=e=>0===e.translateXPercent&&0===e.translateYPercent&&1===e.scaleX&&1===e.scaleY,a=e=>[e.x,e.y,e.w,e.h].every(Number.isFinite)&&e.w>0&&e.h>0,s=(e,t)=>{if(!t)return e.style.removeProperty("transform"),e.style.removeProperty("transform-origin"),void e.style.removeProperty("will-change");e.style.transformOrigin="0 0",e.style.willChange="transform",e.style.transform=`translate(${t.translateXPercent}%,${t.translateYPercent}%) scale(${t.scaleX},${t.scaleY})`};function i(e,t,n){if(!a(t.view)||!a(n.view)||!a(n.floor))return;const i=o(n.view),l=o(n.floor);for(const t of e.querySelectorAll('[data-hp-live-viewbox="camera"]'))t.setAttribute("viewBox",i);for(const t of e.querySelectorAll('[data-hp-live-viewbox="floor"]'))t.setAttribute("viewBox",l);const c=(f=t.view,d=n.view,{translateXPercent:(f.x-d.x)/d.w*100,translateYPercent:(f.y-d.y)/d.h*100,scaleX:f.w/d.w,scaleY:f.h/d.h});var f,d;for(const t of e.querySelectorAll('[data-hp-live-layer="camera"]'))s(t,r(c)?null:c);const u=e.querySelector("[data-hp-live-zoom]");if(u){u.hidden=n.zoom<=1;const e=u.querySelector("[data-hp-live-zoom-value]");e&&(e.textContent=`${Math.round(100*n.zoom)}%`)}}const l=e=>{const t=e._viewOr(e._baseVb());return{view:{...t},floor:{...e._floorView(t)},zoom:e._zoom}};const c=new WeakMap,f=(e,t,n,o)=>{if(!n)return;const r=document.createElement("span");if(r.className="m",t){r.append(`${t} `);const e=document.createElement("b");e.textContent=n,o&&(e.style.color=o),r.append(e)}else r.textContent=n;e.append(r)},d=(e,t,n)=>{const o=e.querySelector(t);o&&(o.setAttribute("d",n),o.toggleAttribute("hidden",!n))};function u(t){const n=t,o=n.renderRoot;if(!o)return;((t,n)=>{const o=n.querySelector("[data-hp-live-tip]");if(!o)return;const r=t._tip;if(!r)return o.hidden=!0,void o.replaceChildren();o.style.left=`${r.x+12}px`,o.style.top=`${r.y+12}px`,o.replaceChildren();const a=document.createElement("b");a.textContent=r.title,o.append(a),f(o,"",r.meta),f(o,t._t("tip.temp_avg"),null==r.temp?"":`${r.temp}°`),f(o,t._t("tip.hum_avg"),null==r.hum?"":`${r.hum}%`),f(o,t._t("tip.lqi"),null==r.lqi?"":String(r.lqi),null==r.lqi?void 0:e(r.lqi)),o.hidden=!1})(n,o);const r=n._hoverRoom,a=c.get(t),s=r?.space||"",i=r?.room||null;if(a?.room===i&&a?.space===s)return;c.set(t,{room:i,space:s});const l=r&&n._spaceModel(),u=l?n._roomHoverPaths(l):null;d(o,'[data-hp-live-room-hover="fill"]',u?.fillD||""),d(o,'[data-hp-live-room-hover="halo"]',u?.outlineD||""),d(o,'[data-hp-live-room-hover="outline"]',u?.outlineD||"")}function m(e){c.delete(e)}class p{constructor(e){this.host=e,this.deferredHass=!1}hass(e,t,n,o){const r=function(e,t,n){if(e===t)return"none";if(!e||!t||!n)return"structural";if(e.connection!==t.connection||e.entities!==t.entities||e.devices!==t.devices||e.areas!==t.areas||e.themes!==t.themes||e.user!==t.user||e.config!==t.config||e.floors!==t.floors||e.services!==t.services||e.panels!==t.panels||e.language!==t.language||e.locale?.language!==t.locale?.language||e.locale?.number_format!==t.locale?.number_format||e.locale?.time_format!==t.locale?.time_format||e.locale?.date_format!==t.locale?.date_format)return"structural";const o=new Set(["states","connection","entities","devices","areas","themes","user","config","floors","services","panels","language","locale"]);for(const n of new Set([...Object.keys(e),...Object.keys(t)]))if(!o.has(n)&&e[n]!==t[n])return"structural";for(const o of n.entityIds)if(e.states?.[o]!==t.states?.[o])return"state";return"none"}(e,t,n),a="state"===r&&this.active();a&&(this.deferredHass=!0);const s="none"!==r&&!a;return s||this.host._renderLife.observe(e,t,n,o),s}clear(){this.deferredHass=!1}take(){const e=this.deferredHass;return this.deferredHass=!1,e}viewport(e=!1){!function(e,t=!1){const o=e,r=n(e),a=l(o);if(t)return r.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(r.raf),r.raf=0,r.pending=null,r.painted||(r.painted=a),void i(o.renderRoot,r.painted,a);r.pending=a,r.raf||"function"!=typeof requestAnimationFrame||(r.raf=requestAnimationFrame(()=>{r.raf=0;const e=r.pending;r.pending=null;const t=o.renderRoot;e&&t&&(r.painted||(r.painted=e),i(t,r.painted,e))}))}(this.host,e)}hover(){u(this.host)}active(){const e=this.host;return e._pointers.size>0||e._cameraTransition.active||!!e._deviceDrag||!!e._physicalDrag||!!e._physicalRotate||!!e._decorMove||!!e._decorDraft||!!e._dtDrag||!!e._bdDrag||!!e._opDrag||!!e._resize?.dragging}commit(){!function(e){const t=e,o=n(e);o.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(o.raf),o.raf=0,o.pending=null,o.painted=l(t);const r=t.renderRoot;if(r){for(const e of r.querySelectorAll('[data-hp-live-layer="camera"]'))s(e,null);i(r,o.painted,o.painted)}}(this.host),m(this.host),u(this.host)}dispose(){!function(e){const n=t.get(e);n?.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(n.raf),t.delete(e)}(this.host),m(this.host)}}export{p as LiveRuntime}; diff --git a/dist/houseplan-assets/zigbee-topology-BUFPOnoy.js b/dist/houseplan-assets/zigbee-topology-B-C5QCCD.js similarity index 95% rename from dist/houseplan-assets/zigbee-topology-BUFPOnoy.js rename to dist/houseplan-assets/zigbee-topology-B-C5QCCD.js index d1356412..e54b0c11 100644 --- a/dist/houseplan-assets/zigbee-topology-BUFPOnoy.js +++ b/dist/houseplan-assets/zigbee-topology-B-C5QCCD.js @@ -1 +1 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{s as e,F as n}from"./houseplan-card-CODdCIWj.js";var t={title:"Zigbee links",toggle:"Show Zigbee links when hovering over a device",hint:"Shows observed direct neighbours only. Nothing is fetched while you hover.",help:"Shows which Zigbee devices each device talks to directly. Line colour is link quality (LQI) on the same scale as the device's LQI reading: red at 40 and below, green at 180 and above. A dashed line means quality was not reported. An arrow points to the next device on the way to the coordinator: one arrow leads out, incoming arrows are the devices that route through this one. A line without an arrow is a spare neighbour. This is the route tree House Plan builds, not the path a packet takes right now: a label at the end of an arrow means its target is not on this plan, and no arrow at all means the route is unknown. Data comes from the last load and goes stale; links are shown with a mouse only.",help_aria:"Help: Zigbee links",admin_only:"Topology data is available to Home Assistant administrators only.",save_first:"Save this setting before loading topology data.",zha:"ZHA",zha_read:"Read ZHA data",zha_hint:"Reads ZHA's cached topology; it does not start a radio scan.",z2m:"Zigbee2MQTT",z2m_topics:"Base topics (one per line)",z2m_update:"Update map",z2m_warning:"A network-map scan can take 10 seconds to 2 minutes and may temporarily reduce Zigbee responsiveness.",status_idle:"Data not loaded",status_loading:"Loading…",status_ready:"Received {time}",status_stale:"Received {time} · stale",status_partial:"Received {time} · some nodes were omitted",status_no_links:"Received {time} · no observed links found",error_permission:"Administrator permission is required.",error_unsupported:"This provider or Home Assistant API is unavailable.",error_timeout:"The provider did not respond in time.",error_invalid_topic:"Check the Zigbee2MQTT base topic.",error_invalid_payload:"The provider returned unsupported topology data.",error_provider:"Topology data could not be loaded.",remote_count:"+{n} in other spaces",route_device_not_on_plan:"device is not on the plan",route_coordinator_not_on_plan:"coordinator is not on the plan",route_other_space:"another space"};const i={en:t,ru:{title:"Связи Zigbee",toggle:"Показывать связи Zigbee при наведении на устройство",hint:"Показываются только наблюдаемые прямые соседи. Наведение ничего не запрашивает.",help:"Показывает, с какими устройствами Zigbee каждое связано напрямую. Цвет линии — качество связи (LQI) по той же шкале, что у показателя LQI устройства: красный при 40 и ниже, зелёный при 180 и выше. Пунктир — качество не сообщено. Стрелка ведёт к следующему устройству по пути к координатору: исходящая одна, входящие — те, кто ходит через это устройство. Линия без стрелки — запасной сосед. Это дерево маршрутов, которое строит House Plan, а не путь пакета в эту секунду: подпись на конце стрелки значит, что цель не на этом плане, а отсутствие стрелки — что путь неизвестен. Данные из последней загрузки и устаревают, связи видны только при работе мышью.",help_aria:"Справка: связи Zigbee",admin_only:"Данные топологии доступны только администраторам Home Assistant.",save_first:"Сохраните настройку перед загрузкой данных топологии.",zha:"ZHA",zha_read:"Прочитать данные ZHA",zha_hint:"Читает сохранённую топологию ZHA и не запускает радио-сканирование.",z2m:"Zigbee2MQTT",z2m_topics:"Базовые топики (по одному в строке)",z2m_update:"Обновить карту",z2m_warning:"Сканирование карты сети занимает от 10 секунд до 2 минут и временно может снизить отзывчивость Zigbee.",status_idle:"Данные не загружены",status_loading:"Загрузка…",status_ready:"Получено: {time}",status_stale:"Получено: {time} · данные устарели",status_partial:"Получено: {time} · часть узлов не показана",status_no_links:"Получено: {time} · наблюдаемые связи не найдены",error_permission:"Нужны права администратора.",error_unsupported:"Провайдер или API Home Assistant недоступен.",error_timeout:"Провайдер не ответил вовремя.",error_invalid_topic:"Проверьте базовый топик Zigbee2MQTT.",error_invalid_payload:"Провайдер вернул неподдерживаемые данные топологии.",error_provider:"Не удалось загрузить данные топологии.",remote_count:"+{n} в других пространствах",route_device_not_on_plan:"устройства нет на плане",route_coordinator_not_on_plan:"координатора нет на плане",route_other_space:"другое пространство"},de:{title:"Zigbee-Verbindungen",toggle:"Zigbee-Verbindungen beim Darüberfahren über ein Gerät anzeigen",hint:"Es werden nur beobachtete direkte Nachbarn angezeigt. Beim Darüberfahren werden keine Daten abgerufen.",help:"Zeigt, mit welchen Zigbee-Geräten jedes Gerät direkt verbunden ist. Die Linienfarbe ist die Verbindungsqualität (LQI) auf derselben Skala wie der LQI-Wert des Geräts: rot bei 40 und darunter, grün bei 180 und darüber. Eine gestrichelte Linie bedeutet, dass die Qualität nicht gemeldet wurde. Ein Pfeil zeigt auf das nächste Gerät auf dem Weg zum Koordinator: ein Pfeil führt hinaus, eingehende Pfeile sind die Geräte, die über dieses Gerät routen. Eine Linie ohne Pfeil ist ein Ersatznachbar. Das ist der Routenbaum, den House Plan bildet, nicht der Weg eines Pakets in diesem Moment: eine Beschriftung am Pfeilende bedeutet, dass das Ziel nicht auf diesem Plan liegt, und ein fehlender Pfeil, dass die Route unbekannt ist. Die Daten stammen aus dem letzten Laden und veralten; Verbindungen sind nur mit der Maus sichtbar.",help_aria:"Hilfe: Zigbee-Verbindungen",admin_only:"Topologiedaten sind nur für Home-Assistant-Administratoren verfügbar.",save_first:"Speichere diese Einstellung, bevor Topologiedaten geladen werden.",zha:"ZHA",zha_read:"ZHA-Daten lesen",zha_hint:"Liest den ZHA-Topologiecache; es wird kein Funkscan gestartet.",z2m:"Zigbee2MQTT",z2m_topics:"Basistopics (eines pro Zeile)",z2m_update:"Karte aktualisieren",z2m_warning:"Ein Netzwerkscan kann 10 Sekunden bis 2 Minuten dauern und Zigbee vorübergehend verlangsamen.",status_idle:"Daten nicht geladen",status_loading:"Wird geladen…",status_ready:"Empfangen: {time}",status_stale:"Empfangen: {time} · veraltet",status_partial:"Empfangen: {time} · einige Knoten fehlen",status_no_links:"Empfangen: {time} · keine beobachteten Verbindungen gefunden",error_permission:"Administratorrechte sind erforderlich.",error_unsupported:"Dieser Anbieter oder die Home-Assistant-API ist nicht verfügbar.",error_timeout:"Der Anbieter hat nicht rechtzeitig geantwortet.",error_invalid_topic:"Prüfe das Zigbee2MQTT-Basistopic.",error_invalid_payload:"Der Anbieter hat nicht unterstützte Topologiedaten geliefert.",error_provider:"Topologiedaten konnten nicht geladen werden.",remote_count:"+{n} in anderen Bereichen",route_device_not_on_plan:"Gerät ist nicht im Plan",route_coordinator_not_on_plan:"Koordinator ist nicht im Plan",route_other_space:"anderer Bereich"},fr:{title:"Liens Zigbee",toggle:"Afficher les liens Zigbee au survol d’un appareil",hint:"Seuls les voisins directs observés sont affichés. Le survol ne lance aucune requête.",help:"Montre avec quels appareils Zigbee chaque appareil communique directement. La couleur de la ligne est la qualité du lien (LQI) sur la même échelle que l'indicateur LQI de l'appareil : rouge à 40 et en dessous, vert à 180 et au-dessus. Une ligne pointillée signifie que la qualité n'a pas été communiquée. Une flèche pointe vers l'appareil suivant sur le chemin du coordinateur : une flèche part, les flèches entrantes sont les appareils qui passent par celui-ci. Une ligne sans flèche est un voisin de secours. C'est l'arbre de routes que construit House Plan, pas le trajet d'un paquet à cet instant : une étiquette au bout d'une flèche signifie que sa cible n'est pas sur ce plan, et l'absence de flèche que la route est inconnue. Les données proviennent du dernier chargement et vieillissent ; les liens ne sont visibles qu'à la souris.",help_aria:"Aide : liens Zigbee",admin_only:"Les données de topologie sont réservées aux administrateurs Home Assistant.",save_first:"Enregistrez ce réglage avant de charger les données de topologie.",zha:"ZHA",zha_read:"Lire les données ZHA",zha_hint:"Lit la topologie en cache de ZHA sans lancer d’analyse radio.",z2m:"Zigbee2MQTT",z2m_topics:"Topics de base (un par ligne)",z2m_update:"Actualiser la carte",z2m_warning:"L’analyse de la carte réseau peut durer de 10 secondes à 2 minutes et réduire temporairement la réactivité de Zigbee.",status_idle:"Données non chargées",status_loading:"Chargement…",status_ready:"Reçu : {time}",status_stale:"Reçu : {time} · obsolète",status_partial:"Reçu : {time} · certains nœuds sont omis",status_no_links:"Reçu : {time} · aucun lien observé trouvé",error_permission:"Les droits administrateur sont requis.",error_unsupported:"Ce fournisseur ou l’API Home Assistant n’est pas disponible.",error_timeout:"Le fournisseur n’a pas répondu à temps.",error_invalid_topic:"Vérifiez le topic de base Zigbee2MQTT.",error_invalid_payload:"Le fournisseur a renvoyé des données de topologie non prises en charge.",error_provider:"Impossible de charger les données de topologie.",remote_count:"+{n} dans d’autres espaces",route_device_not_on_plan:"appareil absent du plan",route_coordinator_not_on_plan:"coordinateur absent du plan",route_other_space:"autre espace"}};function r(e,n){const r=i[e]?.[n]??t[n];return"string"==typeof r&&r.trim().length>0}function o(n,r,o){return e(i[n]?.[r]??t[r]??r,o)}const s=3e5,a=2097152,d=6e3;function l(e){return null!==e&&"object"==typeof e?e:null}function u(e){if("string"!=typeof e&&"number"!=typeof e)return null;let n=String(e).trim().toLowerCase();return n=/^0x[0-9a-f]{16}$/.test(n)?n.slice(2):n.replace(/[:-]/g,""),/^[0-9a-f]{16}$/.test(n)?n:null}function c(e,n,t){return`${e}:${n}:${t}`}function p(e){const n=String(e||"").toLowerCase().replace(/[ _-]/g,"");return n.includes("coordinator")?"coordinator":n.includes("router")?"router":n.includes("enddevice")||"end"===n?"end":"unknown"}const h=["parent","child","sibling","none","previous_child"];function g(e){const n=l(e),t=function(e){const n=Number(e);return Number.isFinite(n)&&n>=0&&n<=255?Math.round(n):void 0}(n?.lqi??n?.linkquality??n?.link_quality),i=function(e){if("number"==typeof e)return h[e];if("string"!=typeof e)return;const n=e.trim().toLowerCase().replace(/[\s_-]+/g,"");return"previouschild"===n?"previous_child":n.slice(0,40)||void 0}(n?.relationship);return{...void 0===t?{}:{lqi:t},...i?{relationship:i}:{}}}function f(e,n){return Array.isArray(e)&&e.length<=n?e:null}function _(e){if("string"==typeof e)return e.length<=a;try{return JSON.stringify(e).length<=a}catch{return!1}}function m(e,n,t,i,r){if(t===i)return void n.push({code:"self_link",nodeKey:t});const o=t=d){t.push({code:"invalid_payload"});break}const n=l(e),i=u(n?.ieee??n?.ieee_address);if(!i){t.push({code:"invalid_payload",nodeKey:s});continue}const a=c("zha","zha",i);r.has(a)||r.set(a,{key:a,ieee:i,role:p(n?.device_type)}),m(o,t,s,a,e)}else null!=n?.neighbors&&t.push({code:"invalid_payload",nodeKey:s})}return{provider:"zha",instanceId:"zha",obtainedAt:n,freshness:"provider-cache",nodes:[...r.values()],links:[...o.values()],warnings:t}}function v(e,n){const t=l(e),i=u(t?.ieeeAddr??t?.ieee_address??t?.ieee??e);if(i)return i;for(const i of[t?.id,t?.networkAddress,t?.network_address,e])if(null!=i){const e=n.get(String(i));if(e)return e}return null}function y(e,t,i=Date.now()){const r=[],o=n(t)||"invalid",s=_(e)?function(e){let n=e;if("string"==typeof n){if(n.length>a)return null;try{n=JSON.parse(n)}catch{return null}}const t=l(n),i=l(t?.data);if(n=i?.value??t?.value??t?.data??n,"string"==typeof n){if(n.length>a)return null;try{n=JSON.parse(n)}catch{return null}}return n}(e):null,h=l(s),g=f(h?.nodes,1e3),b=f(h?.links,d);if(!g||!b)return{provider:"z2m",instanceId:o,obtainedAt:i,freshness:"fresh-scan",nodes:[],links:[],warnings:[{code:"invalid_payload"}]};const y=new Map,k=new Map;for(const e of g){const n=l(e),t=u(n?.ieeeAddr??n?.ieee_address??n?.ieee);if(!t){r.push({code:"invalid_payload"});continue}const i=c("z2m",o,t);y.set(i,{key:i,ieee:t,role:p(n?.type??n?.device_type),..."boolean"==typeof n?.failed?{available:!n.failed}:{}});for(const e of[n?.id,n?.networkAddress,n?.network_address])null!=e&&k.set(String(e),t)}const w=new Map;for(const e of b){const n=l(e),t=u(n?.sourceIeeeAddr)??v(n?.source,k),i=u(n?.targetIeeeAddr)??v(n?.target,k);if(!t||!i){r.push({code:"invalid_payload"});continue}const s=c("z2m",o,t),a=c("z2m",o,i);y.has(s)||y.set(s,{key:s,ieee:t,role:"unknown"}),y.has(a)||y.set(a,{key:a,ieee:i,role:"unknown"}),m(w,r,s,a,e)}return{provider:"z2m",instanceId:o,obtainedAt:i,freshness:"fresh-scan",nodes:[...y.values()],links:[...w.values()],warnings:r}}function k(e){if("string"!=typeof e)return null;const n=u(e);if(n)return n;const t=e.toLowerCase().match(/^zigbee2mqtt(?:_bridge)?_(.+)$/);return t?u(t[1]):null}function w(e,n){if(e.deviceId&&n.devices[e.deviceId])return[e.deviceId];const t=new Set;for(const[i,r]of Object.entries(n.devices)){const n=l(r);(Array.isArray(n?.identifiers)?n.identifiers:[]).some(n=>Array.isArray(n)&&k(n[1])===e.ieee)&&t.add(i)}if(t.size)return[...t];for(const i of Object.values(n.entities)){const n=l(i);"string"==typeof n?.device_id&&"string"==typeof n.unique_id&&(k(n.unique_id)===e.ieee&&t.add(n.device_id))}return[...t]}function z(e){return!e.hidden&&!e.virtual&&"ha_disabled"!==e.bindingStatus?.kind&&"orphaned"!==e.bindingStatus?.kind&&"unverified"!==e.bindingStatus?.kind}function A(e){const n=new Map,t=new Map,i=e.nodes.filter(e=>"coordinator"===e.role).map(e=>e.key).sort();if(1!==i.length)return{distances:n,parents:t};const r=i[0],o=function(e){const n=new Set(e.nodes.map(e=>e.key)),t=new Map;for(const e of[...n].sort())t.set(e,[]);for(const i of[...e.links].sort((e,n)=>`${e.a}\0${e.b}`.localeCompare(`${n.a}\0${n.b}`)))n.has(i.a)&&n.has(i.b)&&(t.get(i.a).push({neighborKey:i.b,observation:i.aToB}),t.get(i.b).push({neighborKey:i.a,observation:i.bToA}));for(const e of t.values())e.sort((e,n)=>e.neighborKey.localeCompare(n.neighborKey));return t}(e);if(!o.has(r))return{distances:n,parents:t};n.set(r,0);const s=[r];for(let e=0;en.get(e)===i-1).sort((e,n)=>{const t="parent"===e.observation?.relationship?1:0,i="parent"===n.observation?.relationship?1:0;if(t!==i)return i-t;const r=e.observation?.lqi??-1;return(n.observation?.lqi??-1)-r||e.neighborKey.localeCompare(n.neighborKey)});r[0]&&t.set(e,r[0].neighborKey)}return{coordinatorKey:r,distances:n,parents:t}}function Z(e,n,t){const i=new Map,r=[];for(const o of e.nodes){if(!1===o.available){r.push({code:"provider_scan_failure",nodeKey:o.key});continue}const e=w(o,t);if(1!==e.length){r.push({code:"unmatched_device",nodeKey:o.key});continue}const s=e[0];let a=n.filter(e=>z(e)&&"device"===e.bindingKind&&e.bindingRef===s);a.length||(a=n.filter(e=>z(e)&&"entity"===e.bindingKind&&!!e.bindingRef&&t.entities[e.bindingRef]?.device_id===s)),1===a.length?i.set(o.key,{markerId:a[0].id,space:a[0].space}):r.push({code:a.length>1?"ambiguous_placement":"unmatched_device",nodeKey:o.key})}return{placements:i,warnings:r}}function T(e,n,t){return e.map(e=>({topology:e,placements:Z(e,n,t).placements,routes:A(e)}))}function q(e,n,t){const i=new Map,r=new Set,o=new Map;let s=0;for(const{topology:a,placements:d,routes:l}of e){const e=new Set([...d].filter(([,e])=>e.markerId===t&&e.space===n).map(([e])=>e));if(e.size){for(const t of e){const e=l.parents.get(t);if(!e)continue;const i=d.get(e);if(i?.space===n)continue;let r;r=i?{kind:"remote-space",spaceId:i.space}:"coordinator"===a.nodes.find(n=>n.key===e)?.role?{kind:"unplaced-coordinator"}:{kind:"unplaced-device"};const s="remote-space"===r.kind?`${r.kind}:${r.spaceId}`:r.kind;o.set(s,r)}for(const o of a.links){const a=e.has(o.a),u=e.has(o.b);if(!a&&!u)continue;const c=a?o.a:o.b,p=a?o.b:o.a,h=d.get(p);if(!h||h.markerId===t){s++;continue}const g=l.parents.get(c)===p;if(h.space!==n){g||r.add(h.markerId);continue}const f=a?o.aToB:o.bToA,_=g?"toward-neighbor":l.parents.get(p)===c?"toward-origin":void 0,m=i.get(h.markerId);m?(void 0===m.line.lqi&&void 0!==f?.lqi&&(m.line.lqi=f.lqi),_&&m.directions.add(_)):i.set(h.markerId,{line:{neighborMarkerId:h.markerId,lqi:f?.lqi},directions:new Set(_?[_]:[])})}}}return{lines:[...i.values()].map(({line:e,directions:n})=>1===n.size?{...e,routeDirection:[...n][0]}:e),remoteCount:r.size,omittedCount:s,parentTargets:[...o.values()]}}export{s as T,T as a,y as b,r as h,Z as m,b as n,q as r,o as t}; +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{s as e,F as n}from"./houseplan-card-Bhpi71t0.js";var t={title:"Zigbee links",toggle:"Show Zigbee links when hovering over a device",hint:"Shows observed direct neighbours only. Nothing is fetched while you hover.",help:"Shows which Zigbee devices each device talks to directly. Line colour is link quality (LQI) on the same scale as the device's LQI reading: red at 40 and below, green at 180 and above. A dashed line means quality was not reported. An arrow points to the next device on the way to the coordinator: one arrow leads out, incoming arrows are the devices that route through this one. A line without an arrow is a spare neighbour. This is the route tree House Plan builds, not the path a packet takes right now: a label at the end of an arrow means its target is not on this plan, and no arrow at all means the route is unknown. Data comes from the last load and goes stale; links are shown with a mouse only.",help_aria:"Help: Zigbee links",admin_only:"Topology data is available to Home Assistant administrators only.",save_first:"Save this setting before loading topology data.",zha:"ZHA",zha_read:"Read ZHA data",zha_hint:"Reads ZHA's cached topology; it does not start a radio scan.",z2m:"Zigbee2MQTT",z2m_topics:"Base topics (one per line)",z2m_update:"Update map",z2m_warning:"A network-map scan can take 10 seconds to 2 minutes and may temporarily reduce Zigbee responsiveness.",status_idle:"Data not loaded",status_loading:"Loading…",status_ready:"Received {time}",status_stale:"Received {time} · stale",status_partial:"Received {time} · some nodes were omitted",status_no_links:"Received {time} · no observed links found",error_permission:"Administrator permission is required.",error_unsupported:"This provider or Home Assistant API is unavailable.",error_timeout:"The provider did not respond in time.",error_invalid_topic:"Check the Zigbee2MQTT base topic.",error_invalid_payload:"The provider returned unsupported topology data.",error_provider:"Topology data could not be loaded.",remote_count:"+{n} in other spaces",route_device_not_on_plan:"device is not on the plan",route_coordinator_not_on_plan:"coordinator is not on the plan",route_other_space:"another space"};const i={en:t,ru:{title:"Связи Zigbee",toggle:"Показывать связи Zigbee при наведении на устройство",hint:"Показываются только наблюдаемые прямые соседи. Наведение ничего не запрашивает.",help:"Показывает, с какими устройствами Zigbee каждое связано напрямую. Цвет линии — качество связи (LQI) по той же шкале, что у показателя LQI устройства: красный при 40 и ниже, зелёный при 180 и выше. Пунктир — качество не сообщено. Стрелка ведёт к следующему устройству по пути к координатору: исходящая одна, входящие — те, кто ходит через это устройство. Линия без стрелки — запасной сосед. Это дерево маршрутов, которое строит House Plan, а не путь пакета в эту секунду: подпись на конце стрелки значит, что цель не на этом плане, а отсутствие стрелки — что путь неизвестен. Данные из последней загрузки и устаревают, связи видны только при работе мышью.",help_aria:"Справка: связи Zigbee",admin_only:"Данные топологии доступны только администраторам Home Assistant.",save_first:"Сохраните настройку перед загрузкой данных топологии.",zha:"ZHA",zha_read:"Прочитать данные ZHA",zha_hint:"Читает сохранённую топологию ZHA и не запускает радио-сканирование.",z2m:"Zigbee2MQTT",z2m_topics:"Базовые топики (по одному в строке)",z2m_update:"Обновить карту",z2m_warning:"Сканирование карты сети занимает от 10 секунд до 2 минут и временно может снизить отзывчивость Zigbee.",status_idle:"Данные не загружены",status_loading:"Загрузка…",status_ready:"Получено: {time}",status_stale:"Получено: {time} · данные устарели",status_partial:"Получено: {time} · часть узлов не показана",status_no_links:"Получено: {time} · наблюдаемые связи не найдены",error_permission:"Нужны права администратора.",error_unsupported:"Провайдер или API Home Assistant недоступен.",error_timeout:"Провайдер не ответил вовремя.",error_invalid_topic:"Проверьте базовый топик Zigbee2MQTT.",error_invalid_payload:"Провайдер вернул неподдерживаемые данные топологии.",error_provider:"Не удалось загрузить данные топологии.",remote_count:"+{n} в других пространствах",route_device_not_on_plan:"устройства нет на плане",route_coordinator_not_on_plan:"координатора нет на плане",route_other_space:"другое пространство"},de:{title:"Zigbee-Verbindungen",toggle:"Zigbee-Verbindungen beim Darüberfahren über ein Gerät anzeigen",hint:"Es werden nur beobachtete direkte Nachbarn angezeigt. Beim Darüberfahren werden keine Daten abgerufen.",help:"Zeigt, mit welchen Zigbee-Geräten jedes Gerät direkt verbunden ist. Die Linienfarbe ist die Verbindungsqualität (LQI) auf derselben Skala wie der LQI-Wert des Geräts: rot bei 40 und darunter, grün bei 180 und darüber. Eine gestrichelte Linie bedeutet, dass die Qualität nicht gemeldet wurde. Ein Pfeil zeigt auf das nächste Gerät auf dem Weg zum Koordinator: ein Pfeil führt hinaus, eingehende Pfeile sind die Geräte, die über dieses Gerät routen. Eine Linie ohne Pfeil ist ein Ersatznachbar. Das ist der Routenbaum, den House Plan bildet, nicht der Weg eines Pakets in diesem Moment: eine Beschriftung am Pfeilende bedeutet, dass das Ziel nicht auf diesem Plan liegt, und ein fehlender Pfeil, dass die Route unbekannt ist. Die Daten stammen aus dem letzten Laden und veralten; Verbindungen sind nur mit der Maus sichtbar.",help_aria:"Hilfe: Zigbee-Verbindungen",admin_only:"Topologiedaten sind nur für Home-Assistant-Administratoren verfügbar.",save_first:"Speichere diese Einstellung, bevor Topologiedaten geladen werden.",zha:"ZHA",zha_read:"ZHA-Daten lesen",zha_hint:"Liest den ZHA-Topologiecache; es wird kein Funkscan gestartet.",z2m:"Zigbee2MQTT",z2m_topics:"Basistopics (eines pro Zeile)",z2m_update:"Karte aktualisieren",z2m_warning:"Ein Netzwerkscan kann 10 Sekunden bis 2 Minuten dauern und Zigbee vorübergehend verlangsamen.",status_idle:"Daten nicht geladen",status_loading:"Wird geladen…",status_ready:"Empfangen: {time}",status_stale:"Empfangen: {time} · veraltet",status_partial:"Empfangen: {time} · einige Knoten fehlen",status_no_links:"Empfangen: {time} · keine beobachteten Verbindungen gefunden",error_permission:"Administratorrechte sind erforderlich.",error_unsupported:"Dieser Anbieter oder die Home-Assistant-API ist nicht verfügbar.",error_timeout:"Der Anbieter hat nicht rechtzeitig geantwortet.",error_invalid_topic:"Prüfe das Zigbee2MQTT-Basistopic.",error_invalid_payload:"Der Anbieter hat nicht unterstützte Topologiedaten geliefert.",error_provider:"Topologiedaten konnten nicht geladen werden.",remote_count:"+{n} in anderen Bereichen",route_device_not_on_plan:"Gerät ist nicht im Plan",route_coordinator_not_on_plan:"Koordinator ist nicht im Plan",route_other_space:"anderer Bereich"},fr:{title:"Liens Zigbee",toggle:"Afficher les liens Zigbee au survol d’un appareil",hint:"Seuls les voisins directs observés sont affichés. Le survol ne lance aucune requête.",help:"Montre avec quels appareils Zigbee chaque appareil communique directement. La couleur de la ligne est la qualité du lien (LQI) sur la même échelle que l'indicateur LQI de l'appareil : rouge à 40 et en dessous, vert à 180 et au-dessus. Une ligne pointillée signifie que la qualité n'a pas été communiquée. Une flèche pointe vers l'appareil suivant sur le chemin du coordinateur : une flèche part, les flèches entrantes sont les appareils qui passent par celui-ci. Une ligne sans flèche est un voisin de secours. C'est l'arbre de routes que construit House Plan, pas le trajet d'un paquet à cet instant : une étiquette au bout d'une flèche signifie que sa cible n'est pas sur ce plan, et l'absence de flèche que la route est inconnue. Les données proviennent du dernier chargement et vieillissent ; les liens ne sont visibles qu'à la souris.",help_aria:"Aide : liens Zigbee",admin_only:"Les données de topologie sont réservées aux administrateurs Home Assistant.",save_first:"Enregistrez ce réglage avant de charger les données de topologie.",zha:"ZHA",zha_read:"Lire les données ZHA",zha_hint:"Lit la topologie en cache de ZHA sans lancer d’analyse radio.",z2m:"Zigbee2MQTT",z2m_topics:"Topics de base (un par ligne)",z2m_update:"Actualiser la carte",z2m_warning:"L’analyse de la carte réseau peut durer de 10 secondes à 2 minutes et réduire temporairement la réactivité de Zigbee.",status_idle:"Données non chargées",status_loading:"Chargement…",status_ready:"Reçu : {time}",status_stale:"Reçu : {time} · obsolète",status_partial:"Reçu : {time} · certains nœuds sont omis",status_no_links:"Reçu : {time} · aucun lien observé trouvé",error_permission:"Les droits administrateur sont requis.",error_unsupported:"Ce fournisseur ou l’API Home Assistant n’est pas disponible.",error_timeout:"Le fournisseur n’a pas répondu à temps.",error_invalid_topic:"Vérifiez le topic de base Zigbee2MQTT.",error_invalid_payload:"Le fournisseur a renvoyé des données de topologie non prises en charge.",error_provider:"Impossible de charger les données de topologie.",remote_count:"+{n} dans d’autres espaces",route_device_not_on_plan:"appareil absent du plan",route_coordinator_not_on_plan:"coordinateur absent du plan",route_other_space:"autre espace"}};function r(e,n){const r=i[e]?.[n]??t[n];return"string"==typeof r&&r.trim().length>0}function o(n,r,o){return e(i[n]?.[r]??t[r]??r,o)}const s=3e5,a=2097152,d=6e3;function l(e){return null!==e&&"object"==typeof e?e:null}function u(e){if("string"!=typeof e&&"number"!=typeof e)return null;let n=String(e).trim().toLowerCase();return n=/^0x[0-9a-f]{16}$/.test(n)?n.slice(2):n.replace(/[:-]/g,""),/^[0-9a-f]{16}$/.test(n)?n:null}function c(e,n,t){return`${e}:${n}:${t}`}function p(e){const n=String(e||"").toLowerCase().replace(/[ _-]/g,"");return n.includes("coordinator")?"coordinator":n.includes("router")?"router":n.includes("enddevice")||"end"===n?"end":"unknown"}const h=["parent","child","sibling","none","previous_child"];function g(e){const n=l(e),t=function(e){const n=Number(e);return Number.isFinite(n)&&n>=0&&n<=255?Math.round(n):void 0}(n?.lqi??n?.linkquality??n?.link_quality),i=function(e){if("number"==typeof e)return h[e];if("string"!=typeof e)return;const n=e.trim().toLowerCase().replace(/[\s_-]+/g,"");return"previouschild"===n?"previous_child":n.slice(0,40)||void 0}(n?.relationship);return{...void 0===t?{}:{lqi:t},...i?{relationship:i}:{}}}function f(e,n){return Array.isArray(e)&&e.length<=n?e:null}function _(e){if("string"==typeof e)return e.length<=a;try{return JSON.stringify(e).length<=a}catch{return!1}}function b(e,n,t,i,r){if(t===i)return void n.push({code:"self_link",nodeKey:t});const o=t=d){t.push({code:"invalid_payload"});break}const n=l(e),i=u(n?.ieee??n?.ieee_address);if(!i){t.push({code:"invalid_payload",nodeKey:s});continue}const a=c("zha","zha",i);r.has(a)||r.set(a,{key:a,ieee:i,role:p(n?.device_type)}),b(o,t,s,a,e)}else null!=n?.neighbors&&t.push({code:"invalid_payload",nodeKey:s})}return{provider:"zha",instanceId:"zha",obtainedAt:n,freshness:"provider-cache",nodes:[...r.values()],links:[...o.values()],warnings:t}}function v(e,n){const t=l(e),i=u(t?.ieeeAddr??t?.ieee_address??t?.ieee??e);if(i)return i;for(const i of[t?.id,t?.networkAddress,t?.network_address,e])if(null!=i){const e=n.get(String(i));if(e)return e}return null}function y(e,t,i=Date.now()){const r=[],o=n(t)||"invalid",s=_(e)?function(e){let n=e;if("string"==typeof n){if(n.length>a)return null;try{n=JSON.parse(n)}catch{return null}}const t=l(n),i=l(t?.data);if(n=i?.value??t?.value??t?.data??n,"string"==typeof n){if(n.length>a)return null;try{n=JSON.parse(n)}catch{return null}}return n}(e):null,h=l(s),g=f(h?.nodes,1e3),m=f(h?.links,d);if(!g||!m)return{provider:"z2m",instanceId:o,obtainedAt:i,freshness:"fresh-scan",nodes:[],links:[],warnings:[{code:"invalid_payload"}]};const y=new Map,k=new Map;for(const e of g){const n=l(e),t=u(n?.ieeeAddr??n?.ieee_address??n?.ieee);if(!t){r.push({code:"invalid_payload"});continue}const i=c("z2m",o,t);y.set(i,{key:i,ieee:t,role:p(n?.type??n?.device_type),..."boolean"==typeof n?.failed?{available:!n.failed}:{}});for(const e of[n?.id,n?.networkAddress,n?.network_address])null!=e&&k.set(String(e),t)}const w=new Map;for(const e of m){const n=l(e),t=u(n?.sourceIeeeAddr)??v(n?.source,k),i=u(n?.targetIeeeAddr)??v(n?.target,k);if(!t||!i){r.push({code:"invalid_payload"});continue}const s=c("z2m",o,t),a=c("z2m",o,i);y.has(s)||y.set(s,{key:s,ieee:t,role:"unknown"}),y.has(a)||y.set(a,{key:a,ieee:i,role:"unknown"}),b(w,r,s,a,e)}return{provider:"z2m",instanceId:o,obtainedAt:i,freshness:"fresh-scan",nodes:[...y.values()],links:[...w.values()],warnings:r}}function k(e){if("string"!=typeof e)return null;const n=u(e);if(n)return n;const t=e.toLowerCase().match(/^zigbee2mqtt(?:_bridge)?_(.+)$/);return t?u(t[1]):null}function w(e,n){if(e.deviceId&&n.devices[e.deviceId])return[e.deviceId];const t=new Set;for(const[i,r]of Object.entries(n.devices)){const n=l(r);(Array.isArray(n?.identifiers)?n.identifiers:[]).some(n=>Array.isArray(n)&&k(n[1])===e.ieee)&&t.add(i)}if(t.size)return[...t];for(const i of Object.values(n.entities)){const n=l(i);"string"==typeof n?.device_id&&"string"==typeof n.unique_id&&(k(n.unique_id)===e.ieee&&t.add(n.device_id))}return[...t]}function z(e){return!e.hidden&&!e.virtual&&"ha_disabled"!==e.bindingStatus?.kind&&"orphaned"!==e.bindingStatus?.kind&&"unverified"!==e.bindingStatus?.kind}function A(e){const n=new Map,t=new Map,i=e.nodes.filter(e=>"coordinator"===e.role).map(e=>e.key).sort();if(1!==i.length)return{distances:n,parents:t};const r=i[0],o=function(e){const n=new Set(e.nodes.map(e=>e.key)),t=new Map;for(const e of[...n].sort())t.set(e,[]);for(const i of[...e.links].sort((e,n)=>`${e.a}\0${e.b}`.localeCompare(`${n.a}\0${n.b}`)))n.has(i.a)&&n.has(i.b)&&(t.get(i.a).push({neighborKey:i.b,observation:i.aToB}),t.get(i.b).push({neighborKey:i.a,observation:i.bToA}));for(const e of t.values())e.sort((e,n)=>e.neighborKey.localeCompare(n.neighborKey));return t}(e);if(!o.has(r))return{distances:n,parents:t};n.set(r,0);const s=[r];for(let e=0;en.get(e)===i-1).sort((e,n)=>{const t="parent"===e.observation?.relationship?1:0,i="parent"===n.observation?.relationship?1:0;if(t!==i)return i-t;const r=e.observation?.lqi??-1;return(n.observation?.lqi??-1)-r||e.neighborKey.localeCompare(n.neighborKey)});r[0]&&t.set(e,r[0].neighborKey)}return{coordinatorKey:r,distances:n,parents:t}}function Z(e,n,t){const i=new Map,r=[];for(const o of e.nodes){if(!1===o.available){r.push({code:"provider_scan_failure",nodeKey:o.key});continue}const e=w(o,t);if(1!==e.length){r.push({code:"unmatched_device",nodeKey:o.key});continue}const s=e[0];let a=n.filter(e=>z(e)&&"device"===e.bindingKind&&e.bindingRef===s);a.length||(a=n.filter(e=>z(e)&&"entity"===e.bindingKind&&!!e.bindingRef&&t.entities[e.bindingRef]?.device_id===s)),1===a.length?i.set(o.key,{markerId:a[0].id,space:a[0].space}):r.push({code:a.length>1?"ambiguous_placement":"unmatched_device",nodeKey:o.key})}return{placements:i,warnings:r}}function T(e,n,t){return e.map(e=>({topology:e,placements:Z(e,n,t).placements,routes:A(e)}))}function q(e,n,t){const i=new Map,r=new Set,o=new Map;let s=0;for(const{topology:a,placements:d,routes:l}of e){const e=new Set([...d].filter(([,e])=>e.markerId===t&&e.space===n).map(([e])=>e));if(e.size){for(const t of e){const e=l.parents.get(t);if(!e)continue;const i=d.get(e);if(i?.space===n)continue;let r;r=i?{kind:"remote-space",spaceId:i.space}:"coordinator"===a.nodes.find(n=>n.key===e)?.role?{kind:"unplaced-coordinator"}:{kind:"unplaced-device"};const s="remote-space"===r.kind?`${r.kind}:${r.spaceId}`:r.kind;o.set(s,r)}for(const o of a.links){const a=e.has(o.a),u=e.has(o.b);if(!a&&!u)continue;const c=a?o.a:o.b,p=a?o.b:o.a,h=d.get(p);if(!h||h.markerId===t){s++;continue}const g=l.parents.get(c)===p;if(h.space!==n){g||r.add(h.markerId);continue}const f=a?o.aToB:o.bToA,_=g?"toward-neighbor":l.parents.get(p)===c?"toward-origin":void 0,b=i.get(h.markerId);b?(void 0===b.line.lqi&&void 0!==f?.lqi&&(b.line.lqi=f.lqi),_&&b.directions.add(_)):i.set(h.markerId,{line:{neighborMarkerId:h.markerId,lqi:f?.lqi},directions:new Set(_?[_]:[])})}}}return{lines:[...i.values()].map(({line:e,directions:n})=>1===n.size?{...e,routeDirection:[...n][0]}:e),remoteCount:r.size,omittedCount:s,parentTargets:[...o.values()]}}export{s as T,T as a,y as b,r as h,Z as m,m as n,q as r,o as t}; diff --git a/dist/houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js b/dist/houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js similarity index 77% rename from dist/houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js rename to dist/houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js index 53ab45ac..52f87da2 100644 --- a/dist/houseplan-assets/zigbee-topology-runtime-Jy73PIeo.js +++ b/dist/houseplan-assets/zigbee-topology-runtime-C4ZtGWbD.js @@ -1 +1 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";import{n as t,b as n}from"./zigbee-topology-BUFPOnoy.js";import{F as e}from"./houseplan-card-CODdCIWj.js";const o=new WeakMap;function i(t){const n=function(t){const n=t?.connection||t;return!n||"object"!=typeof n&&"function"!=typeof n?null:n}(t);if(!n)return null;let e=o.get(n);return e||(e={revision:0,topologies:[],states:{},listeners:new Set,inflight:new Map},o.set(n,e)),e}function r(t,n,e){t.states={...t.states,[n]:e},function(t){t.revision++;for(const n of t.listeners)n()}(t)}function s(t){const n=t?.code;if("permission"===n||"unsupported"===n||"timeout"===n||"invalid_topic"===n||"invalid_payload"===n)return n;const e=String(t?.message||"").toLowerCase();return e.includes("unauthor")||e.includes("permission")?"permission":e.includes("unknown_command")||e.includes("not found")?"unsupported":"provider"}function a(t){return Object.assign(new Error(t),{code:t})}function c(t,n,e){const o=t.inflight.get(n);if(o)return o;r(t,n,{phase:"loading"});const i=e().then(n=>{if(!n.nodes.length&&n.warnings.some(t=>"invalid_payload"===t.code))throw a("invalid_payload");!function(t,n){t.topologies=[...t.topologies.filter(t=>!(t.provider===n.provider&&t.instanceId===n.instanceId)),n],r(t,"zha"===n.provider?"zha":`z2m:${n.instanceId}`,{phase:"ready",obtainedAt:n.obtainedAt,partial:n.warnings.length>0})}(t,n)}).catch(e=>{r(t,n,{phase:"error",error:s(e)})}).finally(()=>t.inflight.delete(n));return t.inflight.set(n,i),i}function l(t){const n=i(t);return n?{revision:n.revision,topologies:n.topologies,states:n.states}:{revision:0,topologies:[],states:{}}}function u(t,n){const e=i(t);return e?(e.listeners.add(n),()=>e.listeners.delete(n)):()=>{}}function p(t){if(!0!==t?.user?.is_admin)throw a("permission")}function f(n){const e=i(n);return e?c(e,"zha",async()=>{if(p(n),"function"!=typeof n?.callWS)throw a("unsupported");return t(await n.callWS({type:"zha/devices"}))}):Promise.resolve()}function d(t){return null!==t&&"object"==typeof t?t:null}function h(t){const n=d(t),e=n?.payload??t;if("string"!=typeof e)return e;try{return JSON.parse(e)}catch{return null}}async function m(t,n){let e;try{return await Promise.race([t,new Promise((t,o)=>{e=globalThis.setTimeout(()=>o(a("timeout")),Math.max(1,n))})])}finally{void 0!==e&&globalThis.clearTimeout(e)}}function g(t,o,r=15e4){const s=i(t);if(!s)return Promise.resolve();const l=e(o);return c(s,`z2m:${l||String(o)}`,async()=>{if(p(t),!l)throw a("invalid_topic");const e=t.connection,o=e?.subscribeMessage;if("function"!=typeof o||"function"!=typeof t?.callService)throw a("unsupported");const i=function(){const t=globalThis.crypto;return"function"==typeof t?.randomUUID?`houseplan-${t.randomUUID()}`:`houseplan-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}(),s=Date.now()+Math.max(1,r);let c=!1,u=null,f=null,g=null;const y=new Promise(t=>{u=t}),w=new Promise((t,n)=>{f=t,g=n}),b=[];try{const r=await o.call(e,t=>{!0===d(t)?.retain&&h(t)&&u?.()},{type:"mqtt/subscribe",topic:`${l}/bridge/info`});"function"==typeof r&&b.push(r);const p=await o.call(e,t=>{if(!0===d(t)?.retain)return;const n=h(t);null!==n?n&&function(t){const n=d(t),e=n?.transaction??d(n?.data)?.transaction;return"string"==typeof e||"number"==typeof e?String(e):null}(n)===i&&f?.(n):c&&g?.(a("invalid_payload"))},{type:"mqtt/subscribe",topic:`${l}/bridge/response/networkmap`});"function"==typeof p&&b.push(p),await m(y,Math.min(4e3,Math.max(1,s-Date.now()))),c=!0,await t.callService("mqtt","publish",{topic:`${l}/bridge/request/networkmap`,payload:JSON.stringify({type:"raw",routes:!1,transaction:i}),qos:0,retain:!1});const v=await m(w,s-Date.now()),_=d(v)?.status;if(_&&"ok"!==_)throw a("provider");return n(v,l)}finally{for(const t of b)try{t()}catch{}}})}export{f as readZhaTopology,g as refreshZ2mTopology,u as subscribeZigbeeTopology,l as zigbeeTopologyRuntimeSnapshot}; +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";import{n as t,b as n}from"./zigbee-topology-B-C5QCCD.js";import{F as e}from"./houseplan-card-Bhpi71t0.js";const o=new WeakMap;function i(t){const n=function(t){const n=t?.connection||t;return!n||"object"!=typeof n&&"function"!=typeof n?null:n}(t);if(!n)return null;let e=o.get(n);return e||(e={revision:0,topologies:[],states:{},listeners:new Set,inflight:new Map},o.set(n,e)),e}function r(t,n,e){t.states={...t.states,[n]:e},function(t){t.revision++;for(const n of t.listeners)n()}(t)}function s(t){const n=t?.code;if("permission"===n||"unsupported"===n||"timeout"===n||"invalid_topic"===n||"invalid_payload"===n)return n;const e=String(t?.message||"").toLowerCase();return e.includes("unauthor")||e.includes("permission")?"permission":e.includes("unknown_command")||e.includes("not found")?"unsupported":"provider"}function a(t){return Object.assign(new Error(t),{code:t})}function c(t,n,e){const o=t.inflight.get(n);if(o)return o;r(t,n,{phase:"loading"});const i=e().then(n=>{if(!n.nodes.length&&n.warnings.some(t=>"invalid_payload"===t.code))throw a("invalid_payload");!function(t,n){t.topologies=[...t.topologies.filter(t=>!(t.provider===n.provider&&t.instanceId===n.instanceId)),n],r(t,"zha"===n.provider?"zha":`z2m:${n.instanceId}`,{phase:"ready",obtainedAt:n.obtainedAt,partial:n.warnings.length>0})}(t,n)}).catch(e=>{r(t,n,{phase:"error",error:s(e)})}).finally(()=>t.inflight.delete(n));return t.inflight.set(n,i),i}function l(t){const n=i(t);return n?{revision:n.revision,topologies:n.topologies,states:n.states}:{revision:0,topologies:[],states:{}}}function u(t,n){const e=i(t);return e?(e.listeners.add(n),()=>e.listeners.delete(n)):()=>{}}function f(t){if(!0!==t?.user?.is_admin)throw a("permission")}function p(n){const e=i(n);return e?c(e,"zha",async()=>{if(f(n),"function"!=typeof n?.callWS)throw a("unsupported");return t(await n.callWS({type:"zha/devices"}))}):Promise.resolve()}function d(t){return null!==t&&"object"==typeof t?t:null}function h(t){const n=d(t),e=n?.payload??t;if("string"!=typeof e)return e;try{return JSON.parse(e)}catch{return null}}async function m(t,n){let e;try{return await Promise.race([t,new Promise((t,o)=>{e=globalThis.setTimeout(()=>o(a("timeout")),Math.max(1,n))})])}finally{void 0!==e&&globalThis.clearTimeout(e)}}function g(t,o,r=15e4){const s=i(t);if(!s)return Promise.resolve();const l=e(o);return c(s,`z2m:${l||String(o)}`,async()=>{if(f(t),!l)throw a("invalid_topic");const e=t.connection,o=e?.subscribeMessage;if("function"!=typeof o||"function"!=typeof t?.callService)throw a("unsupported");const i=function(){const t=globalThis.crypto;return"function"==typeof t?.randomUUID?`houseplan-${t.randomUUID()}`:`houseplan-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}(),s=Date.now()+Math.max(1,r);let c=!1,u=null,p=null,g=null;const y=new Promise(t=>{u=t}),w=new Promise((t,n)=>{p=t,g=n}),b=[];try{const r=await o.call(e,t=>{!0===d(t)?.retain&&h(t)&&u?.()},{type:"mqtt/subscribe",topic:`${l}/bridge/info`});"function"==typeof r&&b.push(r);const f=await o.call(e,t=>{if(!0===d(t)?.retain)return;const n=h(t);null!==n?n&&function(t){const n=d(t),e=n?.transaction??d(n?.data)?.transaction;return"string"==typeof e||"number"==typeof e?String(e):null}(n)===i&&p?.(n):c&&g?.(a("invalid_payload"))},{type:"mqtt/subscribe",topic:`${l}/bridge/response/networkmap`});"function"==typeof f&&b.push(f),await m(y,Math.min(4e3,Math.max(1,s-Date.now()))),c=!0,await t.callService("mqtt","publish",{topic:`${l}/bridge/request/networkmap`,payload:JSON.stringify({type:"raw",routes:!1,transaction:i}),qos:0,retain:!1});const v=await m(w,s-Date.now()),_=d(v)?.status;if(_&&"ok"!==_)throw a("provider");return n(v,l)}finally{for(const t of b)try{t()}catch{}}})}export{p as readZhaTopology,g as refreshZ2mTopology,u as subscribeZigbeeTopology,l as zigbeeTopologyRuntimeSnapshot}; diff --git a/dist/houseplan-card.js b/dist/houseplan-card.js index 2b6b8632..e29c9329 100644 --- a/dist/houseplan-card.js +++ b/dist/houseplan-card.js @@ -1 +1 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="884182570484410d7ab1a7212b07de9f2b4e5683c0d859f4e9d3feaae9318c87";try{await import("./houseplan-assets/houseplan-card-CODdCIWj.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)} +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="0a474ab88fe7bfa881df73dfd02ba12a180d097f529b6740c83c620d3b78ca64";try{await import("./houseplan-assets/houseplan-card-Bhpi71t0.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)} diff --git a/scripts/bundle-budget.mjs b/scripts/bundle-budget.mjs index 27db3bd4..1b61b0a3 100644 --- a/scripts/bundle-budget.mjs +++ b/scripts/bundle-budget.mjs @@ -150,8 +150,15 @@ export const LOW_HEADROOM_WARNING_BYTES = 15_000; * измеренный initial факт до 299 501 Б и оставила лишь 499 Б сверху — меньше * обязательного шумового запаса. Новый центр оставляет 999 Б сверху и * 1 001 Б снизу; продуктовый граф при этом не расширялся. + * + * 2026-09-06, #474: потолок опущен 300 500 → 290 500 без изменения общего + * бюджета. Арт 44 дизайнерских символов мебели (`furniture-plan-art.generated`) + * вынесен в ленивый чанк `lazyFurnitureArtFiles` (10 252 Б gzip): его грузят + * только планы с мебелью, редактор отдаёт его рантайму синхронно. Измеренный + * initial факт 289 690 Б оставляет 810 Б сверху и 1 190 Б до нижней границы + * полосы; запас до стены 301 066 — 11 376 Б. */ -export const INITIAL_VIEW_GZIP_CEILING = 300_500; +export const INITIAL_VIEW_GZIP_CEILING = 290_500; export const INITIAL_VIEW_CEILING_BAND = 2_000; /** @@ -268,6 +275,14 @@ export function assertBundleBudget(manifest, budget = INITIAL_VIEW_GZIP_BUDGET) if (!manifest.lazyIsometricFiles?.length) { throw new Error('bundle has no lazy isometric graph'); } + // #474: designer furniture artwork is lazy; a static import anywhere in the + // View graph would pull ~10 KB gzip back into the initial graph silently. + if (!manifest.lazyFurnitureArtFiles?.length) { + throw new Error('bundle has no lazy furniture artwork graph'); + } + if (manifest.initialViewFiles.some((path) => manifest.lazyFurnitureArtFiles.includes(path))) { + throw new Error('initial View graph overlaps lazy furniture artwork graph'); + } if (manifest.initialViewFiles.some((path) => manifest.lazyEditorFiles.includes(path))) { throw new Error('initial View graph overlaps lazy editor graph'); } @@ -291,6 +306,7 @@ export function assertBundleBudget(manifest, budget = INITIAL_VIEW_GZIP_BUDGET) lazyEditorGzipBytes: manifest.lazyEditorGzipBytes, lazyLocaleGzipBytes: manifest.lazyLocaleGzipBytes, lazyIsometricGzipBytes: manifest.lazyIsometricGzipBytes, + lazyFurnitureArtGzipBytes: manifest.lazyFurnitureArtGzipBytes, }; } diff --git a/scripts/bundle-manifest.mjs b/scripts/bundle-manifest.mjs index b4114cf3..bbda9f2a 100644 --- a/scripts/bundle-manifest.mjs +++ b/scripts/bundle-manifest.mjs @@ -9,6 +9,7 @@ const ONBOARDING_RETRY_ASSET_TOKEN = '__HOUSEPLAN_ONBOARDING_RETRY_ASSET__'; const ISO_RETRY_ASSET_TOKEN = '__HOUSEPLAN_ISO_RETRY_ASSET__'; const DE_RETRY_ASSET_TOKEN = '__HOUSEPLAN_DE_RETRY_ASSET__'; const FR_RETRY_ASSET_TOKEN = '__HOUSEPLAN_FR_RETRY_ASSET__'; +const FURNITURE_ART_RETRY_ASSET_TOKEN = '__HOUSEPLAN_FURNITURE_ART_RETRY_ASSET__'; const sha256 = (value) => createHash('sha256').update(value).digest('hex'); @@ -39,7 +40,11 @@ export function buildBundleManifest(bundle, fingerprint) { ? 'editor' : modules.some((id) => id.endsWith('/src/iso-scene-render.ts')) ? 'isometric' - : undefined; + // #474: designer furniture artwork — its own lazy chunk, shared by + // the editor (static import) and the View runtime (dynamic). + : modules.some((id) => id.endsWith('/src/furniture-plan-art.generated.ts')) + ? 'furniture-art' + : undefined; return { path: chunk.fileName.replaceAll('\\', '/'), sha256: sha256(contents), @@ -71,6 +76,7 @@ export function buildBundleManifest(bundle, fingerprint) { && !localeRoots.includes(path) && !onboardingRoots.includes(path)); const isometricRoots = dynamicRoots.filter((path) => byPath.get(path)?._role === 'isometric' || path.includes('iso-scene-render-')); + const furnitureArtRoots = dynamicRoots.filter((path) => byPath.get(path)?._role === 'furniture-art'); const graphFrom = (roots) => { const graph = new Set(); for (const root of roots) { @@ -82,6 +88,7 @@ export function buildBundleManifest(bundle, fingerprint) { const lazyOnboarding = graphFrom(onboardingRoots); const lazyLocale = graphFrom(localeRoots); const lazyIsometric = graphFrom(isometricRoots); + const lazyFurnitureArt = graphFrom(furnitureArtRoots); const sum = (paths) => [...paths] .reduce((total, path) => total + (byPath.get(path)?.gzipBytes || 0), 0); return { @@ -100,6 +107,8 @@ export function buildBundleManifest(bundle, fingerprint) { lazyLocaleGzipBytes: sum(lazyLocale), lazyIsometricFiles: [...lazyIsometric].sort(), lazyIsometricGzipBytes: sum(lazyIsometric), + lazyFurnitureArtFiles: [...lazyFurnitureArt].sort(), + lazyFurnitureArtGzipBytes: sum(lazyFurnitureArt), files: files.map(({ _role, ...file }) => file), }; } @@ -153,11 +162,15 @@ export function editorRuntimeRetryUrlPlugin() { .some((id) => id.replaceAll('\\', '/').endsWith('/src/i18n/de.ts'))); const french = chunks.find((chunk) => Object.keys(chunk.modules) .some((id) => id.replaceAll('\\', '/').endsWith('/src/i18n/fr.ts'))); + const furnitureArt = chunks.find((chunk) => Object.keys(chunk.modules) + .some((id) => id.replaceAll('\\', '/').endsWith('/src/furniture-plan-art.generated.ts'))); if (!editor) throw new Error('editor runtime chunk was not emitted'); if (!onboarding) throw new Error('onboarding runtime chunk was not emitted'); if (!isometric) throw new Error('isometric runtime chunk was not emitted'); if (!german) throw new Error('German locale chunk was not emitted'); if (!french) throw new Error('French locale chunk was not emitted'); + if (!furnitureArt) throw new Error('furniture artwork chunk was not emitted'); + let furnitureArtReplacements = 0; let editorReplacements = 0; let onboardingReplacements = 0; let isometricReplacements = 0; @@ -194,11 +207,17 @@ export function editorRuntimeRetryUrlPlugin() { frenchReplacements += chunk.code.split(FR_RETRY_ASSET_TOKEN).length - 1; chunk.code = chunk.code.replaceAll(FR_RETRY_ASSET_TOKEN, asset); } + if (chunk.code.includes(FURNITURE_ART_RETRY_ASSET_TOKEN)) { + let asset = posix.relative(posix.dirname(chunk.fileName), furnitureArt.fileName); + if (!asset.startsWith('.')) asset = `./${asset}`; + furnitureArtReplacements += chunk.code.split(FURNITURE_ART_RETRY_ASSET_TOKEN).length - 1; + chunk.code = chunk.code.replaceAll(FURNITURE_ART_RETRY_ASSET_TOKEN, asset); + } } if (editorReplacements !== 1 || onboardingReplacements !== 1 || isometricReplacements !== 1 - || germanReplacements !== 1 || frenchReplacements !== 1) { + || germanReplacements !== 1 || frenchReplacements !== 1 || furnitureArtReplacements !== 1) { throw new Error('lazy retry URL placeholder counts are ' - + `${editorReplacements}/${onboardingReplacements}/${isometricReplacements}/${germanReplacements}/${frenchReplacements}, expected 1/1/1/1/1`); + + `${editorReplacements}/${onboardingReplacements}/${isometricReplacements}/${germanReplacements}/${frenchReplacements}/${furnitureArtReplacements}, expected 1/1/1/1/1/1`); } }, }; diff --git a/scripts/generate-furniture-assets.mjs b/scripts/generate-furniture-assets.mjs index d42aea92..152026c8 100644 --- a/scripts/generate-furniture-assets.mjs +++ b/scripts/generate-furniture-assets.mjs @@ -8,6 +8,9 @@ const PACK = path.join(ROOT, 'assets', 'furniture', 'houseplan-0.3.0'); // Deliberately not named *manifest.json: HACS rejects a repository that // contains any second file matching that suffix outside the integration. const MANIFEST = path.join(PACK, 'pack.json'); +// #474: каталог (id, группа, категория, размеры) — в стартовом графе, арт +// (SVG-пути, ~10 КБ gzip) — отдельный модуль, который View грузит лениво. +const CATALOG_OUT = path.join(ROOT, 'src', 'furniture-plan-catalog.generated.ts'); const PLAN_OUT = path.join(ROOT, 'src', 'furniture-plan-art.generated.ts'); const MENU_OUT = path.join(ROOT, 'src', 'furniture-menu-art.generated.ts'); const CHECK = process.argv.includes('--check'); @@ -146,11 +149,18 @@ function loadPack() { } const header = `/* Generated by scripts/generate-furniture-assets.mjs. DO NOT EDIT. */\n`; +function renderCatalog(symbols) { + const runtime = symbols.map(({ id, group, category, w, h }) => ({ id, group, category, w, h })); + return header + `export const GENERATED_FURNITURE_CATALOG = ${JSON.stringify(runtime)} as const;\n`; +} function renderPlan(symbols) { - const runtime = symbols.map(({ id, group, category, w, h, art }) => ({ - id, group, category, w, h, art, - })); - return header + `export const GENERATED_FURNITURE_PLAN = ${JSON.stringify(runtime)} as const;\n`; + const runtime = Object.fromEntries(symbols.map(({ id, art }) => [id, art])); + return header + + '// Lazy chunk (#474): imported dynamically by furniture-art-runtime.ts and\n' + + '// statically by the editor. The fingerprint token is replaced at build time\n' + + '// so a chunk from another build is rejected instead of half-applied.\n' + + `export const FURNITURE_ART_FINGERPRINT = '__HOUSEPLAN_SOURCE_FINGERPRINT__';\n` + + `export const GENERATED_FURNITURE_ART: Readonly> = ${JSON.stringify(runtime)};\n`; } function renderMenu(menu) { const runtime = menu.map(({ id, group, art }) => ({ id, group, art })); @@ -166,6 +176,7 @@ function output(file, content) { } const pack = loadPack(); +output(CATALOG_OUT, renderCatalog(pack.symbols)); output(PLAN_OUT, renderPlan(pack.symbols)); output(MENU_OUT, renderMenu(pack.menu)); console.log(`Furniture pack OK: ${pack.symbols.length} plan symbols, ${pack.menu.length} menu icons${CHECK ? ' (generated files current)' : ''}.`); diff --git a/scripts/mutation-gate.mjs b/scripts/mutation-gate.mjs index 33fe4cfa..df81fde9 100644 --- a/scripts/mutation-gate.mjs +++ b/scripts/mutation-gate.mjs @@ -1434,10 +1434,10 @@ const MUTANT_DEFINITIONS = [ + 'a German user on a stale tab silently reading English is the N7 hole (#354 К2)', patches: [{ file: 'src/houseplan-card.ts', - find: " this._languageFailureUnsub = subscribeLanguageLoadFailures(() => {\n" + find: " this._languageFailureUnsub = composeUnsub(subscribeLanguageLoadFailures(() => {\n" + " this._showToast(this._t('toast.locale_load_failed'));\n" - + ' });', - replace: ' this._languageFailureUnsub = undefined;', + + ' }), ', + replace: ' this._languageFailureUnsub = composeUnsub(', }], }, { @@ -6541,6 +6541,99 @@ const MUTANT_DEFINITIONS = [ replace: ' if (true', }], }, + // #474: designer furniture artwork is a lazy chunk. Each protective contract + // of the runtime and its integration gets one witness. + { + id: 'furniture-art-eager-import', + guard: 'npm run build && node scripts/bundle-budget.mjs', + because: 'a static import of the artwork anywhere in the View graph silently pulls ~10 KB gzip ' + + 'back into the initial graph — the exact debt #474 removes; the budget must see the chunk as lazy', + patches: [{ + file: 'src/furniture.ts', + find: "import { FURNITURE_ART_RUNTIME, type FurnitureArtHost } from './furniture-art-runtime';", + replace: "import { FURNITURE_ART_RUNTIME, type FurnitureArtHost } from './furniture-art-runtime';\n" + + "import './furniture-plan-art.generated'; // mutant: eager artwork", + }], + }, + { + id: 'furniture-art-fallback-never-settles', + guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs ' + + '&& node --test --test-name-pattern="settle into fallback" test/furniture-art-runtime.test.mjs', + because: 'fallback must be a SETTLED state: a runtime that stays pending after two failed attempts ' + + 'keeps the boot gate waiting and re-imports forever (#352–#355 class)', + patches: [{ + file: 'src/furniture-art-runtime.ts', + find: ' if (this._art) return;\n this._failed = true;', + replace: ' if (this._art) return;\n this._failed = false; // mutant: never settle', + }], + }, + { + id: 'furniture-art-no-retry-nonce', + guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs ' + + '&& node --test --test-name-pattern="first attempt failing and the second succeeding" test/furniture-art-runtime.test.mjs', + because: 'Chromium caches a failed module forever; the second attempt must be a different URL ' + + 'and must exist at all — a single attempt turns every transient failure into fallback', + patches: [{ + file: 'src/furniture-art-runtime.ts', + find: ' for (const attempt of [0, 1] as const) {\n try {\n const module = await this.options.load(attempt);', + replace: ' for (const attempt of [0] as const) {\n try {\n const module = await this.options.load(attempt);', + }], + }, + { + id: 'furniture-art-boot-gate-ignored', + guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs ' + + '&& node --test --test-name-pattern="boot gate waits only while pending" test/furniture-art-runtime.test.mjs', + because: 'the boot veil must hold while a plan with furniture waits for its artwork; a gate that ' + + 'never reports pending lets the first revealed frame miss every piece (#474 AC2)', + patches: [{ + file: 'src/furniture-art-runtime.ts', + find: " return runtime.state() === 'pending' && configNeedsFurnitureArt(config, isDesigner);", + replace: ' return false; // mutant: veil never waits for artwork', + }], + }, + { + id: 'furniture-placement-needs-art', + guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs ' + + '&& node --test --test-name-pattern="wall magnet places a designer piece" test/furniture-art-runtime.test.mjs', + because: 'the magnet needs the catalogue, not the artwork: checking the artwork refuses every ' + + 'designer placement while the chunk is pending (#474 AC6)', + patches: [{ + file: 'src/furniture-placement.ts', + find: ' if (!furnitureSymbol(symbol) || !(canvasW > 0) || !(canvasH > 0)', + replace: " if (!(furnitureSymbol(symbol) && (furnitureSymbol(symbol)?.g || FURNITURE_ART_RUNTIME.art(symbol))) || !(canvasW > 0) || !(canvasH > 0)", + }, { + file: 'src/furniture-placement.ts', + find: "import { clampFurnSize, cmToNorm, furnitureSymbol } from './furniture';", + replace: "import { clampFurnSize, cmToNorm, furnitureSymbol } from './furniture';\nimport { FURNITURE_ART_RUNTIME } from './furniture-art-runtime';", + }], + }, + { + id: 'furniture-art-fingerprint-unchecked', + guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs ' + + '&& node --test --test-name-pattern="foreign build fingerprint is terminal|adopt is synchronous, rejects" test/furniture-art-runtime.test.mjs', + because: 'artwork from another build must be rejected on both paths (load and adopt): a stale ' + + 'chunk half-applied to a newer card is the #353 failure mode', + patches: [{ + file: 'src/furniture-art-runtime.ts', + find: ' if (module.FURNITURE_ART_FINGERPRINT !== this.options.expectedFingerprint) {', + replace: ' if (false) { // mutant: any build will do', + }, { + file: 'src/furniture-art-runtime.ts', + find: ' if (fingerprint !== this.options.expectedFingerprint) {', + replace: ' if (false) { // mutant: any build will do', + }], + }, + { + id: 'furniture-art-editor-adopt-skipped', + guard: 'npm run bundle:sync && node demo/smoke_furniture.mjs', + because: 'the editor imports the artwork statically and must hand it over synchronously; without ' + + 'adopt the palette previews and the placement ghost render empty on a plan without furniture (#474 r1)', + patches: [{ + file: 'src/houseplan-editor-runtime.ts', + find: 'FURNITURE_ART_RUNTIME.adopt(GENERATED_FURNITURE_ART, FURNITURE_ART_FINGERPRINT);', + replace: 'void [FURNITURE_ART_RUNTIME, GENERATED_FURNITURE_ART, FURNITURE_ART_FINGERPRINT]; // mutant: no handover', + }], + }, { id: 'iso-aabb-rejects-touching-wall', guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs ' diff --git a/src/furniture-art-runtime.ts b/src/furniture-art-runtime.ts new file mode 100755 index 00000000..a3003307 --- /dev/null +++ b/src/furniture-art-runtime.ts @@ -0,0 +1,235 @@ +/** + * Lazy designer artwork for furniture (#474). + * + * The 44 designer symbols carry ~10 KB gzip of SVG paths that every plan used + * to pay for, including plans without a single piece of furniture. The + * catalogue (ids, groups, default sizes) stays in the initial View graph; + * the artwork lives in its own chunk behind this page-scoped runtime. + * + * Contract mirrors `LanguageRuntime` and `EditorRuntimeLoader`: + * + * - `pending` until the first `ensure()` and while a load is in flight; + * - `ready` once the artwork is installed — either loaded here or handed over + * synchronously by the editor chunk, which imports the artwork statically + * (`adopt`), so the palette and the placement ghost never see `pending`; + * - `fallback` is a SETTLED state: two failed attempts (the second through a + * nonce URL, because Chromium caches a failed module forever, #352–#355) or + * a fingerprint from another build. A card must never stay behind the boot + * veil because of artwork; pieces render as unknown symbols — nothing — + * exactly as a plan written by a newer card does in an older one. + * + * Hosts that rendered while `pending` register through `art(id, host)` and + * get one `requestUpdate()` when the runtime settles. + */ +import type { FurnitureGraphic } from './furniture'; + +export type FurnitureArtState = 'ready' | 'pending' | 'fallback'; + +export interface FurnitureArtModule { + readonly GENERATED_FURNITURE_ART: Readonly>; + readonly FURNITURE_ART_FINGERPRINT: string; +} + +export interface FurnitureArtHost { + requestUpdate(): void; + readonly isConnected: boolean; +} + +export interface FurnitureArtRuntimeOptions { + /** Build id embedded in the entry; artwork from another build is rejected. */ + expectedFingerprint: string; + /** Attempt 0 — ordinary dynamic import; attempt 1 — nonce URL. */ + load: (attempt: 0 | 1) => Promise; + warn?: (message: string, error: unknown) => void; + /** Settled into `fallback`: the host shows one toast per page. */ + loadFailed?: (terminal: boolean) => void; +} + +/** Minimal shape of a card config for `configNeedsFurnitureArt`. */ +export interface FurnitureArtConfigLike { + spaces?: ReadonlyArray<{ decor?: ReadonlyArray<{ kind?: string; symbol?: string }> | null } | null> | null; +} + +export class FurnitureArtRuntime { + private _art: Readonly> | null = null; + private _failed = false; + private _terminal = false; + private _inFlight: Promise | null = null; + private readonly _hosts = new Set(); + private readonly _settled: Array<() => void> = []; + + public constructor(private readonly options: FurnitureArtRuntimeOptions) {} + + public state(): FurnitureArtState { + if (this._art) return 'ready'; + if (this._failed) return 'fallback'; + return 'pending'; + } + + /** Terminal fallback: the tab holds another build; only a refresh helps. */ + public get terminal(): boolean { + return this._terminal; + } + + /** + * Synchronous artwork lookup. A host passed while `pending` is remembered + * and re-rendered once when the runtime settles; the lookup itself never + * starts a load — that is `ensure()`'s job, so a plan without furniture + * never requests the chunk. + */ + public art(id: string, host?: FurnitureArtHost): FurnitureGraphic | undefined { + if (this._art) return this._art[id]; + if (host && !this._failed) this._hosts.add(host); + return undefined; + } + + /** + * Hand over artwork that another chunk already loaded (the editor imports + * it statically). Synchronous: the palette renders `ready` on its first + * frame. A foreign fingerprint is ignored — the editor loader would have + * rejected such a chunk anyway — and a repeated adopt is a no-op. + */ + public adopt(art: Readonly>, fingerprint: string): boolean { + if (this._art) return true; + if (fingerprint !== this.options.expectedFingerprint) { + (this.options.warn ?? console.warn)( + '[houseplan] furniture artwork from another build ignored', { fingerprint }, + ); + return false; + } + this._install(art); + return true; + } + + /** Idempotent: one in-flight load, settled states resolve immediately. */ + public ensure(): Promise { + if (this.state() !== 'pending') return Promise.resolve(); + if (this._inFlight) return this._inFlight; + this._inFlight = this._loadWithRetry().finally(() => { + this._inFlight = null; + }); + return this._inFlight; + } + + /** Resolves when the runtime leaves `pending` (already settled → next tick). */ + public onSettled(callback: () => void): void { + if (this.state() !== 'pending') { + void Promise.resolve().then(callback); + return; + } + this._settled.push(callback); + } + + private async _loadWithRetry(): Promise { + let lastError: unknown = new Error('furniture artwork did not load'); + for (const attempt of [0, 1] as const) { + try { + const module = await this.options.load(attempt); + if (module.FURNITURE_ART_FINGERPRINT !== this.options.expectedFingerprint) { + this._terminal = true; + lastError = new Error(`furniture artwork fingerprint mismatch: expected ${this.options.expectedFingerprint}, got ${module.FURNITURE_ART_FINGERPRINT}`); + break; + } + if (this._art) return; // adopted by the editor while we were loading + this._install(module.GENERATED_FURNITURE_ART); + return; + } catch (error) { + lastError = error; + } + } + if (this._art) return; + this._failed = true; + (this.options.warn ?? console.warn)('[houseplan] furniture artwork unavailable', lastError); + this.options.loadFailed?.(this._terminal); + this._flush(); + } + + private _install(art: Readonly>): void { + this._art = art; + this._failed = false; + this._flush(); + } + + private _flush(): void { + const hosts = [...this._hosts]; + this._hosts.clear(); + for (const host of hosts) if (host.isConnected) host.requestUpdate(); + const callbacks = this._settled.splice(0); + for (const callback of callbacks) callback(); + } +} + +/** Does this config draw at least one piece whose artwork is lazy? */ +export function configNeedsFurnitureArt( + config: FurnitureArtConfigLike | null | undefined, + isDesigner: (symbol: string) => boolean, +): boolean { + for (const space of config?.spaces ?? []) { + for (const shape of space?.decor ?? []) { + if (shape?.kind === 'furniture' && typeof shape.symbol === 'string' && isDesigner(shape.symbol)) return true; + } + } + return false; +} + +/** + * Boot veil gate: `true` while the veil must stay down because the plan + * draws lazy artwork that has not settled yet. Plans without furniture never + * wait; `fallback` counts as settled. The card's BOOT_MAX_MS hard cap still + * applies on top — the veil can never get stuck on artwork. + */ +export function furnitureArtBootPending( + runtime: Pick, + config: FurnitureArtConfigLike | null | undefined, + isDesigner: (symbol: string) => boolean, +): boolean { + return runtime.state() === 'pending' && configNeedsFurnitureArt(config, isDesigner); +} + +/** + * Config intake: start the load before the first frame when the plan needs + * it; register the host for the settle re-render. One call from the core. + */ +export function ensureFurnitureArtFor( + runtime: FurnitureArtRuntime, + config: FurnitureArtConfigLike | null | undefined, + isDesigner: (symbol: string) => boolean, + host: FurnitureArtHost, +): void { + if (!configNeedsFurnitureArt(config, isDesigner)) return; + if (runtime.state() === 'pending') { + runtime.art('', host); + void runtime.ensure(); + } +} + +/* Page-scoped runtime wired to the real chunk. The retry token is replaced + * at build time with the exact content-hashed asset (bundle-manifest.mjs). */ +const ENTRY_BUILD_FINGERPRINT = '__HOUSEPLAN_SOURCE_FINGERPRINT__'; +const FURNITURE_ART_RETRY_ASSET = '__HOUSEPLAN_FURNITURE_ART_RETRY_ASSET__'; +let retrySeq = 0; + +const loadFailures = new Set<(terminal: boolean) => void>(); +/** Chain unsubscribe handles into one (keeps the host's bookkeeping flat). */ +export function composeUnsub(...unsubs: Array<() => void>): () => void { + return () => { for (const unsub of unsubs) unsub(); }; +} +/** #354-style hook: the host shows one toast per page when artwork settles into fallback. */ +export function subscribeFurnitureArtLoadFailures(listener: (terminal: boolean) => void): () => void { + loadFailures.add(listener); + return () => { loadFailures.delete(listener); }; +} + +export const FURNITURE_ART_RUNTIME = new FurnitureArtRuntime({ + expectedFingerprint: ENTRY_BUILD_FINGERPRINT, + load: async (attempt) => (attempt === 0 + ? await import('./furniture-plan-art.generated') + : await import(/* @vite-ignore */ (() => { + const url = new URL(FURNITURE_ART_RETRY_ASSET, import.meta.url); + url.searchParams.set('hp_retry', `art-${++retrySeq}`); + return url.href; + })())) as FurnitureArtModule, + loadFailed: (terminal) => { + for (const listener of loadFailures) listener(terminal); + }, +}); diff --git a/src/furniture-placement.ts b/src/furniture-placement.ts index 774a1b47..f530a7ec 100644 --- a/src/furniture-placement.ts +++ b/src/furniture-placement.ts @@ -1,6 +1,6 @@ /** Editor-only placement geometry for the furniture tool (#359, #445). */ import { clampCanvasN } from './space-geometry'; -import { clampFurnSize, cmToNorm, furnitureGraphic } from './furniture'; +import { clampFurnSize, cmToNorm, furnitureSymbol } from './furniture'; import type { FurnitureWallSurface } from './furniture-wall-surface'; /** How far from a wall the magnet still reaches, in grid cells. */ @@ -167,7 +167,9 @@ export function resolveFurniturePlacement(input: FurniturePlacementInput): Furni symbol, widthCm, depthCm, point, canvasW, canvasH, cellCm, gridPitch, walls, wallReach, free = false, intentPoint = point, preferredNormal, } = input; - if (!furnitureGraphic(symbol) || !(canvasW > 0) || !(canvasH > 0) + // The magnet needs the catalogue (sizes), not the artwork: designer art is + // lazy (#474) and must not refuse a placement while the chunk is pending. + if (!furnitureSymbol(symbol) || !(canvasW > 0) || !(canvasH > 0) || !Number.isFinite(point[0]) || !Number.isFinite(point[1])) return null; const safeIntent: readonly [number, number] = Number.isFinite(intentPoint[0]) && Number.isFinite(intentPoint[1]) ? intentPoint : point; diff --git a/src/furniture-plan-art.generated.ts b/src/furniture-plan-art.generated.ts index 3cb8994c..4a550607 100644 --- a/src/furniture-plan-art.generated.ts +++ b/src/furniture-plan-art.generated.ts @@ -1,2 +1,6 @@ /* Generated by scripts/generate-furniture-assets.mjs. DO NOT EDIT. */ -export const GENERATED_FURNITURE_PLAN = [{"id":"coffee_table","group":"furniture","category":"coffee_table","w":120,"h":60,"art":{"d":"M3.84 5.884c0-1.21 1.048-2.192 2.34-2.192h107.64c1.293 0 2.34.981 2.34 2.192v48.23c0 1.212-1.047 2.193-2.34 2.193H6.18c-1.292 0-2.34-.981-2.34-2.192z M103.056 15.093V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.078v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m-93.6-35.077V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.078v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877","viewW":120,"viewH":60}},{"id":"coffee_table_round","group":"furniture","category":"coffee_table","w":80,"h":80,"art":{"d":"M3.765 40a36.235 36.235 0 1 0 72.47 0 36.235 36.235 0 1 0-72.47 0 m56.26 26.96-3.843-3.843a.906.906 0 0 1 0-1.28l3.843-3.844a.906.906 0 0 1 1.281 0l3.844 3.843a.906.906 0 0 1 0 1.281l-3.844 3.844a.906.906 0 0 1-1.28 0m-.001 34.66-3.843-3.843a.906.906 0 0 1 0-1.281l3.843-3.844a.906.906 0 0 1 1.281 0l3.843 3.844a.906.906 0 0 1 0 1.28l-3.843 3.844a.906.906 0 0 1-1.281 0m-34.423-34.66-3.843-3.843a.906.906 0 0 1 0-1.281l3.843-3.844a.906.906 0 0 1 1.281 0l3.844 3.844a.906.906 0 0 1 0 1.28l-3.844 3.844a.906.906 0 0 1-1.28 0m-.001 34.66-3.843-3.843a.906.906 0 0 1 0-1.281l3.843-3.843a.906.906 0 0 1 1.281 0l3.844 3.843a.906.906 0 0 1 0 1.281l-3.844 3.843a.906.906 0 0 1-1.28 0","viewW":80,"viewH":80}},{"id":"coffee_table_oval","group":"furniture","category":"coffee_table","w":120,"h":60,"art":{"d":"M3.84 30c0-14.53 12.572-26.308 28.08-26.308h56.16c15.509 0 28.08 11.778 28.08 26.308s-12.571 26.307-28.08 26.307H31.92C16.412 56.307 3.84 44.53 3.84 30 M80.592 15.093V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.077v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877M31.92 15.093V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.876h-5.616a.936.877 0 0 1-.936-.876m0 35.077v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.876h-5.616a.936.877 0 0 1-.936-.876","viewW":120,"viewH":60}},{"id":"coffee_table_rounded","group":"furniture","category":"coffee_table","w":120,"h":60,"art":{"d":"M3.84 12.461c0-4.843 4.19-8.77 9.36-8.77h93.6c5.17 0 9.36 3.927 9.36 8.77v35.077c0 4.843-4.19 8.77-9.36 8.77H13.2c-5.17 0-9.36-3.927-9.36-8.77z M103.056 15.093V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.078v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m-93.6-35.077V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.078v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877","viewW":120,"viewH":60}},{"id":"table_dining","group":"furniture","category":"dining_table","w":160,"h":90,"art":{"d":"M3.879 6.08c0-1.265 1.065-2.29 2.378-2.29h147.484c1.314 0 2.38 1.025 2.38 2.29v77.84c0 1.265-1.066 2.29-2.38 2.29H6.257c-1.313 0-2.378-1.025-2.378-2.29z M138.994 19.358v-5.495a.952.916 0 0 1 .951-.915h5.71a.952.916 0 0 1 .95.915v5.495a.952.916 0 0 1-.95.916h-5.71a.952.916 0 0 1-.951-.916m-.001 56.778v-5.495a.952.916 0 0 1 .952-.915h5.709a.952.916 0 0 1 .951.915v5.495a.952.916 0 0 1-.951.916h-5.71a.952.916 0 0 1-.95-.916m-125.6-56.778v-5.495a.952.916 0 0 1 .951-.916h5.71a.952.916 0 0 1 .95.916v5.495a.952.916 0 0 1-.95.915h-5.71a.952.916 0 0 1-.951-.915m-.001 56.779v-5.495a.952.916 0 0 1 .952-.916h5.709a.952.916 0 0 1 .951.916v5.495a.952.916 0 0 1-.951.915h-5.71a.952.916 0 0 1-.95-.915","viewW":160,"viewH":90}},{"id":"table_round","group":"furniture","category":"dining_table","w":110,"h":110,"art":{"d":"M3.826 55a51.174 51.174 0 1 0 102.349 0A51.174 51.174 0 1 0 3.826 55 m81.005 32.303-3.947-3.947a.93.93 0 0 1 0-1.316l3.947-3.948a.93.93 0 0 1 1.316 0l3.948 3.948a.93.93 0 0 1 0 1.316l-3.948 3.947a.93.93 0 0 1-1.316 0m0 54.897-3.947-3.948a.93.93 0 0 1 0-1.316l3.947-3.947a.93.93 0 0 1 1.316 0l3.948 3.947a.93.93 0 0 1 0 1.316L82.32 87.2a.93.93 0 0 1-1.316 0M27.04 32.304l-3.947-3.948a.93.93 0 0 1 0-1.315l3.948-3.948a.93.93 0 0 1 1.315 0l3.948 3.948a.93.93 0 0 1 0 1.315l-3.948 3.948a.93.93 0 0 1-1.315 0m-.001 54.604-3.947-3.948a.93.93 0 0 1 0-1.316l3.948-3.947a.93.93 0 0 1 1.315 0l3.948 3.947a.93.93 0 0 1 0 1.316l-3.948 3.948a.93.93 0 0 1-1.315 0","viewW":110,"viewH":110}},{"id":"table_dining_oval","group":"furniture","category":"dining_table","w":180,"h":100,"art":{"d":"M3.892 50c0-25.51 21.418-46.19 47.838-46.19h76.54c26.42 0 47.839 20.68 47.839 46.19S154.69 96.19 128.27 96.19H51.73C25.31 96.19 3.892 75.51 3.892 50 M122.53 19.514V13.97a.957.924 0 0 1 .956-.924h5.74a.957.924 0 0 1 .958.924v5.543a.957.924 0 0 1-.957.924h-5.74a.957.924 0 0 1-.958-.924m.001 66.516v-5.543a.957.924 0 0 1 .957-.924h5.74a.957.924 0 0 1 .957.924v5.543a.957.924 0 0 1-.957.924h-5.74a.957.924 0 0 1-.957-.924M49.816 19.515v-5.543a.957.924 0 0 1 .957-.924h5.74a.957.924 0 0 1 .958.924v5.542a.957.924 0 0 1-.957.924h-5.74a.957.924 0 0 1-.958-.924m0 66.516v-5.543a.957.924 0 0 1 .957-.924h5.74a.957.924 0 0 1 .957.924v5.543a.957.924 0 0 1-.957.923h-5.74a.957.924 0 0 1-.957-.924","viewW":180,"viewH":100}},{"id":"table_dining_rounded","group":"furniture","category":"dining_table","w":160,"h":90,"art":{"d":"M3.879 17.527c0-7.587 6.39-13.737 14.272-13.737h123.696c7.883 0 14.273 6.15 14.273 13.737v54.947c0 7.587-6.39 13.737-14.273 13.737H18.151c-7.882 0-14.272-6.15-14.272-13.737z M138.994 19.358v-5.495a.952.916 0 0 1 .951-.915h5.71a.952.916 0 0 1 .95.915v5.495a.952.916 0 0 1-.95.916h-5.71a.952.916 0 0 1-.951-.916m-.001 56.778v-5.495a.952.916 0 0 1 .952-.915h5.709a.952.916 0 0 1 .951.915v5.495a.952.916 0 0 1-.951.916h-5.71a.952.916 0 0 1-.95-.916m-125.6-56.778v-5.495a.952.916 0 0 1 .951-.916h5.71a.952.916 0 0 1 .95.916v5.495a.952.916 0 0 1-.95.915h-5.71a.952.916 0 0 1-.951-.915m-.001 56.779v-5.495a.952.916 0 0 1 .952-.916h5.709a.952.916 0 0 1 .951.916v5.495a.952.916 0 0 1-.951.915h-5.71a.952.916 0 0 1-.95-.915","viewW":160,"viewH":90}},{"id":"desk","group":"furniture","category":"work_table","w":140,"h":70,"art":{"d":"M3.862 5.967c0-1.234 1.057-2.234 2.362-2.234h127.552c1.305 0 2.362 1 2.362 2.234v58.066c0 1.234-1.057 2.233-2.362 2.233H6.224c-1.305 0-2.362-1-2.362-2.233z M9.531 15.346v-5.36a.945.893 0 0 1 .945-.893h5.67a.945.893 0 0 1 .944.893v5.36a.945.893 0 0 1-.945.894h-5.669a.945.893 0 0 1-.945-.894m113.379.001v-5.36a.945.893 0 0 1 .945-.894h5.67a.945.893 0 0 1 .944.894v5.36a.945.893 0 0 1-.945.893h-5.669a.945.893 0 0 1-.945-.893M9.53 60.013v-5.36a.945.893 0 0 1 .946-.893h5.669a.945.893 0 0 1 .945.893v5.36a.945.893 0 0 1-.945.894h-5.67a.945.893 0 0 1-.944-.894m113.38.001v-5.36a.945.893 0 0 1 .945-.894h5.669a.945.893 0 0 1 .945.894v5.36a.945.893 0 0 1-.945.893h-5.67a.945.893 0 0 1-.944-.893m-97.318-2.681h88.814","viewW":140,"viewH":70}},{"id":"desk_corner","group":"furniture","category":"work_table","w":160,"h":160,"art":{"d":"M156.12 66.202a2.38 2.38 0 0 1-2.379 2.38H94.272c-13.138 0-23.788 10.65-23.788 23.787v61.372a2.38 2.38 0 0 1-2.379 2.38H6.257a2.38 2.38 0 0 1-2.378-2.38V6.257A2.38 2.38 0 0 1 6.257 3.88h147.484a2.38 2.38 0 0 1 2.38 2.378z M9.588 16.249v-5.71a.95.95 0 0 1 .951-.95h5.71a.95.95 0 0 1 .95.95v5.71a.95.95 0 0 1-.95.951h-5.71a.95.95 0 0 1-.951-.951m133.212.001v-5.71a.95.95 0 0 1 .951-.951h5.71a.95.95 0 0 1 .95.951v5.71a.95.95 0 0 1-.95.951h-5.71a.95.95 0 0 1-.951-.951m0 45.672v-5.71a.95.95 0 0 1 .952-.951h5.709a.95.95 0 0 1 .951.951v5.71a.95.95 0 0 1-.951.951h-5.71a.95.95 0 0 1-.95-.951M9.587 149.46v-5.708a.95.95 0 0 1 .952-.952h5.709a.95.95 0 0 1 .951.952v5.709a.95.95 0 0 1-.951.951h-5.71a.95.95 0 0 1-.951-.951m47.576 0v-5.709a.95.95 0 0 1 .952-.951h5.709a.95.95 0 0 1 .951.951v5.71a.95.95 0 0 1-.951.95h-5.71a.95.95 0 0 1-.951-.95m51.382-90.396H95.569a34.6 34.6 0 0 0-34.6 34.6v12.976","viewW":160,"viewH":160}},{"id":"chair","group":"furniture","category":"chair","w":50,"h":50,"art":{"d":"M39.452 12.433H10.548a4.398 4.398 0 1 1 0-8.796h28.904a4.398 4.398 0 0 1 0 8.796m-28.904 0H8.035a4.4 4.4 0 0 0-4.398 4.399V40.08a6.283 6.283 0 0 0 6.283 6.284h30.16a6.283 6.283 0 0 0 6.284-6.284V16.832c0-2.43-1.97-4.399-4.399-4.399h-2.513","viewW":50,"viewH":50}},{"id":"chair_bar","group":"furniture","category":"chair","w":45,"h":48,"art":{"d":"M38.579 17.168c1.326 2.526 1.947 6.015 1.947 9.071 0 10.018-8.07 18.139-18.025 18.139S4.475 36.257 4.475 26.239c0-3.056.586-6.552 1.912-9.078m32.192.007a3.59 3.59 0 0 1-3.333-.976m3.333.976a3.6 3.6 0 0 0 1.765-.976m-33.827.996-.13-.027a3.6 3.6 0 0 1-1.731-.969m30.59 0a18 18 0 0 0-5.848-3.932 17.93 17.93 0 0 0-13.796 0 18 18 0 0 0-5.848 3.932 3.59 3.59 0 0 1-3.237.996m28.729-.996a3.59 3.59 0 0 0 5.098 0m-33.827.996a3.6 3.6 0 0 1-1.861-.996 3.644 3.644 0 0 1 0-5.13 25.2 25.2 0 0 1 8.187-5.505A25.1 25.1 0 0 1 22.5 3.623a25.1 25.1 0 0 1 9.657 1.934 25.2 25.2 0 0 1 8.187 5.505 3.644 3.644 0 0 1 0 5.13","viewW":45,"viewH":48}},{"id":"armchair","group":"furniture","category":"armchair","w":90,"h":90,"art":{"d":"M75.702 13.011q.012-.225.012-.453c0-4.843-3.917-8.768-8.748-8.768H23.034c-4.83 0-8.747 3.925-8.747 8.768q0 .228.011.453M77.132 72.09q.59.091 1.206.092c4.348 0 7.873-3.533 7.873-7.892V20.45c0-4.359-3.525-7.892-7.873-7.892-.924 0-1.812.16-2.636.453a7.89 7.89 0 0 0-5.237 7.438v.148m0 0a8.7 8.7 0 0 1-3.499.73H23.034a8.7 8.7 0 0 1-3.499-.73m50.93 0V64.29a7.89 7.89 0 0 0 6.667 7.8M14.298 13.01a7.89 7.89 0 0 1 5.237 7.438v.148m0 0V64.29a7.89 7.89 0 0 1-6.666 7.8q-.59.091-1.206.092c-4.348 0-7.873-3.533-7.873-7.892V20.45c0-4.359 3.525-7.892 7.873-7.892.924 0 1.811.16 2.635.453M77.132 72.09c-1.585 8.05-8.667 14.12-17.164 14.12H30.032c-8.496 0-15.578-6.07-17.163-14.12","viewW":90,"viewH":90}},{"id":"armchair_office","group":"furniture","category":"armchair","w":65,"h":65,"art":{"d":"M56.968 18.845q0-.368-.05-.72M49.051 13.8H15.95a5.04 5.04 0 0 1-5.038-5.043 5.04 5.04 0 0 1 5.038-5.043h33.103a5.04 5.04 0 0 1 5.038 5.043 5.04 5.04 0 0 1-5.038 5.043m-33.103 0h-2.88a5.04 5.04 0 0 0-4.986 4.323M49.052 13.8h2.879a5.04 5.04 0 0 1 4.986 4.324m.051 24.826a4.32 4.32 0 0 0 4.318-4.323v-16.18a4.32 4.32 0 0 0-4.369-4.322m.051 24.826a4.32 4.32 0 0 1-4.318-4.323V22.447a4.32 4.32 0 0 1 4.267-4.322m-11.84 37.24h4.695c.736 0 1.446-.111 2.115-.317a7.21 7.21 0 0 0 5.081-6.889v-5.208M8.084 18.124h-.051a4.32 4.32 0 0 0-4.318 4.323v16.18a4.32 4.32 0 0 0 4.318 4.324 4.32 4.32 0 0 0 4.317-4.323V22.447a4.32 4.32 0 0 0-4.266-4.323m11.935 37.24h-4.79a7.2 7.2 0 0 1-2.04-.294 7.21 7.21 0 0 1-5.156-6.91v-5.21m37.045 12.414 5.177 5.183c.969.97 2.534.987 3.524.038a2.526 2.526 0 0 0 .038-3.605l-1.93-1.932m-6.81.316H20.02m-6.83-.294-1.909 1.91c-.998 1-.98 2.627.038 3.605.99.949 2.555.932 3.524-.038l5.177-5.183","viewW":65,"viewH":65}},{"id":"sofa","group":"furniture","category":"sofa","w":180,"h":90,"art":{"d":"M90 19.365v57.111m0-57.11V7.683m0 11.681c0 2.151-1.836 3.894-4.1 3.894H30.544a10.7 10.7 0 0 1-4.136-.825M90 19.365c0 2.151 1.836 3.894 4.1 3.894h55.356c1.472 0 2.871-.294 4.137-.825M90 76.476c0 5.376-4.59 9.735-10.25 9.735H30.543c-5.266 0-9.605-3.772-10.185-8.625M90 76.476c0 5.376 4.59 9.735 10.25 9.735h49.206c5.266 0 9.605-3.772 10.185-8.625M90 7.684c0-2.15-1.837-3.894-4.101-3.894H30.544c-5.661 0-10.25 4.358-10.25 9.735q0 .416.036.825M90 7.684c0-2.15 1.836-3.894 4.1-3.894h55.356c5.661 0 10.25 4.358 10.25 9.735q0 .416-.036.825m0 0a10.7 10.7 0 0 1 4.137-.825h2.05c5.662 0 10.252 4.358 10.252 9.734v45.43c0 5.376-4.59 9.734-10.251 9.734h-2.05c-1.484 0-2.894-.3-4.167-.837m0 0c-3.585-1.517-6.084-4.93-6.084-8.898V23.26q0-.417.036-.825c.32-3.622 2.728-6.68 6.077-8.084m-139.34 0c3.35 1.404 5.758 4.462 6.078 8.084q.036.408.036.825v45.43c0 3.967-2.5 7.38-6.085 8.897a10.7 10.7 0 0 1-4.166.837h-2.05c-5.662 0-10.251-4.358-10.251-9.735V23.26c0-5.376 4.59-9.734 10.25-9.734h2.05c1.473 0 2.872.294 4.138.825","viewW":180,"viewH":90}},{"id":"sofa_three_seat","group":"furniture","category":"sofa","w":240,"h":90,"art":{"d":"M86.553 18.593V76.96m0-58.366V7.491m0 11.102c0 2.044-1.762 3.701-3.935 3.701H29.496c-1.413 0-2.756-.28-3.97-.784m61.027-2.917c0 2.044 1.762 3.701 3.935 3.701h59.024c2.174 0 3.935-1.657 3.935-3.7M86.553 76.958c0 5.11-4.404 9.252-9.837 9.252h-47.22c-5.054 0-9.218-3.585-9.775-8.198m66.832-1.054c0 5.11 4.404 9.252 9.837 9.252h47.22c5.433 0 9.837-4.142 9.837-9.252m0-58.366V76.96m0-58.366V7.491m0 11.102c0 2.044 1.762 3.701 3.936 3.701h53.122c1.413 0 2.756-.28 3.97-.784m-61.028 55.449c0 5.11 4.405 9.252 9.838 9.252h47.22c5.054 0 9.218-3.585 9.775-8.198M86.553 7.491c0-2.044-1.762-3.701-3.935-3.701H29.496c-5.433 0-9.838 4.142-9.838 9.252q0 .396.035.784m66.86-6.335c0-2.044 1.762-3.701 3.935-3.701h59.024c2.174 0 3.935 1.657 3.935 3.7m0 0c0-2.043 1.762-3.7 3.936-3.7h53.122c5.433 0 9.838 4.142 9.838 9.252 0 .258.022.517 0 .77m-.063 64.201c1.22.512 2.574.796 3.998.796h1.967c5.433 0 9.837-4.142 9.837-9.252V22.294c0-5.11-4.404-9.252-9.837-9.252h-1.967c-5.153 0-9.38 3.725-9.803 8.468q-.036.387-.035.784v47.263c0 3.771 2.399 7.015 5.84 8.456M19.693 13.826a10.3 10.3 0 0 0-3.97-.784h-1.967c-5.433 0-9.838 4.142-9.838 9.252v47.263c0 5.11 4.405 9.252 9.838 9.252h1.967c1.424 0 2.777-.284 3.998-.796 3.441-1.441 5.84-4.685 5.84-8.456V22.294a9 9 0 0 0-.035-.784c-.307-3.443-2.618-6.349-5.833-7.684","viewW":240,"viewH":90}},{"id":"sofa_corner_right","group":"furniture","category":"sofa","w":260,"h":170,"art":{"d":"M93.673 20.687V83.69m0-63.004v-12.6m0 12.6c0 2.32-1.913 4.2-4.273 4.2H31.704a10.8 10.8 0 0 1-4.311-.89m66.28-3.31c0 2.32 1.914 4.2 4.274 4.2h64.106c2.36 0 4.274-1.88 4.274-4.2M93.673 83.692c0 5.8-4.783 10.501-10.684 10.501H31.704c-5.489 0-10.011-4.068-10.616-9.304m72.585-1.197c0 5.8 4.784 10.501 10.684 10.501h51.286c5.9 0 10.684-4.701 10.684-10.5m0-63.005V83.69m0-63.004v-12.6m0 12.6c0 2.32 1.914 4.2 4.273 4.2h57.696c1.534 0 2.993-.317 4.312-.89m-66.28 59.695v71.923c0 5.799 4.782 10.5 10.684 10.5h51.284c5.49 0 10.012-4.068 10.616-9.304V84.888M93.673 8.086c0-2.32-1.913-4.2-4.273-4.2H31.704c-5.9 0-10.684 4.7-10.684 10.5q0 .45.038.89m72.615-7.19c0-2.32 1.914-4.2 4.274-4.2h64.106c2.36 0 4.274 1.88 4.274 4.2m0 0c0-2.32 1.914-4.2 4.273-4.2h57.696c5.9 0 10.685 4.7 10.685 10.5 0 .293.024.587 0 .874m-.07 69.628c1.327.58 2.797.904 4.344.904h2.136c5.901 0 10.684-4.702 10.684-10.501V24.887c0-5.8-4.783-10.5-10.684-10.5h-2.136c-5.596 0-10.187 4.227-10.647 9.61q-.038.44-.038.89V75.29c0 4.28 2.605 7.961 6.342 9.597M21.059 15.276a10.8 10.8 0 0 0-4.312-.89H14.61c-5.9 0-10.684 4.701-10.684 10.5v50.405c0 5.8 4.783 10.5 10.684 10.5h2.137c1.546 0 3.016-.322 4.342-.903 3.737-1.636 6.342-5.317 6.342-9.597V24.887q0-.45-.037-.89c-.334-3.907-2.844-7.206-6.335-8.72","viewW":260,"viewH":170}},{"id":"bed_single","group":"furniture","category":"bed","w":90,"h":200,"art":{"d":"M3.79 14.024c0 5.59 4.318 10.122 9.645 10.122h63.13c5.328 0 9.646-4.532 9.646-10.122m-22.797 46.93V46.23c0-5.082-3.926-9.201-8.769-9.201h-19.29c-4.842 0-8.768 4.12-8.768 9.201v14.723m-22.797 0h82.42m0 22.085H3.79m8.768 113.06h64.885c4.842 0 8.768-4.12 8.768-9.202V13.104c0-5.082-3.926-9.202-8.768-9.202H12.558c-4.843 0-8.768 4.12-8.768 9.202v173.792c0 5.082 3.925 9.202 8.768 9.202","viewW":90,"viewH":200}},{"id":"bed_double","group":"furniture","category":"bed","w":160,"h":200,"art":{"d":"M3.879 14.073c0 5.618 4.516 10.172 10.088 10.172h132.065c5.571 0 10.088-4.554 10.088-10.172m-81.165 47.16V46.438c0-5.107-4.106-9.247-9.171-9.247H45.607c-5.065 0-9.17 4.14-9.17 9.247v14.795m89.877 0V46.438c0-5.107-4.107-9.247-9.172-9.247H96.966c-5.065 0-9.171 4.14-9.171 9.247v14.795m-83.916 0H156.12m0 22.192H3.88m9.17 112.673h133.9c5.065 0 9.171-4.14 9.171-9.247V13.15c0-5.107-4.106-9.247-9.171-9.247H13.05c-5.064 0-9.17 4.14-9.17 9.247v173.7c0 5.107 4.106 9.247 9.17 9.247","viewW":160,"viewH":200}},{"id":"nightstand","group":"furniture","category":"nightstand","w":50,"h":40,"art":{"d":"M5.773 3.555h38.454a2.136 2.056 0 0 1 2.137 2.056v28.777a2.136 2.056 0 0 1-2.137 2.056H5.773a2.136 2.056 0 0 1-2.136-2.056V5.611a2.136 2.056 0 0 1 2.136-2.056","viewW":50,"viewH":40}},{"id":"cabinet_tv","group":"furniture","category":"nightstand","w":140,"h":45,"art":{"d":"M56.772 17.88h5.315m0 0h5.315m-5.315 0v9.214m9.832-9.214 5.315 9.45 5.314-9.45M6.224 41.4h127.552c1.305 0 2.362-.94 2.362-2.1V5.7c0-1.16-1.057-2.1-2.362-2.1H6.224c-1.305 0-2.362.94-2.362 2.1v33.6c0 1.16 1.057 2.1 2.362 2.1","viewW":140,"viewH":45}},{"id":"cabinet_shoe","group":"furniture","category":"nightstand","w":80,"h":35,"art":{"d":"m39.722 16.231 1.505-1.596m1.134 3.15 1.53-1.738M6.03 31.5h67.94c1.251 0 2.265-.895 2.265-2v-24c0-1.105-1.014-2-2.264-2H6.03c-1.251 0-2.265.895-2.265 2v24c0 1.105 1.014 2 2.265 2m41.966-14.305L46.92 17.1a3.4 3.4 0 0 1-1.813-.706l-4.583-3.62c-1.264-1-3.277-.326-3.475 1.161-.185 1.39-1.983 2.1-3.28 1.299l-1.532-.947c-.968-.513-2.2.103-2.2 1.1v3.463c0 1.559 1.43 2.823 3.196 2.823h14.51c1.404 0 2.542-1.005 2.542-2.245 0-1.153-.99-2.118-2.289-2.233","viewW":80,"viewH":35}},{"id":"cabinet_sink","group":"furniture","category":"nightstand","w":80,"h":50,"art":{"d":"M3.765 5.773c0-1.18 1.014-2.136 2.265-2.136h67.94c1.251 0 2.265.956 2.265 2.136v38.454c0 1.18-1.014 2.137-2.264 2.137H6.03c-1.251 0-2.265-.957-2.265-2.137z M36.088 32.135c2.525 1.88 6.205 1.88 8.73 0s3.167-5.101 1.52-7.637l-5.879-8.043-5.893 8.043c-1.644 2.536-1.003 5.755 1.522 7.637","viewW":80,"viewH":50}},{"id":"bookshelf","group":"furniture","category":"wardrobe","w":100,"h":35,"art":{"d":"M57.12 20.488H45.473c-.514 0-1.008.124-1.372.345s-.568.52-.568.832m4.076-8.236h5.434M6.119 3.5h87.762c1.276 0 2.31.895 2.31 2v24c0 1.105-1.034 2-2.31 2H6.12c-1.275 0-2.31-.895-2.31-2v-24c0-1.105 1.035-2 2.31-2m51 6.4v14.118H45.474a2.04 2.04 0 0 1-1.372-.517 1.7 1.7 0 0 1-.568-1.248V11.665c0-.468.204-.917.568-1.248a2.04 2.04 0 0 1 1.372-.517z","viewW":100,"viewH":35}},{"id":"wall_unit","group":"furniture","category":"wardrobe","w":240,"h":45,"art":{"d":"M6.336 41.4h227.328a2.418 2.1 0 0 0 2.418-2.1V5.7a2.418 2.1 0 0 0-2.418-2.1H6.336a2.418 2.1 0 0 0-2.418 2.1v33.6a2.418 2.1 0 0 0 2.418 2.1m43.744-5.88V9.48m46.432 26.04V9.48m46.433 26.04V9.48m46.433 26.04V9.48","viewW":240,"viewH":45}},{"id":"wardrobe","group":"furniture","category":"wardrobe","w":180,"h":60,"art":{"d":"M93.87 20.25a3.3 3.3 0 0 0-1.072-2.407 3.8 3.8 0 0 0-2.586-.997c-.97 0-1.9.358-2.587.997a3.3 3.3 0 0 0-1.071 2.407c0 2.838 1.225 5.107 3.658 6.81h-.015m0 0 14.58 7.537c.57.295 1.046.726 1.377 1.25.331.523.505 1.12.505 1.727v1.401a3.3 3.3 0 0 1-1.071 2.407 3.8 3.8 0 0 1-2.587.998H77.393a3.8 3.8 0 0 1-2.586-.998 3.3 3.3 0 0 1-1.072-2.407v-1.4c0-.608.174-1.205.505-1.728a3.55 3.55 0 0 1 1.377-1.25zM6.284 3.691h167.433c1.32 0 2.392.981 2.392 2.192v48.23c0 1.212-1.071 2.193-2.392 2.193H6.284c-1.321 0-2.392-.981-2.392-2.192V5.885c0-1.212 1.07-2.193 2.392-2.193","viewW":180,"viewH":60}},{"id":"kitchen_floor","group":"furniture","category":"kitchen_cabinet","w":60,"h":60,"art":{"d":"M3.692 5.884c0-1.21.981-2.192 2.192-2.192h48.23c1.212 0 2.193.981 2.193 2.192v48.23a2.19 2.19 0 0 1-2.192 2.193H5.885a2.19 2.19 0 0 1-2.193-2.192z","viewW":60,"viewH":60}},{"id":"kitchen_floor_corner","group":"furniture","category":"kitchen_cabinet","w":90,"h":90,"art":{"d":"M45.944 41.767a2.29 2.29 0 0 0 2.29 2.29H83.92a2.29 2.29 0 0 1 2.29 2.29V83.92a2.29 2.29 0 0 1-2.29 2.29H6.08a2.29 2.29 0 0 1-2.29-2.29V6.08a2.29 2.29 0 0 1 2.29-2.29h37.576a2.29 2.29 0 0 1 2.29 2.29z","viewW":90,"viewH":90}},{"id":"kitchen_wall","group":"furniture","category":"kitchen_cabinet","w":60,"h":35,"art":{"d":"m4.444 31.033 50.75-27.007m-50.752-.06 50.75 27.008M5.884 31.5h48.23c1.212 0 2.193-.895 2.193-2v-24c0-1.105-.981-2-2.192-2H5.885c-1.212 0-2.193.895-2.193 2v24c0 1.105.981 2 2.192 2","viewW":60,"viewH":35}},{"id":"kitchen_wall_corner","group":"furniture","category":"kitchen_cabinet","w":60,"h":60,"art":{"d":"M3.772 29.59 29.88 4.383M4.57 55.43 55.43 30M4.175 4.383l26.701 23.863m-27.184.877L55.43 55.43M28.41 3.692H5.884c-1.21 0-2.192.981-2.192 2.192v48.23c0 1.212.981 2.193 2.192 2.193h48.23a2.19 2.19 0 0 0 2.193-2.192V31.589c0-1.21-.981-2.192-2.192-2.192h-21.32a2.19 2.19 0 0 1-2.193-2.192V5.885a2.19 2.19 0 0 0-2.192-2.193","viewW":60,"viewH":60}},{"id":"shelf_floor","group":"furniture","category":"shelving","w":100,"h":35,"art":{"d":"M6.12 31.5h87.76a2.31 2 0 0 0 2.31-2v-24a2.31 2 0 0 0-2.31-2H6.12a2.31 2 0 0 0-2.31 2v24a2.31 2 0 0 0 2.31 2 M9.089 25.933c-.494.112-.776.546-.63.97s.664.675 1.157.564l-.263-.767zM90.912 9.067c.493-.112.775-.546.63-.97s-.664-.675-1.158-.564l.264.767zM11.875 26.956c.493-.112.775-.546.63-.97s-.664-.676-1.158-.564l.264.767zm3.988-2.556c-.493.112-.775.546-.63.969s.664.676 1.158.564l-.264-.766zm5.045.511c.493-.112.775-.545.63-.969s-.664-.676-1.158-.564l.264.766zm3.988-2.555c-.493.111-.775.545-.63.968.146.424.664.677 1.158.565l-.264-.767zm5.044.51c.494-.111.776-.545.63-.968-.145-.424-.664-.676-1.157-.565l.263.767zm3.99-2.555c-.495.112-.777.546-.63.97.145.423.663.675 1.157.563l-.264-.766zm5.043.511c.494-.112.776-.545.63-.969s-.664-.676-1.158-.564l.264.767zm3.989-2.555c-.494.111-.776.545-.63.969s.664.676 1.157.564l-.263-.767zm5.044.51c.494-.11.776-.545.63-.968-.146-.424-.664-.676-1.158-.565l.264.767zm3.989-2.555c-.494.112-.776.546-.63.97.145.423.664.675 1.157.564l-.264-.767zm5.044.511c.493-.111.775-.545.63-.969s-.664-.676-1.158-.564l.264.767zm3.988-2.555c-.493.112-.775.545-.63.969s.664.676 1.158.564l-.264-.767zm5.045.51c.493-.11.775-.545.63-.968-.146-.424-.664-.676-1.158-.564l.264.766zm3.988-2.555c-.493.112-.775.546-.63.97s.664.675 1.158.564l-.264-.767zm5.044.511c.494-.111.776-.545.63-.968-.145-.424-.664-.677-1.157-.565l.264.767zm3.99-2.555c-.494.112-.777.545-.63.969.145.423.663.676 1.157.564l-.264-.766zm5.043.511c.494-.112.776-.546.63-.969s-.664-.676-1.157-.564l.263.766zm3.989-2.556c-.494.112-.776.546-.63.97s.664.676 1.158.564l-.264-.767zM9.353 26.7l.263.767 2.259-.511-.264-.767-.264-.767-2.258.511zm6.774-1.533.264.766 4.517-1.022-.264-.767-.264-.766-4.517 1.022zm9.033-2.045.264.767 4.516-1.022-.264-.767-.263-.767-4.517 1.023zm9.033-2.044.264.766 4.516-1.022-.264-.766-.264-.767-4.516 1.022zm9.033-2.045.263.767 4.517-1.022-.264-.767-.264-.767-4.516 1.023zm9.032-2.044.264.767 4.517-1.023-.264-.766-.264-.767-4.516 1.022zm9.033-2.045.264.767 4.517-1.022-.264-.767-.264-.766-4.517 1.022zm9.033-2.044.264.767 4.516-1.023-.263-.766-.264-.767-4.517 1.022zm9.033-2.044.264.766 4.516-1.022-.264-.767-.263-.766-4.517 1.022zM88.39 8.81l.264.767 2.258-.511-.264-.767-.264-.767-2.258.511z M9.089 9.067c-.494-.112-.776-.546-.63-.97s.664-.675 1.157-.564l-.263.767zm81.823 16.866c.493.112.775.546.63.97s-.664.675-1.158.564l.264-.767zM11.875 8.044c.493.112.775.546.63.97s-.664.676-1.158.564l.264-.767zm3.988 2.556c-.493-.112-.775-.546-.63-.969s.664-.676 1.158-.564l-.264.766zm5.045-.511c.493.112.775.545.63.969s-.664.676-1.158.564l.264-.766zm3.988 2.555c-.493-.111-.775-.545-.63-.968.146-.424.664-.677 1.158-.565l-.264.767zm5.044-.51c.494.111.776.545.63.968-.145.424-.664.676-1.157.565l.263-.767zm3.99 2.555c-.495-.112-.777-.546-.63-.97.145-.423.663-.675 1.157-.563l-.264.766zm5.043-.511c.494.112.776.545.63.969s-.664.676-1.158.564l.264-.767zm3.989 2.555c-.494-.111-.776-.545-.63-.969s.664-.676 1.157-.564l-.263.767zm5.044-.51c.494.11.776.545.63.968-.146.424-.664.676-1.158.565l.264-.767zm3.989 2.555c-.494-.112-.776-.546-.63-.97.145-.423.664-.675 1.157-.564l-.264.767zm5.044-.511c.493.111.775.545.63.969s-.664.676-1.158.564l.264-.767zm3.988 2.555c-.493-.112-.775-.545-.63-.969s.664-.676 1.158-.564l-.264.767zm5.045-.51c.493.11.775.545.63.968-.146.424-.664.676-1.158.564l.264-.766zm3.988 2.555c-.493-.112-.775-.546-.63-.97s.664-.675 1.158-.564l-.264.767zm5.044-.511c.494.111.776.545.63.968-.145.424-.664.677-1.157.565l.264-.767zm3.99 2.555c-.494-.112-.777-.545-.63-.969.145-.423.663-.676 1.157-.564l-.264.766zm5.043-.511c.494.112.776.546.63.969s-.664.676-1.157.564l.263-.766zm3.989 2.556c-.494-.112-.776-.546-.63-.97s.664-.676 1.158-.564l-.264.767zM9.353 8.3l.263-.767 2.259.511-.264.767-.264.767-2.258-.511zm6.774 1.533.264-.766 4.517 1.022-.264.767-.264.766-4.517-1.022zm9.033 2.045.264-.767 4.516 1.022-.264.767-.263.767-4.517-1.023zm9.033 2.044.264-.766 4.516 1.022-.264.766-.264.767-4.516-1.022zm9.033 2.045.263-.767 4.517 1.022-.264.767-.264.767-4.516-1.023zm9.032 2.044.264-.767 4.517 1.023-.264.766-.264.767-4.516-1.022zm9.033 2.045.264-.767 4.517 1.022-.264.767-.264.766-4.517-1.022zm9.033 2.044.264-.767 4.516 1.023-.263.766-.264.767-4.517-1.022zm9.033 2.044.264-.766 4.516 1.022-.264.767-.263.766-4.517-1.022zm9.033 2.045.264-.767 2.258.511-.264.767-.264.767-2.258-.511z","viewW":100,"viewH":35}},{"id":"shelf_wall","group":"furniture","category":"shelving","w":100,"h":25,"art":{"d":"M18.36 3.15v2.567c0 1.012-1.034 1.833-2.31 1.833h-.924c-1.275 0-2.309-.82-2.309-1.833V3.15m73.905 0v2.567c0 1.012-1.034 1.833-2.31 1.833h-.924c-1.275 0-2.31-.82-2.31-1.833V3.15m-75.29 0H93.65c1.276 0 2.31.82 2.31 1.833V19.65c0 1.012-1.034 1.833-2.31 1.833H5.888c-1.275 0-2.31-.82-2.31-1.833V4.983c0-1.012 1.035-1.833 2.31-1.833","viewW":100,"viewH":25}},{"id":"cooktop_two","group":"appliance","category":"cooktop","w":30,"h":50,"art":{"d":"M15 30.982v-1.71m3.086 5.128h1.542M15 39.527v-1.709M10.372 34.4h1.542M5.84 46.364h18.322c1.331 0 2.41-1.196 2.41-2.67V6.306c0-1.475-1.079-2.67-2.41-2.67H5.839c-1.331 0-2.41 1.195-2.41 2.67v37.386c0 1.475 1.079 2.67 2.41 2.67m14.56-29.91c0 3.304-2.417 5.982-5.4 5.982-2.981 0-5.4-2.678-5.4-5.981s2.419-5.982 5.4-5.982c2.983 0 5.4 2.678 5.4 5.982M18.858 34.4c0 2.36-1.727 4.273-3.857 4.273s-3.857-1.913-3.857-4.273S12.87 30.127 15 30.127s3.857 1.913 3.857 4.273","viewW":30,"viewH":50}},{"id":"stove","group":"appliance","category":"cooktop","w":60,"h":60,"art":{"d":"M41.4 35.261a.877.877 0 1 0-1.754 0zm4.384 6.138a.877.877 0 1 0 0-1.753zM41.4 44.03a.877.877 0 1 0-1.753 0zm-4.384-2.63a.877.877 0 1 0 0-1.754zM5.885 3.691v.877h48.23V2.815H5.885zm50.422 2.192h-.877v48.23h1.754V5.885zm-2.192 50.423v-.877H5.885v1.754h48.23zM3.692 54.115h.877V5.885H2.815v48.23zm2.192 2.192v-.877a1.315 1.315 0 0 1-1.315-1.315H2.815a3.07 3.07 0 0 0 3.07 3.069zm50.423-2.192h-.877c0 .726-.589 1.315-1.315 1.315v1.754a3.07 3.07 0 0 0 3.069-3.07zM54.115 3.692v.877c.726 0 1.315.589 1.315 1.315h1.754a3.07 3.07 0 0 0-3.07-3.069zm-48.23 0v-.877a3.07 3.07 0 0 0-3.07 3.07h1.754c0-.727.589-1.316 1.315-1.316zm19.73 36.83h-.877a5.26 5.26 0 0 1-5.262 5.262v1.754a7.015 7.015 0 0 0 7.016-7.015zm-6.139 6.139v-.877a5.26 5.26 0 0 1-5.261-5.261h-1.754a7.015 7.015 0 0 0 7.015 7.015zm-6.138-6.138h.877a5.26 5.26 0 0 1 5.261-5.262v-1.754a7.015 7.015 0 0 0-7.015 7.016zm6.138-6.139v.877a5.26 5.26 0 0 1 5.262 5.262h1.754a7.015 7.015 0 0 0-7.016-7.016zm27.185-14.908h-.877a5.26 5.26 0 0 1-5.261 5.262v1.754a7.015 7.015 0 0 0 7.015-7.016zm-6.138 6.139v-.877a5.26 5.26 0 0 1-5.262-5.262h-1.754a7.015 7.015 0 0 0 7.016 7.016zm-6.139-6.139h.877a5.26 5.26 0 0 1 5.262-5.261v-1.754a7.015 7.015 0 0 0-7.016 7.015zm6.139-6.138v.877a5.26 5.26 0 0 1 5.261 5.261h1.754a7.015 7.015 0 0 0-7.015-7.015zm4.384 27.185h-.877a3.51 3.51 0 0 1-3.507 3.507v1.754a5.26 5.26 0 0 0 5.261-5.261zm-4.384 4.384v-.877a3.51 3.51 0 0 1-3.508-3.507H35.26a5.26 5.26 0 0 0 5.262 5.261zm-4.385-4.384h.877a3.51 3.51 0 0 1 3.508-3.508V35.26a5.26 5.26 0 0 0-5.262 5.262zm4.385-4.385v.877a3.51 3.51 0 0 1 3.507 3.508h1.754a5.26 5.26 0 0 0-5.261-5.262zm0 .877h.876V35.26h-1.753v1.754zm3.508 3.508v.876h1.753v-1.753h-1.753zm-3.508 5.261h.876V44.03h-1.753v1.754zm-5.261-5.261v.876h1.753v-1.753h-1.753zm-9.647-21.047h-.877a5.26 5.26 0 0 1-5.262 5.262v1.754a7.015 7.015 0 0 0 7.016-7.016zm-6.139 6.139v-.877a5.26 5.26 0 0 1-5.261-5.262h-1.754a7.015 7.015 0 0 0 7.015 7.016zm-6.138-6.139h.877a5.26 5.26 0 0 1 5.261-5.261v-1.754a7.015 7.015 0 0 0-7.015 7.015zm6.138-6.138v.877a5.26 5.26 0 0 1 5.262 5.261h1.754a7.015 7.015 0 0 0-7.016-7.015z","viewW":60,"viewH":60}},{"id":"tv","group":"appliance","category":"tv","w":120,"h":28,"art":{"d":"M45.134 10.766H6.18c-1.292 0-2.34.848-2.34 1.894v2.68c0 1.045 1.048 1.893 2.34 1.893h38.954m0-6.467V5.288c0-1.046 1.048-1.894 2.34-1.894h26.704c1.292 0 2.34.848 2.34 1.894v5.478m-31.384 0h31.384m0 0h37.302c1.293 0 2.34.848 2.34 1.894v2.68c0 1.045-1.047 1.893-2.34 1.893H76.518m-31.384 0v5.479c0 1.046 1.048 1.894 2.34 1.894h26.704c1.292 0 2.34-.848 2.34-1.894v-5.479m-31.384 0h31.384","viewW":120,"viewH":28}},{"id":"tv_wall","group":"appliance","category":"tv","w":120,"h":15,"art":{"d":"M35.664 11.4c-.517 0-.936.269-.936.6s.419.6.936.6zm49.553 1.2c.517 0 .936-.269.936-.6s-.42-.6-.936-.6zM6.18 3v.6h107.64V2.4H6.18zm109.98 1.5h-.936v1.8h1.872V4.5zm-2.34 3.3v-.6H6.18v1.2h107.64zM3.84 6.3h.936V4.5H2.904v1.8zm2.34 1.5v-.6c-.775 0-1.404-.403-1.404-.9H2.904c0 1.16 1.467 2.1 3.276 2.1zm109.98-1.5h-.936c0 .497-.629.9-1.404.9v1.2c1.81 0 3.276-.94 3.276-2.1zM113.82 3v.6c.775 0 1.404.403 1.404.9h1.872c0-1.16-1.467-2.1-3.276-2.1zM6.18 3v-.6c-1.81 0-3.276.94-3.276 2.1h1.872c0-.497.629-.9 1.404-.9zm61.308 4.2h-.936V12h1.872V7.2zM52.512 12h.936V7.2h-1.872V12zm-16.848 0v.6h49.553v-1.2H35.664z","viewW":120,"viewH":15}},{"id":"toilet","group":"sanitary","category":"toilet","w":40,"h":70,"art":{"d":"M3.555 48.976c0 9.55 7.125 17.29 15.914 17.29h1.061c8.79 0 15.914-7.74 15.914-17.29V5.966c0-1.233-.92-2.233-2.056-2.233H5.611c-1.135 0-2.056 1-2.056 2.234z M7.666 49.12c0 7.003 5.225 12.68 11.67 12.68h1.327c6.445 0 11.67-5.677 11.67-12.68V31.873c0-1.233-.92-2.233-2.056-2.233H9.722c-1.135 0-2.056 1-2.056 2.233zM33.792 3.733c1.465 0 2.652 1.29 2.652 2.882v12.103c0 1.592-1.187 2.882-2.652 2.882H6.208c-1.465 0-2.653-1.29-2.653-2.882V6.615c0-1.591 1.188-2.882 2.653-2.882z M24.11 50.186c0 2.467-1.84 4.467-4.11 4.467s-4.111-2-4.111-4.467 1.84-4.466 4.11-4.466 4.112 2 4.112 4.466","viewW":40,"viewH":70}},{"id":"toilet_built_in","group":"sanitary","category":"toilet","w":40,"h":55,"art":{"d":"M3.555 34.56c0 9.263 7.125 16.774 15.914 16.774h1.061c8.79 0 15.914-7.51 15.914-16.775V5.833c0-1.196-.92-2.166-2.056-2.166H5.611c-1.135 0-2.056.97-2.056 2.166z M7.666 34.7c0 6.793 5.225 12.3 11.67 12.3h1.327c6.445 0 11.67-5.507 11.67-12.3V14.5c0-1.197-.92-2.167-2.056-2.167H9.722c-1.135 0-2.056.97-2.056 2.167z M24.11 35.733c0 2.394-1.84 4.334-4.11 4.334s-4.111-1.94-4.111-4.334 1.84-4.333 4.11-4.333 4.112 1.94 4.112 4.333","viewW":40,"viewH":55}},{"id":"bathtub","group":"sanitary","category":"bathtub","w":170,"h":75,"art":{"d":"M3.885 6c0-1.243 1.068-2.25 2.386-2.25h157.458c1.318 0 2.386 1.007 2.386 2.25v63c0 1.243-1.068 2.25-2.386 2.25H6.27c-1.318 0-2.386-1.007-2.386-2.25z M13.428 37.5c0-13.669 11.75-24.75 26.243-24.75h90.658c14.493 0 26.243 11.081 26.243 24.75s-11.75 24.75-26.243 24.75H39.67c-14.493 0-26.243-11.081-26.243-24.75 M31.56 37.5c0 2.237-1.923 4.05-4.295 4.05s-4.294-1.813-4.294-4.05 1.923-4.05 4.294-4.05c2.372 0 4.295 1.813 4.295 4.05","viewW":170,"viewH":75}},{"id":"bathtub_corner","group":"sanitary","category":"bathtub","w":140,"h":140,"art":{"d":"M3.862 6.224a2.36 2.36 0 0 1 2.362-2.362H133.97c1.197 0 2.168.97 2.168 2.168 0 71.857-58.251 130.108-130.108 130.108a2.17 2.17 0 0 1-2.168-2.168z M13.31 32.207c0-10.437 8.46-18.897 18.897-18.897h87.628a2.13 2.13 0 0 1 2.13 2.13c0 58.833-47.692 106.526-106.524 106.526a2.13 2.13 0 0 1-2.13-2.131z M32.207 27.483a4.724 4.724 0 1 1-9.449 0 4.724 4.724 0 0 1 9.449 0","viewW":140,"viewH":140}},{"id":"bidet","group":"sanitary","category":"bidet","w":40,"h":60,"art":{"d":"M22.466 3.692v10.085c0 1.21-.92 2.192-2.055 2.192h-.822c-1.136 0-2.056-.981-2.056-2.192V3.692m4.933 8.77h2.878c1.135 0 2.056-.982 2.056-2.193v-.877c0-1.21-.92-2.192-2.056-2.192h-2.878m-4.933 5.262h-2.878c-1.135 0-2.055-.982-2.055-2.193v-.877c0-1.21.92-2.192 2.055-2.192h2.878M5.611 3.692h28.777c1.136 0 2.056.981 2.056 2.192v33.45c0 9.374-7.125 16.973-15.914 16.973h-1.06c-8.79 0-15.915-7.599-15.915-16.972V5.885c0-1.212.92-2.193 2.056-2.193m4.11 15.785h20.556c1.136 0 2.056.981 2.056 2.192v17.807c0 6.874-5.225 12.447-11.67 12.447h-1.327c-6.445 0-11.67-5.573-11.67-12.447V21.67c0-1.21.92-2.192 2.056-2.192m13.567 7.892c0 1.937-1.472 3.508-3.288 3.508-1.817 0-3.29-1.57-3.29-3.508s1.473-3.507 3.29-3.507 3.288 1.57 3.288 3.507","viewW":40,"viewH":60}},{"id":"bidet_built_in","group":"sanitary","category":"bidet","w":40,"h":50,"art":{"d":"M17.318 12.182h-8.06c-.88 0-1.592.74-1.592 1.654v16.126c0 6.698 5.225 12.129 11.67 12.129h1.327c6.445 0 11.67-5.43 11.67-12.13V13.837c0-.914-.713-1.654-1.591-1.654H22.68m-.215-8.545v9.827c0 1.18-.92 2.136-2.055 2.136h-.822c-1.136 0-2.056-.956-2.056-2.136V3.637m10.689 8.545V3.637m-16.445 0v8.545M5.611 3.637h28.777c1.136 0 2.056.956 2.056 2.136v24.051c0 9.135-7.125 16.54-15.914 16.54h-1.06c-8.79 0-15.915-7.405-15.915-16.54V5.773c0-1.18.92-2.136 2.056-2.136M23.289 23.29c0 1.888-1.473 3.418-3.29 3.418s-3.288-1.53-3.288-3.418 1.472-3.418 3.289-3.418c1.816 0 3.288 1.53 3.288 3.418","viewW":40,"viewH":50}},{"id":"kitchen_sink","group":"sanitary","category":"kitchen_sink","w":60,"h":50,"art":{"d":"M38.188 8.7h10.598c1.211 0 2.193.956 2.193 2.136v28.2c0 1.18-.982 2.136-2.193 2.136H11.08c-1.21 0-2.192-.956-2.192-2.136v-28.2c0-1.18.981-2.136 2.192-2.136h10.599m10.885-5.128V15.11c0 1.18-.981 2.136-2.192 2.136h-.877c-1.21 0-2.192-.957-2.192-2.136V3.572m5.261 7.691h3.07c1.21 0 2.192-.956 2.192-2.136v-.855c0-1.18-.982-2.136-2.192-2.136h-3.07m-5.261 5.127h-3.07c-1.21 0-2.192-.956-2.192-2.136v-.855c0-1.18.982-2.136 2.193-2.136h3.069M5.817 46.299h48.231c1.21 0 2.192-.956 2.192-2.136V5.709c0-1.18-.981-2.137-2.192-2.137H5.818c-1.211 0-2.193.957-2.193 2.137v38.454c0 1.18.982 2.136 2.192 2.136M33.44 25.79c0 1.888-1.57 3.418-3.507 3.418s-3.508-1.53-3.508-3.418c0-1.887 1.57-3.418 3.508-3.418s3.507 1.53 3.507 3.418","viewW":60,"viewH":50}},{"id":"kitchen_sink_double","group":"sanitary","category":"kitchen_sink","w":90,"h":50,"art":{"d":"M53.173 12.182c-.468 0-.847.354-.847.79s.38.79.847.79zm21.979 1.58c.467 0 .846-.353.846-.79 0-.436-.379-.79-.846-.79zM6.01 3.572v.79h77.842v-1.58H6.01zM86.14 5.71h-.847v38.454h1.694V5.709zM83.85 46.3v-.79H6.01v1.58h77.842zM3.72 44.163h.847V5.709H2.873v38.454zm2.29 2.136v-.79c-.797 0-1.443-.603-1.443-1.346H2.873c0 1.616 1.404 2.926 3.137 2.926zm80.131-2.136h-.847c0 .743-.646 1.346-1.442 1.346v1.58c1.732 0 3.136-1.31 3.136-2.926zm-2.29-40.59v.79c.797 0 1.443.602 1.443 1.346h1.694c0-1.617-1.404-2.927-3.136-2.927zm-77.841 0v-.79c-1.733 0-3.137 1.31-3.137 2.926h1.694c0-.744.646-1.347 1.443-1.347zm5.494 37.599v.79h28.39v-1.58h-28.39zm30.68-2.136h.846v-28.2h-1.694v28.2zm-32.97-28.2h-.846v28.2h1.694v-28.2zM39.895 8.7v-.79h-5.669v1.58h5.669zm-22.721 0v-.79h-5.669v1.58h5.669zm-7.958 2.136h.847c0-.744.645-1.346 1.442-1.346V7.91c-1.732 0-3.136 1.31-3.136 2.926zm32.968 0h.847c0-1.616-1.404-2.927-3.136-2.927v1.58c.797 0 1.442.603 1.442 1.347zm-2.29 30.336v.79c1.733 0 3.137-1.31 3.137-2.926h-1.694c0 .743-.645 1.346-1.442 1.346zm-28.389 0v-.79c-.797 0-1.442-.603-1.442-1.346H8.368c0 1.616 1.404 2.926 3.136 2.926zm13.737-23.927v.79h.916v-1.58h-.916zm3.205-2.136h.847V3.572H27.6V15.11zM22.952 3.572h-.847V15.11h1.693V3.572zm3.205 13.673v.79c1.732 0 3.136-1.31 3.136-2.926H27.6c0 .743-.646 1.346-1.443 1.346zm-.916 0v-.79c-.797 0-1.443-.603-1.443-1.346h-1.693c0 1.616 1.404 2.926 3.136 2.926zm3.205-5.982v.79h3.206v-1.58h-3.206zm5.495-2.136h.847v-.855h-1.694v.855zm-2.29-2.991v-.79h-3.205v1.58h3.206zm2.29 2.136h.847c0-1.616-1.404-2.926-3.136-2.926v1.58c.796 0 1.442.603 1.442 1.346zm-2.29 2.991v.79c1.733 0 3.137-1.31 3.137-2.926h-1.694c0 .743-.646 1.346-1.442 1.346zm-11.905 0v.79h3.206v-1.58h-3.206zm3.206-5.127v-.79h-3.206v1.58h3.206zm-5.495 2.136h-.847v.855h1.694v-.855zm2.29-2.136v-.79c-1.733 0-3.137 1.31-3.137 2.926h1.694c0-.743.646-1.346 1.442-1.346zm0 5.127v-.79c-.797 0-1.443-.603-1.443-1.346H16.61c0 1.616 1.404 2.926 3.136 2.926zm9.615 14.527h-.847c0 1.452-1.26 2.628-2.816 2.628v1.58c2.49 0 4.51-1.884 4.51-4.208zM25.7 29.208v-.79c-1.555 0-2.816-1.176-2.816-2.628H21.19c0 2.324 2.02 4.209 4.51 4.209zm-3.663-3.418h.847c0-1.451 1.26-2.628 2.816-2.628v-1.58c-2.49 0-4.51 1.884-4.51 4.208zm3.663-3.418v.79c1.555 0 2.816 1.177 2.816 2.628h1.694c0-2.324-2.02-4.208-4.51-4.208zm24.268 18.8v.79h28.39v-1.58h-28.39zm30.68-2.136h.846v-28.2H79.8v28.2zM78.356 8.7v-.79h-28.39v1.58h28.39zm-30.68 2.136h-.846v28.2h1.694v-28.2zm2.29-2.136v-.79c-1.732 0-3.136 1.31-3.136 2.926h1.694c0-.744.646-1.346 1.442-1.346zm30.68 2.136h.846c0-1.616-1.404-2.927-3.136-2.927v1.58c.797 0 1.443.603 1.443 1.347zm-2.29 30.336v.79c1.732 0 3.136-1.31 3.136-2.926H79.8c0 .743-.646 1.346-1.443 1.346zm-28.39 0v-.79c-.796 0-1.442-.603-1.442-1.346H46.83c0 1.616 1.404 2.926 3.136 2.926zm3.206-28.2v.79h21.979v-1.58h-21.98z","viewW":90,"viewH":50}}] as const; +// Lazy chunk (#474): imported dynamically by furniture-art-runtime.ts and +// statically by the editor. The fingerprint token is replaced at build time +// so a chunk from another build is rejected instead of half-applied. +export const FURNITURE_ART_FINGERPRINT = '__HOUSEPLAN_SOURCE_FINGERPRINT__'; +export const GENERATED_FURNITURE_ART: Readonly> = {"coffee_table":{"d":"M3.84 5.884c0-1.21 1.048-2.192 2.34-2.192h107.64c1.293 0 2.34.981 2.34 2.192v48.23c0 1.212-1.047 2.193-2.34 2.193H6.18c-1.292 0-2.34-.981-2.34-2.192z M103.056 15.093V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.078v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m-93.6-35.077V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.078v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877","viewW":120,"viewH":60},"coffee_table_round":{"d":"M3.765 40a36.235 36.235 0 1 0 72.47 0 36.235 36.235 0 1 0-72.47 0 m56.26 26.96-3.843-3.843a.906.906 0 0 1 0-1.28l3.843-3.844a.906.906 0 0 1 1.281 0l3.844 3.843a.906.906 0 0 1 0 1.281l-3.844 3.844a.906.906 0 0 1-1.28 0m-.001 34.66-3.843-3.843a.906.906 0 0 1 0-1.281l3.843-3.844a.906.906 0 0 1 1.281 0l3.843 3.844a.906.906 0 0 1 0 1.28l-3.843 3.844a.906.906 0 0 1-1.281 0m-34.423-34.66-3.843-3.843a.906.906 0 0 1 0-1.281l3.843-3.844a.906.906 0 0 1 1.281 0l3.844 3.844a.906.906 0 0 1 0 1.28l-3.844 3.844a.906.906 0 0 1-1.28 0m-.001 34.66-3.843-3.843a.906.906 0 0 1 0-1.281l3.843-3.843a.906.906 0 0 1 1.281 0l3.844 3.843a.906.906 0 0 1 0 1.281l-3.844 3.843a.906.906 0 0 1-1.28 0","viewW":80,"viewH":80},"coffee_table_oval":{"d":"M3.84 30c0-14.53 12.572-26.308 28.08-26.308h56.16c15.509 0 28.08 11.778 28.08 26.308s-12.571 26.307-28.08 26.307H31.92C16.412 56.307 3.84 44.53 3.84 30 M80.592 15.093V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.077v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877M31.92 15.093V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.876h-5.616a.936.877 0 0 1-.936-.876m0 35.077v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.876h-5.616a.936.877 0 0 1-.936-.876","viewW":120,"viewH":60},"coffee_table_rounded":{"d":"M3.84 12.461c0-4.843 4.19-8.77 9.36-8.77h93.6c5.17 0 9.36 3.927 9.36 8.77v35.077c0 4.843-4.19 8.77-9.36 8.77H13.2c-5.17 0-9.36-3.927-9.36-8.77z M103.056 15.093V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.078v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m-93.6-35.077V9.83a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877m0 35.078v-5.262a.936.877 0 0 1 .936-.877h5.616a.936.877 0 0 1 .936.877v5.262a.936.877 0 0 1-.936.877h-5.616a.936.877 0 0 1-.936-.877","viewW":120,"viewH":60},"table_dining":{"d":"M3.879 6.08c0-1.265 1.065-2.29 2.378-2.29h147.484c1.314 0 2.38 1.025 2.38 2.29v77.84c0 1.265-1.066 2.29-2.38 2.29H6.257c-1.313 0-2.378-1.025-2.378-2.29z M138.994 19.358v-5.495a.952.916 0 0 1 .951-.915h5.71a.952.916 0 0 1 .95.915v5.495a.952.916 0 0 1-.95.916h-5.71a.952.916 0 0 1-.951-.916m-.001 56.778v-5.495a.952.916 0 0 1 .952-.915h5.709a.952.916 0 0 1 .951.915v5.495a.952.916 0 0 1-.951.916h-5.71a.952.916 0 0 1-.95-.916m-125.6-56.778v-5.495a.952.916 0 0 1 .951-.916h5.71a.952.916 0 0 1 .95.916v5.495a.952.916 0 0 1-.95.915h-5.71a.952.916 0 0 1-.951-.915m-.001 56.779v-5.495a.952.916 0 0 1 .952-.916h5.709a.952.916 0 0 1 .951.916v5.495a.952.916 0 0 1-.951.915h-5.71a.952.916 0 0 1-.95-.915","viewW":160,"viewH":90},"table_round":{"d":"M3.826 55a51.174 51.174 0 1 0 102.349 0A51.174 51.174 0 1 0 3.826 55 m81.005 32.303-3.947-3.947a.93.93 0 0 1 0-1.316l3.947-3.948a.93.93 0 0 1 1.316 0l3.948 3.948a.93.93 0 0 1 0 1.316l-3.948 3.947a.93.93 0 0 1-1.316 0m0 54.897-3.947-3.948a.93.93 0 0 1 0-1.316l3.947-3.947a.93.93 0 0 1 1.316 0l3.948 3.947a.93.93 0 0 1 0 1.316L82.32 87.2a.93.93 0 0 1-1.316 0M27.04 32.304l-3.947-3.948a.93.93 0 0 1 0-1.315l3.948-3.948a.93.93 0 0 1 1.315 0l3.948 3.948a.93.93 0 0 1 0 1.315l-3.948 3.948a.93.93 0 0 1-1.315 0m-.001 54.604-3.947-3.948a.93.93 0 0 1 0-1.316l3.948-3.947a.93.93 0 0 1 1.315 0l3.948 3.947a.93.93 0 0 1 0 1.316l-3.948 3.948a.93.93 0 0 1-1.315 0","viewW":110,"viewH":110},"table_dining_oval":{"d":"M3.892 50c0-25.51 21.418-46.19 47.838-46.19h76.54c26.42 0 47.839 20.68 47.839 46.19S154.69 96.19 128.27 96.19H51.73C25.31 96.19 3.892 75.51 3.892 50 M122.53 19.514V13.97a.957.924 0 0 1 .956-.924h5.74a.957.924 0 0 1 .958.924v5.543a.957.924 0 0 1-.957.924h-5.74a.957.924 0 0 1-.958-.924m.001 66.516v-5.543a.957.924 0 0 1 .957-.924h5.74a.957.924 0 0 1 .957.924v5.543a.957.924 0 0 1-.957.924h-5.74a.957.924 0 0 1-.957-.924M49.816 19.515v-5.543a.957.924 0 0 1 .957-.924h5.74a.957.924 0 0 1 .958.924v5.542a.957.924 0 0 1-.957.924h-5.74a.957.924 0 0 1-.958-.924m0 66.516v-5.543a.957.924 0 0 1 .957-.924h5.74a.957.924 0 0 1 .957.924v5.543a.957.924 0 0 1-.957.923h-5.74a.957.924 0 0 1-.957-.924","viewW":180,"viewH":100},"table_dining_rounded":{"d":"M3.879 17.527c0-7.587 6.39-13.737 14.272-13.737h123.696c7.883 0 14.273 6.15 14.273 13.737v54.947c0 7.587-6.39 13.737-14.273 13.737H18.151c-7.882 0-14.272-6.15-14.272-13.737z M138.994 19.358v-5.495a.952.916 0 0 1 .951-.915h5.71a.952.916 0 0 1 .95.915v5.495a.952.916 0 0 1-.95.916h-5.71a.952.916 0 0 1-.951-.916m-.001 56.778v-5.495a.952.916 0 0 1 .952-.915h5.709a.952.916 0 0 1 .951.915v5.495a.952.916 0 0 1-.951.916h-5.71a.952.916 0 0 1-.95-.916m-125.6-56.778v-5.495a.952.916 0 0 1 .951-.916h5.71a.952.916 0 0 1 .95.916v5.495a.952.916 0 0 1-.95.915h-5.71a.952.916 0 0 1-.951-.915m-.001 56.779v-5.495a.952.916 0 0 1 .952-.916h5.709a.952.916 0 0 1 .951.916v5.495a.952.916 0 0 1-.951.915h-5.71a.952.916 0 0 1-.95-.915","viewW":160,"viewH":90},"desk":{"d":"M3.862 5.967c0-1.234 1.057-2.234 2.362-2.234h127.552c1.305 0 2.362 1 2.362 2.234v58.066c0 1.234-1.057 2.233-2.362 2.233H6.224c-1.305 0-2.362-1-2.362-2.233z M9.531 15.346v-5.36a.945.893 0 0 1 .945-.893h5.67a.945.893 0 0 1 .944.893v5.36a.945.893 0 0 1-.945.894h-5.669a.945.893 0 0 1-.945-.894m113.379.001v-5.36a.945.893 0 0 1 .945-.894h5.67a.945.893 0 0 1 .944.894v5.36a.945.893 0 0 1-.945.893h-5.669a.945.893 0 0 1-.945-.893M9.53 60.013v-5.36a.945.893 0 0 1 .946-.893h5.669a.945.893 0 0 1 .945.893v5.36a.945.893 0 0 1-.945.894h-5.67a.945.893 0 0 1-.944-.894m113.38.001v-5.36a.945.893 0 0 1 .945-.894h5.669a.945.893 0 0 1 .945.894v5.36a.945.893 0 0 1-.945.893h-5.67a.945.893 0 0 1-.944-.893m-97.318-2.681h88.814","viewW":140,"viewH":70},"desk_corner":{"d":"M156.12 66.202a2.38 2.38 0 0 1-2.379 2.38H94.272c-13.138 0-23.788 10.65-23.788 23.787v61.372a2.38 2.38 0 0 1-2.379 2.38H6.257a2.38 2.38 0 0 1-2.378-2.38V6.257A2.38 2.38 0 0 1 6.257 3.88h147.484a2.38 2.38 0 0 1 2.38 2.378z M9.588 16.249v-5.71a.95.95 0 0 1 .951-.95h5.71a.95.95 0 0 1 .95.95v5.71a.95.95 0 0 1-.95.951h-5.71a.95.95 0 0 1-.951-.951m133.212.001v-5.71a.95.95 0 0 1 .951-.951h5.71a.95.95 0 0 1 .95.951v5.71a.95.95 0 0 1-.95.951h-5.71a.95.95 0 0 1-.951-.951m0 45.672v-5.71a.95.95 0 0 1 .952-.951h5.709a.95.95 0 0 1 .951.951v5.71a.95.95 0 0 1-.951.951h-5.71a.95.95 0 0 1-.95-.951M9.587 149.46v-5.708a.95.95 0 0 1 .952-.952h5.709a.95.95 0 0 1 .951.952v5.709a.95.95 0 0 1-.951.951h-5.71a.95.95 0 0 1-.951-.951m47.576 0v-5.709a.95.95 0 0 1 .952-.951h5.709a.95.95 0 0 1 .951.951v5.71a.95.95 0 0 1-.951.95h-5.71a.95.95 0 0 1-.951-.95m51.382-90.396H95.569a34.6 34.6 0 0 0-34.6 34.6v12.976","viewW":160,"viewH":160},"chair":{"d":"M39.452 12.433H10.548a4.398 4.398 0 1 1 0-8.796h28.904a4.398 4.398 0 0 1 0 8.796m-28.904 0H8.035a4.4 4.4 0 0 0-4.398 4.399V40.08a6.283 6.283 0 0 0 6.283 6.284h30.16a6.283 6.283 0 0 0 6.284-6.284V16.832c0-2.43-1.97-4.399-4.399-4.399h-2.513","viewW":50,"viewH":50},"chair_bar":{"d":"M38.579 17.168c1.326 2.526 1.947 6.015 1.947 9.071 0 10.018-8.07 18.139-18.025 18.139S4.475 36.257 4.475 26.239c0-3.056.586-6.552 1.912-9.078m32.192.007a3.59 3.59 0 0 1-3.333-.976m3.333.976a3.6 3.6 0 0 0 1.765-.976m-33.827.996-.13-.027a3.6 3.6 0 0 1-1.731-.969m30.59 0a18 18 0 0 0-5.848-3.932 17.93 17.93 0 0 0-13.796 0 18 18 0 0 0-5.848 3.932 3.59 3.59 0 0 1-3.237.996m28.729-.996a3.59 3.59 0 0 0 5.098 0m-33.827.996a3.6 3.6 0 0 1-1.861-.996 3.644 3.644 0 0 1 0-5.13 25.2 25.2 0 0 1 8.187-5.505A25.1 25.1 0 0 1 22.5 3.623a25.1 25.1 0 0 1 9.657 1.934 25.2 25.2 0 0 1 8.187 5.505 3.644 3.644 0 0 1 0 5.13","viewW":45,"viewH":48},"armchair":{"d":"M75.702 13.011q.012-.225.012-.453c0-4.843-3.917-8.768-8.748-8.768H23.034c-4.83 0-8.747 3.925-8.747 8.768q0 .228.011.453M77.132 72.09q.59.091 1.206.092c4.348 0 7.873-3.533 7.873-7.892V20.45c0-4.359-3.525-7.892-7.873-7.892-.924 0-1.812.16-2.636.453a7.89 7.89 0 0 0-5.237 7.438v.148m0 0a8.7 8.7 0 0 1-3.499.73H23.034a8.7 8.7 0 0 1-3.499-.73m50.93 0V64.29a7.89 7.89 0 0 0 6.667 7.8M14.298 13.01a7.89 7.89 0 0 1 5.237 7.438v.148m0 0V64.29a7.89 7.89 0 0 1-6.666 7.8q-.59.091-1.206.092c-4.348 0-7.873-3.533-7.873-7.892V20.45c0-4.359 3.525-7.892 7.873-7.892.924 0 1.811.16 2.635.453M77.132 72.09c-1.585 8.05-8.667 14.12-17.164 14.12H30.032c-8.496 0-15.578-6.07-17.163-14.12","viewW":90,"viewH":90},"armchair_office":{"d":"M56.968 18.845q0-.368-.05-.72M49.051 13.8H15.95a5.04 5.04 0 0 1-5.038-5.043 5.04 5.04 0 0 1 5.038-5.043h33.103a5.04 5.04 0 0 1 5.038 5.043 5.04 5.04 0 0 1-5.038 5.043m-33.103 0h-2.88a5.04 5.04 0 0 0-4.986 4.323M49.052 13.8h2.879a5.04 5.04 0 0 1 4.986 4.324m.051 24.826a4.32 4.32 0 0 0 4.318-4.323v-16.18a4.32 4.32 0 0 0-4.369-4.322m.051 24.826a4.32 4.32 0 0 1-4.318-4.323V22.447a4.32 4.32 0 0 1 4.267-4.322m-11.84 37.24h4.695c.736 0 1.446-.111 2.115-.317a7.21 7.21 0 0 0 5.081-6.889v-5.208M8.084 18.124h-.051a4.32 4.32 0 0 0-4.318 4.323v16.18a4.32 4.32 0 0 0 4.318 4.324 4.32 4.32 0 0 0 4.317-4.323V22.447a4.32 4.32 0 0 0-4.266-4.323m11.935 37.24h-4.79a7.2 7.2 0 0 1-2.04-.294 7.21 7.21 0 0 1-5.156-6.91v-5.21m37.045 12.414 5.177 5.183c.969.97 2.534.987 3.524.038a2.526 2.526 0 0 0 .038-3.605l-1.93-1.932m-6.81.316H20.02m-6.83-.294-1.909 1.91c-.998 1-.98 2.627.038 3.605.99.949 2.555.932 3.524-.038l5.177-5.183","viewW":65,"viewH":65},"sofa":{"d":"M90 19.365v57.111m0-57.11V7.683m0 11.681c0 2.151-1.836 3.894-4.1 3.894H30.544a10.7 10.7 0 0 1-4.136-.825M90 19.365c0 2.151 1.836 3.894 4.1 3.894h55.356c1.472 0 2.871-.294 4.137-.825M90 76.476c0 5.376-4.59 9.735-10.25 9.735H30.543c-5.266 0-9.605-3.772-10.185-8.625M90 76.476c0 5.376 4.59 9.735 10.25 9.735h49.206c5.266 0 9.605-3.772 10.185-8.625M90 7.684c0-2.15-1.837-3.894-4.101-3.894H30.544c-5.661 0-10.25 4.358-10.25 9.735q0 .416.036.825M90 7.684c0-2.15 1.836-3.894 4.1-3.894h55.356c5.661 0 10.25 4.358 10.25 9.735q0 .416-.036.825m0 0a10.7 10.7 0 0 1 4.137-.825h2.05c5.662 0 10.252 4.358 10.252 9.734v45.43c0 5.376-4.59 9.734-10.251 9.734h-2.05c-1.484 0-2.894-.3-4.167-.837m0 0c-3.585-1.517-6.084-4.93-6.084-8.898V23.26q0-.417.036-.825c.32-3.622 2.728-6.68 6.077-8.084m-139.34 0c3.35 1.404 5.758 4.462 6.078 8.084q.036.408.036.825v45.43c0 3.967-2.5 7.38-6.085 8.897a10.7 10.7 0 0 1-4.166.837h-2.05c-5.662 0-10.251-4.358-10.251-9.735V23.26c0-5.376 4.59-9.734 10.25-9.734h2.05c1.473 0 2.872.294 4.138.825","viewW":180,"viewH":90},"sofa_three_seat":{"d":"M86.553 18.593V76.96m0-58.366V7.491m0 11.102c0 2.044-1.762 3.701-3.935 3.701H29.496c-1.413 0-2.756-.28-3.97-.784m61.027-2.917c0 2.044 1.762 3.701 3.935 3.701h59.024c2.174 0 3.935-1.657 3.935-3.7M86.553 76.958c0 5.11-4.404 9.252-9.837 9.252h-47.22c-5.054 0-9.218-3.585-9.775-8.198m66.832-1.054c0 5.11 4.404 9.252 9.837 9.252h47.22c5.433 0 9.837-4.142 9.837-9.252m0-58.366V76.96m0-58.366V7.491m0 11.102c0 2.044 1.762 3.701 3.936 3.701h53.122c1.413 0 2.756-.28 3.97-.784m-61.028 55.449c0 5.11 4.405 9.252 9.838 9.252h47.22c5.054 0 9.218-3.585 9.775-8.198M86.553 7.491c0-2.044-1.762-3.701-3.935-3.701H29.496c-5.433 0-9.838 4.142-9.838 9.252q0 .396.035.784m66.86-6.335c0-2.044 1.762-3.701 3.935-3.701h59.024c2.174 0 3.935 1.657 3.935 3.7m0 0c0-2.043 1.762-3.7 3.936-3.7h53.122c5.433 0 9.838 4.142 9.838 9.252 0 .258.022.517 0 .77m-.063 64.201c1.22.512 2.574.796 3.998.796h1.967c5.433 0 9.837-4.142 9.837-9.252V22.294c0-5.11-4.404-9.252-9.837-9.252h-1.967c-5.153 0-9.38 3.725-9.803 8.468q-.036.387-.035.784v47.263c0 3.771 2.399 7.015 5.84 8.456M19.693 13.826a10.3 10.3 0 0 0-3.97-.784h-1.967c-5.433 0-9.838 4.142-9.838 9.252v47.263c0 5.11 4.405 9.252 9.838 9.252h1.967c1.424 0 2.777-.284 3.998-.796 3.441-1.441 5.84-4.685 5.84-8.456V22.294a9 9 0 0 0-.035-.784c-.307-3.443-2.618-6.349-5.833-7.684","viewW":240,"viewH":90},"sofa_corner_right":{"d":"M93.673 20.687V83.69m0-63.004v-12.6m0 12.6c0 2.32-1.913 4.2-4.273 4.2H31.704a10.8 10.8 0 0 1-4.311-.89m66.28-3.31c0 2.32 1.914 4.2 4.274 4.2h64.106c2.36 0 4.274-1.88 4.274-4.2M93.673 83.692c0 5.8-4.783 10.501-10.684 10.501H31.704c-5.489 0-10.011-4.068-10.616-9.304m72.585-1.197c0 5.8 4.784 10.501 10.684 10.501h51.286c5.9 0 10.684-4.701 10.684-10.5m0-63.005V83.69m0-63.004v-12.6m0 12.6c0 2.32 1.914 4.2 4.273 4.2h57.696c1.534 0 2.993-.317 4.312-.89m-66.28 59.695v71.923c0 5.799 4.782 10.5 10.684 10.5h51.284c5.49 0 10.012-4.068 10.616-9.304V84.888M93.673 8.086c0-2.32-1.913-4.2-4.273-4.2H31.704c-5.9 0-10.684 4.7-10.684 10.5q0 .45.038.89m72.615-7.19c0-2.32 1.914-4.2 4.274-4.2h64.106c2.36 0 4.274 1.88 4.274 4.2m0 0c0-2.32 1.914-4.2 4.273-4.2h57.696c5.9 0 10.685 4.7 10.685 10.5 0 .293.024.587 0 .874m-.07 69.628c1.327.58 2.797.904 4.344.904h2.136c5.901 0 10.684-4.702 10.684-10.501V24.887c0-5.8-4.783-10.5-10.684-10.5h-2.136c-5.596 0-10.187 4.227-10.647 9.61q-.038.44-.038.89V75.29c0 4.28 2.605 7.961 6.342 9.597M21.059 15.276a10.8 10.8 0 0 0-4.312-.89H14.61c-5.9 0-10.684 4.701-10.684 10.5v50.405c0 5.8 4.783 10.5 10.684 10.5h2.137c1.546 0 3.016-.322 4.342-.903 3.737-1.636 6.342-5.317 6.342-9.597V24.887q0-.45-.037-.89c-.334-3.907-2.844-7.206-6.335-8.72","viewW":260,"viewH":170},"bed_single":{"d":"M3.79 14.024c0 5.59 4.318 10.122 9.645 10.122h63.13c5.328 0 9.646-4.532 9.646-10.122m-22.797 46.93V46.23c0-5.082-3.926-9.201-8.769-9.201h-19.29c-4.842 0-8.768 4.12-8.768 9.201v14.723m-22.797 0h82.42m0 22.085H3.79m8.768 113.06h64.885c4.842 0 8.768-4.12 8.768-9.202V13.104c0-5.082-3.926-9.202-8.768-9.202H12.558c-4.843 0-8.768 4.12-8.768 9.202v173.792c0 5.082 3.925 9.202 8.768 9.202","viewW":90,"viewH":200},"bed_double":{"d":"M3.879 14.073c0 5.618 4.516 10.172 10.088 10.172h132.065c5.571 0 10.088-4.554 10.088-10.172m-81.165 47.16V46.438c0-5.107-4.106-9.247-9.171-9.247H45.607c-5.065 0-9.17 4.14-9.17 9.247v14.795m89.877 0V46.438c0-5.107-4.107-9.247-9.172-9.247H96.966c-5.065 0-9.171 4.14-9.171 9.247v14.795m-83.916 0H156.12m0 22.192H3.88m9.17 112.673h133.9c5.065 0 9.171-4.14 9.171-9.247V13.15c0-5.107-4.106-9.247-9.171-9.247H13.05c-5.064 0-9.17 4.14-9.17 9.247v173.7c0 5.107 4.106 9.247 9.17 9.247","viewW":160,"viewH":200},"nightstand":{"d":"M5.773 3.555h38.454a2.136 2.056 0 0 1 2.137 2.056v28.777a2.136 2.056 0 0 1-2.137 2.056H5.773a2.136 2.056 0 0 1-2.136-2.056V5.611a2.136 2.056 0 0 1 2.136-2.056","viewW":50,"viewH":40},"cabinet_tv":{"d":"M56.772 17.88h5.315m0 0h5.315m-5.315 0v9.214m9.832-9.214 5.315 9.45 5.314-9.45M6.224 41.4h127.552c1.305 0 2.362-.94 2.362-2.1V5.7c0-1.16-1.057-2.1-2.362-2.1H6.224c-1.305 0-2.362.94-2.362 2.1v33.6c0 1.16 1.057 2.1 2.362 2.1","viewW":140,"viewH":45},"cabinet_shoe":{"d":"m39.722 16.231 1.505-1.596m1.134 3.15 1.53-1.738M6.03 31.5h67.94c1.251 0 2.265-.895 2.265-2v-24c0-1.105-1.014-2-2.264-2H6.03c-1.251 0-2.265.895-2.265 2v24c0 1.105 1.014 2 2.265 2m41.966-14.305L46.92 17.1a3.4 3.4 0 0 1-1.813-.706l-4.583-3.62c-1.264-1-3.277-.326-3.475 1.161-.185 1.39-1.983 2.1-3.28 1.299l-1.532-.947c-.968-.513-2.2.103-2.2 1.1v3.463c0 1.559 1.43 2.823 3.196 2.823h14.51c1.404 0 2.542-1.005 2.542-2.245 0-1.153-.99-2.118-2.289-2.233","viewW":80,"viewH":35},"cabinet_sink":{"d":"M3.765 5.773c0-1.18 1.014-2.136 2.265-2.136h67.94c1.251 0 2.265.956 2.265 2.136v38.454c0 1.18-1.014 2.137-2.264 2.137H6.03c-1.251 0-2.265-.957-2.265-2.137z M36.088 32.135c2.525 1.88 6.205 1.88 8.73 0s3.167-5.101 1.52-7.637l-5.879-8.043-5.893 8.043c-1.644 2.536-1.003 5.755 1.522 7.637","viewW":80,"viewH":50},"bookshelf":{"d":"M57.12 20.488H45.473c-.514 0-1.008.124-1.372.345s-.568.52-.568.832m4.076-8.236h5.434M6.119 3.5h87.762c1.276 0 2.31.895 2.31 2v24c0 1.105-1.034 2-2.31 2H6.12c-1.275 0-2.31-.895-2.31-2v-24c0-1.105 1.035-2 2.31-2m51 6.4v14.118H45.474a2.04 2.04 0 0 1-1.372-.517 1.7 1.7 0 0 1-.568-1.248V11.665c0-.468.204-.917.568-1.248a2.04 2.04 0 0 1 1.372-.517z","viewW":100,"viewH":35},"wall_unit":{"d":"M6.336 41.4h227.328a2.418 2.1 0 0 0 2.418-2.1V5.7a2.418 2.1 0 0 0-2.418-2.1H6.336a2.418 2.1 0 0 0-2.418 2.1v33.6a2.418 2.1 0 0 0 2.418 2.1m43.744-5.88V9.48m46.432 26.04V9.48m46.433 26.04V9.48m46.433 26.04V9.48","viewW":240,"viewH":45},"wardrobe":{"d":"M93.87 20.25a3.3 3.3 0 0 0-1.072-2.407 3.8 3.8 0 0 0-2.586-.997c-.97 0-1.9.358-2.587.997a3.3 3.3 0 0 0-1.071 2.407c0 2.838 1.225 5.107 3.658 6.81h-.015m0 0 14.58 7.537c.57.295 1.046.726 1.377 1.25.331.523.505 1.12.505 1.727v1.401a3.3 3.3 0 0 1-1.071 2.407 3.8 3.8 0 0 1-2.587.998H77.393a3.8 3.8 0 0 1-2.586-.998 3.3 3.3 0 0 1-1.072-2.407v-1.4c0-.608.174-1.205.505-1.728a3.55 3.55 0 0 1 1.377-1.25zM6.284 3.691h167.433c1.32 0 2.392.981 2.392 2.192v48.23c0 1.212-1.071 2.193-2.392 2.193H6.284c-1.321 0-2.392-.981-2.392-2.192V5.885c0-1.212 1.07-2.193 2.392-2.193","viewW":180,"viewH":60},"kitchen_floor":{"d":"M3.692 5.884c0-1.21.981-2.192 2.192-2.192h48.23c1.212 0 2.193.981 2.193 2.192v48.23a2.19 2.19 0 0 1-2.192 2.193H5.885a2.19 2.19 0 0 1-2.193-2.192z","viewW":60,"viewH":60},"kitchen_floor_corner":{"d":"M45.944 41.767a2.29 2.29 0 0 0 2.29 2.29H83.92a2.29 2.29 0 0 1 2.29 2.29V83.92a2.29 2.29 0 0 1-2.29 2.29H6.08a2.29 2.29 0 0 1-2.29-2.29V6.08a2.29 2.29 0 0 1 2.29-2.29h37.576a2.29 2.29 0 0 1 2.29 2.29z","viewW":90,"viewH":90},"kitchen_wall":{"d":"m4.444 31.033 50.75-27.007m-50.752-.06 50.75 27.008M5.884 31.5h48.23c1.212 0 2.193-.895 2.193-2v-24c0-1.105-.981-2-2.192-2H5.885c-1.212 0-2.193.895-2.193 2v24c0 1.105.981 2 2.192 2","viewW":60,"viewH":35},"kitchen_wall_corner":{"d":"M3.772 29.59 29.88 4.383M4.57 55.43 55.43 30M4.175 4.383l26.701 23.863m-27.184.877L55.43 55.43M28.41 3.692H5.884c-1.21 0-2.192.981-2.192 2.192v48.23c0 1.212.981 2.193 2.192 2.193h48.23a2.19 2.19 0 0 0 2.193-2.192V31.589c0-1.21-.981-2.192-2.192-2.192h-21.32a2.19 2.19 0 0 1-2.193-2.192V5.885a2.19 2.19 0 0 0-2.192-2.193","viewW":60,"viewH":60},"shelf_floor":{"d":"M6.12 31.5h87.76a2.31 2 0 0 0 2.31-2v-24a2.31 2 0 0 0-2.31-2H6.12a2.31 2 0 0 0-2.31 2v24a2.31 2 0 0 0 2.31 2 M9.089 25.933c-.494.112-.776.546-.63.97s.664.675 1.157.564l-.263-.767zM90.912 9.067c.493-.112.775-.546.63-.97s-.664-.675-1.158-.564l.264.767zM11.875 26.956c.493-.112.775-.546.63-.97s-.664-.676-1.158-.564l.264.767zm3.988-2.556c-.493.112-.775.546-.63.969s.664.676 1.158.564l-.264-.766zm5.045.511c.493-.112.775-.545.63-.969s-.664-.676-1.158-.564l.264.766zm3.988-2.555c-.493.111-.775.545-.63.968.146.424.664.677 1.158.565l-.264-.767zm5.044.51c.494-.111.776-.545.63-.968-.145-.424-.664-.676-1.157-.565l.263.767zm3.99-2.555c-.495.112-.777.546-.63.97.145.423.663.675 1.157.563l-.264-.766zm5.043.511c.494-.112.776-.545.63-.969s-.664-.676-1.158-.564l.264.767zm3.989-2.555c-.494.111-.776.545-.63.969s.664.676 1.157.564l-.263-.767zm5.044.51c.494-.11.776-.545.63-.968-.146-.424-.664-.676-1.158-.565l.264.767zm3.989-2.555c-.494.112-.776.546-.63.97.145.423.664.675 1.157.564l-.264-.767zm5.044.511c.493-.111.775-.545.63-.969s-.664-.676-1.158-.564l.264.767zm3.988-2.555c-.493.112-.775.545-.63.969s.664.676 1.158.564l-.264-.767zm5.045.51c.493-.11.775-.545.63-.968-.146-.424-.664-.676-1.158-.564l.264.766zm3.988-2.555c-.493.112-.775.546-.63.97s.664.675 1.158.564l-.264-.767zm5.044.511c.494-.111.776-.545.63-.968-.145-.424-.664-.677-1.157-.565l.264.767zm3.99-2.555c-.494.112-.777.545-.63.969.145.423.663.676 1.157.564l-.264-.766zm5.043.511c.494-.112.776-.546.63-.969s-.664-.676-1.157-.564l.263.766zm3.989-2.556c-.494.112-.776.546-.63.97s.664.676 1.158.564l-.264-.767zM9.353 26.7l.263.767 2.259-.511-.264-.767-.264-.767-2.258.511zm6.774-1.533.264.766 4.517-1.022-.264-.767-.264-.766-4.517 1.022zm9.033-2.045.264.767 4.516-1.022-.264-.767-.263-.767-4.517 1.023zm9.033-2.044.264.766 4.516-1.022-.264-.766-.264-.767-4.516 1.022zm9.033-2.045.263.767 4.517-1.022-.264-.767-.264-.767-4.516 1.023zm9.032-2.044.264.767 4.517-1.023-.264-.766-.264-.767-4.516 1.022zm9.033-2.045.264.767 4.517-1.022-.264-.767-.264-.766-4.517 1.022zm9.033-2.044.264.767 4.516-1.023-.263-.766-.264-.767-4.517 1.022zm9.033-2.044.264.766 4.516-1.022-.264-.767-.263-.766-4.517 1.022zM88.39 8.81l.264.767 2.258-.511-.264-.767-.264-.767-2.258.511z M9.089 9.067c-.494-.112-.776-.546-.63-.97s.664-.675 1.157-.564l-.263.767zm81.823 16.866c.493.112.775.546.63.97s-.664.675-1.158.564l.264-.767zM11.875 8.044c.493.112.775.546.63.97s-.664.676-1.158.564l.264-.767zm3.988 2.556c-.493-.112-.775-.546-.63-.969s.664-.676 1.158-.564l-.264.766zm5.045-.511c.493.112.775.545.63.969s-.664.676-1.158.564l.264-.766zm3.988 2.555c-.493-.111-.775-.545-.63-.968.146-.424.664-.677 1.158-.565l-.264.767zm5.044-.51c.494.111.776.545.63.968-.145.424-.664.676-1.157.565l.263-.767zm3.99 2.555c-.495-.112-.777-.546-.63-.97.145-.423.663-.675 1.157-.563l-.264.766zm5.043-.511c.494.112.776.545.63.969s-.664.676-1.158.564l.264-.767zm3.989 2.555c-.494-.111-.776-.545-.63-.969s.664-.676 1.157-.564l-.263.767zm5.044-.51c.494.11.776.545.63.968-.146.424-.664.676-1.158.565l.264-.767zm3.989 2.555c-.494-.112-.776-.546-.63-.97.145-.423.664-.675 1.157-.564l-.264.767zm5.044-.511c.493.111.775.545.63.969s-.664.676-1.158.564l.264-.767zm3.988 2.555c-.493-.112-.775-.545-.63-.969s.664-.676 1.158-.564l-.264.767zm5.045-.51c.493.11.775.545.63.968-.146.424-.664.676-1.158.564l.264-.766zm3.988 2.555c-.493-.112-.775-.546-.63-.97s.664-.675 1.158-.564l-.264.767zm5.044-.511c.494.111.776.545.63.968-.145.424-.664.677-1.157.565l.264-.767zm3.99 2.555c-.494-.112-.777-.545-.63-.969.145-.423.663-.676 1.157-.564l-.264.766zm5.043-.511c.494.112.776.546.63.969s-.664.676-1.157.564l.263-.766zm3.989 2.556c-.494-.112-.776-.546-.63-.97s.664-.676 1.158-.564l-.264.767zM9.353 8.3l.263-.767 2.259.511-.264.767-.264.767-2.258-.511zm6.774 1.533.264-.766 4.517 1.022-.264.767-.264.766-4.517-1.022zm9.033 2.045.264-.767 4.516 1.022-.264.767-.263.767-4.517-1.023zm9.033 2.044.264-.766 4.516 1.022-.264.766-.264.767-4.516-1.022zm9.033 2.045.263-.767 4.517 1.022-.264.767-.264.767-4.516-1.023zm9.032 2.044.264-.767 4.517 1.023-.264.766-.264.767-4.516-1.022zm9.033 2.045.264-.767 4.517 1.022-.264.767-.264.766-4.517-1.022zm9.033 2.044.264-.767 4.516 1.023-.263.766-.264.767-4.517-1.022zm9.033 2.044.264-.766 4.516 1.022-.264.767-.263.766-4.517-1.022zm9.033 2.045.264-.767 2.258.511-.264.767-.264.767-2.258-.511z","viewW":100,"viewH":35},"shelf_wall":{"d":"M18.36 3.15v2.567c0 1.012-1.034 1.833-2.31 1.833h-.924c-1.275 0-2.309-.82-2.309-1.833V3.15m73.905 0v2.567c0 1.012-1.034 1.833-2.31 1.833h-.924c-1.275 0-2.31-.82-2.31-1.833V3.15m-75.29 0H93.65c1.276 0 2.31.82 2.31 1.833V19.65c0 1.012-1.034 1.833-2.31 1.833H5.888c-1.275 0-2.31-.82-2.31-1.833V4.983c0-1.012 1.035-1.833 2.31-1.833","viewW":100,"viewH":25},"cooktop_two":{"d":"M15 30.982v-1.71m3.086 5.128h1.542M15 39.527v-1.709M10.372 34.4h1.542M5.84 46.364h18.322c1.331 0 2.41-1.196 2.41-2.67V6.306c0-1.475-1.079-2.67-2.41-2.67H5.839c-1.331 0-2.41 1.195-2.41 2.67v37.386c0 1.475 1.079 2.67 2.41 2.67m14.56-29.91c0 3.304-2.417 5.982-5.4 5.982-2.981 0-5.4-2.678-5.4-5.981s2.419-5.982 5.4-5.982c2.983 0 5.4 2.678 5.4 5.982M18.858 34.4c0 2.36-1.727 4.273-3.857 4.273s-3.857-1.913-3.857-4.273S12.87 30.127 15 30.127s3.857 1.913 3.857 4.273","viewW":30,"viewH":50},"stove":{"d":"M41.4 35.261a.877.877 0 1 0-1.754 0zm4.384 6.138a.877.877 0 1 0 0-1.753zM41.4 44.03a.877.877 0 1 0-1.753 0zm-4.384-2.63a.877.877 0 1 0 0-1.754zM5.885 3.691v.877h48.23V2.815H5.885zm50.422 2.192h-.877v48.23h1.754V5.885zm-2.192 50.423v-.877H5.885v1.754h48.23zM3.692 54.115h.877V5.885H2.815v48.23zm2.192 2.192v-.877a1.315 1.315 0 0 1-1.315-1.315H2.815a3.07 3.07 0 0 0 3.07 3.069zm50.423-2.192h-.877c0 .726-.589 1.315-1.315 1.315v1.754a3.07 3.07 0 0 0 3.069-3.07zM54.115 3.692v.877c.726 0 1.315.589 1.315 1.315h1.754a3.07 3.07 0 0 0-3.07-3.069zm-48.23 0v-.877a3.07 3.07 0 0 0-3.07 3.07h1.754c0-.727.589-1.316 1.315-1.316zm19.73 36.83h-.877a5.26 5.26 0 0 1-5.262 5.262v1.754a7.015 7.015 0 0 0 7.016-7.015zm-6.139 6.139v-.877a5.26 5.26 0 0 1-5.261-5.261h-1.754a7.015 7.015 0 0 0 7.015 7.015zm-6.138-6.138h.877a5.26 5.26 0 0 1 5.261-5.262v-1.754a7.015 7.015 0 0 0-7.015 7.016zm6.138-6.139v.877a5.26 5.26 0 0 1 5.262 5.262h1.754a7.015 7.015 0 0 0-7.016-7.016zm27.185-14.908h-.877a5.26 5.26 0 0 1-5.261 5.262v1.754a7.015 7.015 0 0 0 7.015-7.016zm-6.138 6.139v-.877a5.26 5.26 0 0 1-5.262-5.262h-1.754a7.015 7.015 0 0 0 7.016 7.016zm-6.139-6.139h.877a5.26 5.26 0 0 1 5.262-5.261v-1.754a7.015 7.015 0 0 0-7.016 7.015zm6.139-6.138v.877a5.26 5.26 0 0 1 5.261 5.261h1.754a7.015 7.015 0 0 0-7.015-7.015zm4.384 27.185h-.877a3.51 3.51 0 0 1-3.507 3.507v1.754a5.26 5.26 0 0 0 5.261-5.261zm-4.384 4.384v-.877a3.51 3.51 0 0 1-3.508-3.507H35.26a5.26 5.26 0 0 0 5.262 5.261zm-4.385-4.384h.877a3.51 3.51 0 0 1 3.508-3.508V35.26a5.26 5.26 0 0 0-5.262 5.262zm4.385-4.385v.877a3.51 3.51 0 0 1 3.507 3.508h1.754a5.26 5.26 0 0 0-5.261-5.262zm0 .877h.876V35.26h-1.753v1.754zm3.508 3.508v.876h1.753v-1.753h-1.753zm-3.508 5.261h.876V44.03h-1.753v1.754zm-5.261-5.261v.876h1.753v-1.753h-1.753zm-9.647-21.047h-.877a5.26 5.26 0 0 1-5.262 5.262v1.754a7.015 7.015 0 0 0 7.016-7.016zm-6.139 6.139v-.877a5.26 5.26 0 0 1-5.261-5.262h-1.754a7.015 7.015 0 0 0 7.015 7.016zm-6.138-6.139h.877a5.26 5.26 0 0 1 5.261-5.261v-1.754a7.015 7.015 0 0 0-7.015 7.015zm6.138-6.138v.877a5.26 5.26 0 0 1 5.262 5.261h1.754a7.015 7.015 0 0 0-7.016-7.015z","viewW":60,"viewH":60},"tv":{"d":"M45.134 10.766H6.18c-1.292 0-2.34.848-2.34 1.894v2.68c0 1.045 1.048 1.893 2.34 1.893h38.954m0-6.467V5.288c0-1.046 1.048-1.894 2.34-1.894h26.704c1.292 0 2.34.848 2.34 1.894v5.478m-31.384 0h31.384m0 0h37.302c1.293 0 2.34.848 2.34 1.894v2.68c0 1.045-1.047 1.893-2.34 1.893H76.518m-31.384 0v5.479c0 1.046 1.048 1.894 2.34 1.894h26.704c1.292 0 2.34-.848 2.34-1.894v-5.479m-31.384 0h31.384","viewW":120,"viewH":28},"tv_wall":{"d":"M35.664 11.4c-.517 0-.936.269-.936.6s.419.6.936.6zm49.553 1.2c.517 0 .936-.269.936-.6s-.42-.6-.936-.6zM6.18 3v.6h107.64V2.4H6.18zm109.98 1.5h-.936v1.8h1.872V4.5zm-2.34 3.3v-.6H6.18v1.2h107.64zM3.84 6.3h.936V4.5H2.904v1.8zm2.34 1.5v-.6c-.775 0-1.404-.403-1.404-.9H2.904c0 1.16 1.467 2.1 3.276 2.1zm109.98-1.5h-.936c0 .497-.629.9-1.404.9v1.2c1.81 0 3.276-.94 3.276-2.1zM113.82 3v.6c.775 0 1.404.403 1.404.9h1.872c0-1.16-1.467-2.1-3.276-2.1zM6.18 3v-.6c-1.81 0-3.276.94-3.276 2.1h1.872c0-.497.629-.9 1.404-.9zm61.308 4.2h-.936V12h1.872V7.2zM52.512 12h.936V7.2h-1.872V12zm-16.848 0v.6h49.553v-1.2H35.664z","viewW":120,"viewH":15},"toilet":{"d":"M3.555 48.976c0 9.55 7.125 17.29 15.914 17.29h1.061c8.79 0 15.914-7.74 15.914-17.29V5.966c0-1.233-.92-2.233-2.056-2.233H5.611c-1.135 0-2.056 1-2.056 2.234z M7.666 49.12c0 7.003 5.225 12.68 11.67 12.68h1.327c6.445 0 11.67-5.677 11.67-12.68V31.873c0-1.233-.92-2.233-2.056-2.233H9.722c-1.135 0-2.056 1-2.056 2.233zM33.792 3.733c1.465 0 2.652 1.29 2.652 2.882v12.103c0 1.592-1.187 2.882-2.652 2.882H6.208c-1.465 0-2.653-1.29-2.653-2.882V6.615c0-1.591 1.188-2.882 2.653-2.882z M24.11 50.186c0 2.467-1.84 4.467-4.11 4.467s-4.111-2-4.111-4.467 1.84-4.466 4.11-4.466 4.112 2 4.112 4.466","viewW":40,"viewH":70},"toilet_built_in":{"d":"M3.555 34.56c0 9.263 7.125 16.774 15.914 16.774h1.061c8.79 0 15.914-7.51 15.914-16.775V5.833c0-1.196-.92-2.166-2.056-2.166H5.611c-1.135 0-2.056.97-2.056 2.166z M7.666 34.7c0 6.793 5.225 12.3 11.67 12.3h1.327c6.445 0 11.67-5.507 11.67-12.3V14.5c0-1.197-.92-2.167-2.056-2.167H9.722c-1.135 0-2.056.97-2.056 2.167z M24.11 35.733c0 2.394-1.84 4.334-4.11 4.334s-4.111-1.94-4.111-4.334 1.84-4.333 4.11-4.333 4.112 1.94 4.112 4.333","viewW":40,"viewH":55},"bathtub":{"d":"M3.885 6c0-1.243 1.068-2.25 2.386-2.25h157.458c1.318 0 2.386 1.007 2.386 2.25v63c0 1.243-1.068 2.25-2.386 2.25H6.27c-1.318 0-2.386-1.007-2.386-2.25z M13.428 37.5c0-13.669 11.75-24.75 26.243-24.75h90.658c14.493 0 26.243 11.081 26.243 24.75s-11.75 24.75-26.243 24.75H39.67c-14.493 0-26.243-11.081-26.243-24.75 M31.56 37.5c0 2.237-1.923 4.05-4.295 4.05s-4.294-1.813-4.294-4.05 1.923-4.05 4.294-4.05c2.372 0 4.295 1.813 4.295 4.05","viewW":170,"viewH":75},"bathtub_corner":{"d":"M3.862 6.224a2.36 2.36 0 0 1 2.362-2.362H133.97c1.197 0 2.168.97 2.168 2.168 0 71.857-58.251 130.108-130.108 130.108a2.17 2.17 0 0 1-2.168-2.168z M13.31 32.207c0-10.437 8.46-18.897 18.897-18.897h87.628a2.13 2.13 0 0 1 2.13 2.13c0 58.833-47.692 106.526-106.524 106.526a2.13 2.13 0 0 1-2.13-2.131z M32.207 27.483a4.724 4.724 0 1 1-9.449 0 4.724 4.724 0 0 1 9.449 0","viewW":140,"viewH":140},"bidet":{"d":"M22.466 3.692v10.085c0 1.21-.92 2.192-2.055 2.192h-.822c-1.136 0-2.056-.981-2.056-2.192V3.692m4.933 8.77h2.878c1.135 0 2.056-.982 2.056-2.193v-.877c0-1.21-.92-2.192-2.056-2.192h-2.878m-4.933 5.262h-2.878c-1.135 0-2.055-.982-2.055-2.193v-.877c0-1.21.92-2.192 2.055-2.192h2.878M5.611 3.692h28.777c1.136 0 2.056.981 2.056 2.192v33.45c0 9.374-7.125 16.973-15.914 16.973h-1.06c-8.79 0-15.915-7.599-15.915-16.972V5.885c0-1.212.92-2.193 2.056-2.193m4.11 15.785h20.556c1.136 0 2.056.981 2.056 2.192v17.807c0 6.874-5.225 12.447-11.67 12.447h-1.327c-6.445 0-11.67-5.573-11.67-12.447V21.67c0-1.21.92-2.192 2.056-2.192m13.567 7.892c0 1.937-1.472 3.508-3.288 3.508-1.817 0-3.29-1.57-3.29-3.508s1.473-3.507 3.29-3.507 3.288 1.57 3.288 3.507","viewW":40,"viewH":60},"bidet_built_in":{"d":"M17.318 12.182h-8.06c-.88 0-1.592.74-1.592 1.654v16.126c0 6.698 5.225 12.129 11.67 12.129h1.327c6.445 0 11.67-5.43 11.67-12.13V13.837c0-.914-.713-1.654-1.591-1.654H22.68m-.215-8.545v9.827c0 1.18-.92 2.136-2.055 2.136h-.822c-1.136 0-2.056-.956-2.056-2.136V3.637m10.689 8.545V3.637m-16.445 0v8.545M5.611 3.637h28.777c1.136 0 2.056.956 2.056 2.136v24.051c0 9.135-7.125 16.54-15.914 16.54h-1.06c-8.79 0-15.915-7.405-15.915-16.54V5.773c0-1.18.92-2.136 2.056-2.136M23.289 23.29c0 1.888-1.473 3.418-3.29 3.418s-3.288-1.53-3.288-3.418 1.472-3.418 3.289-3.418c1.816 0 3.288 1.53 3.288 3.418","viewW":40,"viewH":50},"kitchen_sink":{"d":"M38.188 8.7h10.598c1.211 0 2.193.956 2.193 2.136v28.2c0 1.18-.982 2.136-2.193 2.136H11.08c-1.21 0-2.192-.956-2.192-2.136v-28.2c0-1.18.981-2.136 2.192-2.136h10.599m10.885-5.128V15.11c0 1.18-.981 2.136-2.192 2.136h-.877c-1.21 0-2.192-.957-2.192-2.136V3.572m5.261 7.691h3.07c1.21 0 2.192-.956 2.192-2.136v-.855c0-1.18-.982-2.136-2.192-2.136h-3.07m-5.261 5.127h-3.07c-1.21 0-2.192-.956-2.192-2.136v-.855c0-1.18.982-2.136 2.193-2.136h3.069M5.817 46.299h48.231c1.21 0 2.192-.956 2.192-2.136V5.709c0-1.18-.981-2.137-2.192-2.137H5.818c-1.211 0-2.193.957-2.193 2.137v38.454c0 1.18.982 2.136 2.192 2.136M33.44 25.79c0 1.888-1.57 3.418-3.507 3.418s-3.508-1.53-3.508-3.418c0-1.887 1.57-3.418 3.508-3.418s3.507 1.53 3.507 3.418","viewW":60,"viewH":50},"kitchen_sink_double":{"d":"M53.173 12.182c-.468 0-.847.354-.847.79s.38.79.847.79zm21.979 1.58c.467 0 .846-.353.846-.79 0-.436-.379-.79-.846-.79zM6.01 3.572v.79h77.842v-1.58H6.01zM86.14 5.71h-.847v38.454h1.694V5.709zM83.85 46.3v-.79H6.01v1.58h77.842zM3.72 44.163h.847V5.709H2.873v38.454zm2.29 2.136v-.79c-.797 0-1.443-.603-1.443-1.346H2.873c0 1.616 1.404 2.926 3.137 2.926zm80.131-2.136h-.847c0 .743-.646 1.346-1.442 1.346v1.58c1.732 0 3.136-1.31 3.136-2.926zm-2.29-40.59v.79c.797 0 1.443.602 1.443 1.346h1.694c0-1.617-1.404-2.927-3.136-2.927zm-77.841 0v-.79c-1.733 0-3.137 1.31-3.137 2.926h1.694c0-.744.646-1.347 1.443-1.347zm5.494 37.599v.79h28.39v-1.58h-28.39zm30.68-2.136h.846v-28.2h-1.694v28.2zm-32.97-28.2h-.846v28.2h1.694v-28.2zM39.895 8.7v-.79h-5.669v1.58h5.669zm-22.721 0v-.79h-5.669v1.58h5.669zm-7.958 2.136h.847c0-.744.645-1.346 1.442-1.346V7.91c-1.732 0-3.136 1.31-3.136 2.926zm32.968 0h.847c0-1.616-1.404-2.927-3.136-2.927v1.58c.797 0 1.442.603 1.442 1.347zm-2.29 30.336v.79c1.733 0 3.137-1.31 3.137-2.926h-1.694c0 .743-.645 1.346-1.442 1.346zm-28.389 0v-.79c-.797 0-1.442-.603-1.442-1.346H8.368c0 1.616 1.404 2.926 3.136 2.926zm13.737-23.927v.79h.916v-1.58h-.916zm3.205-2.136h.847V3.572H27.6V15.11zM22.952 3.572h-.847V15.11h1.693V3.572zm3.205 13.673v.79c1.732 0 3.136-1.31 3.136-2.926H27.6c0 .743-.646 1.346-1.443 1.346zm-.916 0v-.79c-.797 0-1.443-.603-1.443-1.346h-1.693c0 1.616 1.404 2.926 3.136 2.926zm3.205-5.982v.79h3.206v-1.58h-3.206zm5.495-2.136h.847v-.855h-1.694v.855zm-2.29-2.991v-.79h-3.205v1.58h3.206zm2.29 2.136h.847c0-1.616-1.404-2.926-3.136-2.926v1.58c.796 0 1.442.603 1.442 1.346zm-2.29 2.991v.79c1.733 0 3.137-1.31 3.137-2.926h-1.694c0 .743-.646 1.346-1.442 1.346zm-11.905 0v.79h3.206v-1.58h-3.206zm3.206-5.127v-.79h-3.206v1.58h3.206zm-5.495 2.136h-.847v.855h1.694v-.855zm2.29-2.136v-.79c-1.733 0-3.137 1.31-3.137 2.926h1.694c0-.743.646-1.346 1.442-1.346zm0 5.127v-.79c-.797 0-1.443-.603-1.443-1.346H16.61c0 1.616 1.404 2.926 3.136 2.926zm9.615 14.527h-.847c0 1.452-1.26 2.628-2.816 2.628v1.58c2.49 0 4.51-1.884 4.51-4.208zM25.7 29.208v-.79c-1.555 0-2.816-1.176-2.816-2.628H21.19c0 2.324 2.02 4.209 4.51 4.209zm-3.663-3.418h.847c0-1.451 1.26-2.628 2.816-2.628v-1.58c-2.49 0-4.51 1.884-4.51 4.208zm3.663-3.418v.79c1.555 0 2.816 1.177 2.816 2.628h1.694c0-2.324-2.02-4.208-4.51-4.208zm24.268 18.8v.79h28.39v-1.58h-28.39zm30.68-2.136h.846v-28.2H79.8v28.2zM78.356 8.7v-.79h-28.39v1.58h28.39zm-30.68 2.136h-.846v28.2h1.694v-28.2zm2.29-2.136v-.79c-1.732 0-3.136 1.31-3.136 2.926h1.694c0-.744.646-1.346 1.442-1.346zm30.68 2.136h.846c0-1.616-1.404-2.927-3.136-2.927v1.58c.797 0 1.443.603 1.443 1.347zm-2.29 30.336v.79c1.732 0 3.136-1.31 3.136-2.926H79.8c0 .743-.646 1.346-1.443 1.346zm-28.39 0v-.79c-.796 0-1.442-.603-1.442-1.346H46.83c0 1.616 1.404 2.926 3.136 2.926zm3.206-28.2v.79h21.979v-1.58h-21.98z","viewW":90,"viewH":50}}; diff --git a/src/furniture-plan-catalog.generated.ts b/src/furniture-plan-catalog.generated.ts new file mode 100644 index 00000000..9f2e272b --- /dev/null +++ b/src/furniture-plan-catalog.generated.ts @@ -0,0 +1,2 @@ +/* Generated by scripts/generate-furniture-assets.mjs. DO NOT EDIT. */ +export const GENERATED_FURNITURE_CATALOG = [{"id":"coffee_table","group":"furniture","category":"coffee_table","w":120,"h":60},{"id":"coffee_table_round","group":"furniture","category":"coffee_table","w":80,"h":80},{"id":"coffee_table_oval","group":"furniture","category":"coffee_table","w":120,"h":60},{"id":"coffee_table_rounded","group":"furniture","category":"coffee_table","w":120,"h":60},{"id":"table_dining","group":"furniture","category":"dining_table","w":160,"h":90},{"id":"table_round","group":"furniture","category":"dining_table","w":110,"h":110},{"id":"table_dining_oval","group":"furniture","category":"dining_table","w":180,"h":100},{"id":"table_dining_rounded","group":"furniture","category":"dining_table","w":160,"h":90},{"id":"desk","group":"furniture","category":"work_table","w":140,"h":70},{"id":"desk_corner","group":"furniture","category":"work_table","w":160,"h":160},{"id":"chair","group":"furniture","category":"chair","w":50,"h":50},{"id":"chair_bar","group":"furniture","category":"chair","w":45,"h":48},{"id":"armchair","group":"furniture","category":"armchair","w":90,"h":90},{"id":"armchair_office","group":"furniture","category":"armchair","w":65,"h":65},{"id":"sofa","group":"furniture","category":"sofa","w":180,"h":90},{"id":"sofa_three_seat","group":"furniture","category":"sofa","w":240,"h":90},{"id":"sofa_corner_right","group":"furniture","category":"sofa","w":260,"h":170},{"id":"bed_single","group":"furniture","category":"bed","w":90,"h":200},{"id":"bed_double","group":"furniture","category":"bed","w":160,"h":200},{"id":"nightstand","group":"furniture","category":"nightstand","w":50,"h":40},{"id":"cabinet_tv","group":"furniture","category":"nightstand","w":140,"h":45},{"id":"cabinet_shoe","group":"furniture","category":"nightstand","w":80,"h":35},{"id":"cabinet_sink","group":"furniture","category":"nightstand","w":80,"h":50},{"id":"bookshelf","group":"furniture","category":"wardrobe","w":100,"h":35},{"id":"wall_unit","group":"furniture","category":"wardrobe","w":240,"h":45},{"id":"wardrobe","group":"furniture","category":"wardrobe","w":180,"h":60},{"id":"kitchen_floor","group":"furniture","category":"kitchen_cabinet","w":60,"h":60},{"id":"kitchen_floor_corner","group":"furniture","category":"kitchen_cabinet","w":90,"h":90},{"id":"kitchen_wall","group":"furniture","category":"kitchen_cabinet","w":60,"h":35},{"id":"kitchen_wall_corner","group":"furniture","category":"kitchen_cabinet","w":60,"h":60},{"id":"shelf_floor","group":"furniture","category":"shelving","w":100,"h":35},{"id":"shelf_wall","group":"furniture","category":"shelving","w":100,"h":25},{"id":"cooktop_two","group":"appliance","category":"cooktop","w":30,"h":50},{"id":"stove","group":"appliance","category":"cooktop","w":60,"h":60},{"id":"tv","group":"appliance","category":"tv","w":120,"h":28},{"id":"tv_wall","group":"appliance","category":"tv","w":120,"h":15},{"id":"toilet","group":"sanitary","category":"toilet","w":40,"h":70},{"id":"toilet_built_in","group":"sanitary","category":"toilet","w":40,"h":55},{"id":"bathtub","group":"sanitary","category":"bathtub","w":170,"h":75},{"id":"bathtub_corner","group":"sanitary","category":"bathtub","w":140,"h":140},{"id":"bidet","group":"sanitary","category":"bidet","w":40,"h":60},{"id":"bidet_built_in","group":"sanitary","category":"bidet","w":40,"h":50},{"id":"kitchen_sink","group":"sanitary","category":"kitchen_sink","w":60,"h":50},{"id":"kitchen_sink_double","group":"sanitary","category":"kitchen_sink","w":90,"h":50}] as const; diff --git a/src/furniture.ts b/src/furniture.ts index 20465c28..5ab333db 100644 --- a/src/furniture.ts +++ b/src/furniture.ts @@ -30,7 +30,8 @@ */ import { NORM_W, GRID_PITCH, CANVAS_LIMIT } from './space-geometry'; -import { GENERATED_FURNITURE_PLAN } from './furniture-plan-art.generated'; +import { GENERATED_FURNITURE_CATALOG } from './furniture-plan-catalog.generated'; +import { FURNITURE_ART_RUNTIME, type FurnitureArtHost } from './furniture-art-runtime'; /** Groups the palette shows, in the order it shows them. */ export const FURNITURE_GROUPS = ['furniture', 'appliance', 'sanitary', 'other'] as const; @@ -64,8 +65,8 @@ export interface FurnitureSymbol { h: number; /** Legacy drawing retained for symbols absent from the designer pack. */ g?: Prim[]; - /** Designer drawing with its native SVG viewBox. */ - art?: FurnitureGraphic; + /** Designer symbol: its drawing lives in the lazy artwork chunk (#474). */ + designer?: true; } export interface FurnitureGraphic { @@ -242,13 +243,13 @@ const RETAINED_IDS = new Set([ /** Complete public library: 44 designer symbols plus the 12 useful existing * symbols for which the pack intentionally has no top-view replacement. */ export const FURNITURE: FurnitureSymbol[] = [ - ...GENERATED_FURNITURE_PLAN.map((symbol) => ({ + ...GENERATED_FURNITURE_CATALOG.map((symbol) => ({ id: symbol.id, group: symbol.group as FurnitureGroup, category: symbol.category, w: symbol.w, h: symbol.h, - art: symbol.art, + designer: true as const, })), ...LEGACY_FURNITURE.filter((symbol) => RETAINED_IDS.has(symbol.id)), ]; @@ -262,6 +263,11 @@ export function furnitureSymbol(id: string | null | undefined): FurnitureSymbol return (id && BY_ID.get(id)) || null; } +/** Designer symbol whose drawing is lazy (#474); legacy symbols draw eagerly. */ +export function furnitureArtIsLazy(id: string): boolean { + return BY_ID.get(id)?.designer === true; +} + /** The symbols of one group, in table order. */ export function furnitureOfGroup(group: FurnitureGroup): FurnitureSymbol[] { return FURNITURE.filter((s) => s.group === group); @@ -360,10 +366,13 @@ function primitivePathD(s: FurnitureSymbol, w: number, h: number): string { /** Native one-path artwork and its coordinate box. The renderer scales this * box non-uniformly to the user's stored dimensions; the furniture stroke * helpers below separate that local scale from the outer plan camera. */ -export function furnitureGraphic(id: string): FurnitureGraphic | null { +export function furnitureGraphic(id: string, host?: FurnitureArtHost): FurnitureGraphic | null { const symbol = furnitureSymbol(id); if (!symbol) return null; - if (symbol.art) return symbol.art; + // Designer artwork is lazy (#474): `undefined` while the chunk is pending or + // settled into fallback renders the piece as an unknown symbol — nothing — + // and a host passed here is re-rendered once the runtime settles. + if (symbol.designer) return FURNITURE_ART_RUNTIME.art(id, host) ?? null; const d = primitivePathD(symbol, 1, 1); return d ? { d, viewW: 1, viewH: 1 } : null; } @@ -373,7 +382,8 @@ export function furnitureGraphic(id: string): FurnitureGraphic | null { export function furniturePathD(id: string, w: number, h: number): string { const symbol = furnitureSymbol(id); if (!symbol || !(w > 0) || !(h > 0)) return ''; - return symbol.art?.d || primitivePathD(symbol, w, h); + if (symbol.designer) return FURNITURE_ART_RUNTIME.art(id)?.d || ''; + return primitivePathD(symbol, w, h); } /** diff --git a/src/houseplan-card.ts b/src/houseplan-card.ts index 9d688deb..dd87c24f 100755 --- a/src/houseplan-card.ts +++ b/src/houseplan-card.ts @@ -71,7 +71,7 @@ import { } from './sun'; import { dayCycleStageVars, renderDayCycleEnvironment } from './day-cycle-render'; import { - furnitureGraphic, + furnitureGraphic, furnitureArtIsLazy, furniturePlanScreenScale, furnitureStrokePx, furnitureRenderTransform, } from './furniture'; @@ -329,6 +329,7 @@ import { type RoomFitGestureCandidate, } from './room-fit'; import { EditorRuntimeLoader, lazyLoadFailureMessage, safeRuntimeDiagnostic, type EditorRuntimeLoaderState } from './editor-runtime-loader'; +import { FURNITURE_ART_RUNTIME, composeUnsub, ensureFurnitureArtFor, furnitureArtBootPending, subscribeFurnitureArtLoadFailures } from './furniture-art-runtime'; import type { BackdropGuardState } from './backdrop-pick'; import { expiredWarmViewport, lruRead, lruWrite, normalizeMarkupTool, strictNumber, @@ -932,6 +933,7 @@ export class HouseplanCard extends LitElement { private _decorStyleSeeded = false; private _seedDecorStyle(cfg: ServerConfig | null): void { + ensureFurnitureArtFor(FURNITURE_ART_RUNTIME, cfg, furnitureArtIsLazy, this); // #474: plan intake starts the lazy artwork before the first frame if (this._decorStyleSeeded || !cfg) return; this._decorStyleSeeded = true; const raw = (cfg.settings as { decor_default_style?: unknown } | undefined) @@ -2572,9 +2574,9 @@ export class HouseplanCard extends LitElement { // locale-load failure into a visible message; other runtime surfaces keep // the console warning from the shared LanguageRuntime. this._languageFailureUnsub?.(); - this._languageFailureUnsub = subscribeLanguageLoadFailures(() => { + this._languageFailureUnsub = composeUnsub(subscribeLanguageLoadFailures(() => { this._showToast(this._t('toast.locale_load_failed')); - }); + }), subscribeFurnitureArtLoadFailures(() => this._showToast(this._t('toast.furniture_art_load_failed')))); // #474 super.connectedCallback(); void this._ensureLiveRuntime().catch(() => this.requestUpdate()); this._pointerModality.connect(this.ownerDocument.defaultView); @@ -3172,9 +3174,7 @@ export class HouseplanCard extends LitElement { try { const ks = JSON.parse(localStorage.getItem(LS_KIOSK) || 'null'); this._kioskScale = { icon: clampScale(ks?.icon), font: clampScale(ks?.font) }; - } catch { - /* defaults */ - } + } catch { /* defaults */ } // instant render from cache (stale-while-revalidate): show the plan and icons // right away, without waiting for the server response — fresh data will load in the background. try { @@ -3191,9 +3191,7 @@ export class HouseplanCard extends LitElement { this._virtualLights = virtualLightSnapshot(c.virtual_lights, this._cfgRev); this._serverStorage = true; } - } catch { - /* ignore */ - } + } catch { /* ignore */ } this._adoptInitialSpace(this._model, this._loadOk); // HP-1551: the saved per-space zoom used to be applied only by // _restoreZoom()'s rAF after the server round-trip, so the cached config @@ -6499,7 +6497,7 @@ export class HouseplanCard extends LitElement { const h = this._stageEl ? this._stageEl.clientHeight : 0; if (h !== this._bootLastH) { this._bootLastH = h; this._bootLastChange = now; } const elapsed = now - this._bootStart; - if (elapsed >= BOOT_MAX_MS || (elapsed >= BOOT_MIN_MS && h > 0 && now - this._bootLastChange >= BOOT_QUIET_MS)) { + if (elapsed >= BOOT_MAX_MS || (elapsed >= BOOT_MIN_MS && h > 0 && now - this._bootLastChange >= BOOT_QUIET_MS && !furnitureArtBootPending(FURNITURE_ART_RUNTIME, this._serverCfg, furnitureArtIsLazy))) { this._bootSettled(); return; } @@ -8912,7 +8910,7 @@ export class HouseplanCard extends LitElement { // physical plan zoom. // An unknown symbol renders as nothing: a plan from a newer card must // open in an older one, not break it. - const art = furnitureGraphic(sh.symbol); + const art = furnitureGraphic(sh.symbol, this); if (!art) return nothing; const tr = furnitureRenderTransform(sh, W, H, art.viewW, art.viewH); const visibleStrokePx = furnitureStrokePx(strokeWidth, furnitureScreenScale); diff --git a/src/houseplan-editor-runtime.ts b/src/houseplan-editor-runtime.ts index a875158d..104fbdd6 100644 --- a/src/houseplan-editor-runtime.ts +++ b/src/houseplan-editor-runtime.ts @@ -85,6 +85,8 @@ import { type FurnitureResizeResult, } from './furniture'; import { FURN_WALL_CELLS, resolveFurniturePlacement, snapFurnitureToWall, type FurniturePlacement } from './furniture-placement'; +import { FURNITURE_ART_RUNTIME } from './furniture-art-runtime'; +import { FURNITURE_ART_FINGERPRINT, GENERATED_FURNITURE_ART } from './furniture-plan-art.generated'; import { furnitureWallSurfacesFor, type FurnitureWallSurface } from './furniture-wall-surface'; import { degradeWalls, rekeyWallsAfterMoveChecked, wallRecordCarrierViolations, @@ -368,6 +370,11 @@ import { applyOpeningMoves, mergeCollinearPartitions, spaceMergeGeometry } from const CARD_VERSION = '1.73.0-beta.1'; +// #474: the editor imports the furniture artwork statically and hands it to +// the page runtime the moment this chunk evaluates — before the loader's +// `install`, so the palette and the placement ghost never render `pending`. +FURNITURE_ART_RUNTIME.adopt(GENERATED_FURNITURE_ART, FURNITURE_ART_FINGERPRINT); + type ResizeLiveLabel = { kind: 'length'; x: number; diff --git a/src/i18n/de.json b/src/i18n/de.json index 7a46a78b..866f9a36 100644 --- a/src/i18n/de.json +++ b/src/i18n/de.json @@ -676,6 +676,7 @@ "preview.room_name": "Wohnzimmer", "toast.cfg_reload_failed": "Der Plan konnte nicht vom Server neu geladen werden: {err}", "toast.locale_load_failed": "Das Sprachpaket konnte nicht geladen werden. Bis zum Neuladen der Seite wird Englisch verwendet.", + "toast.furniture_art_load_failed": "Die Möbelzeichnungen konnten nicht geladen werden. Laden Sie die Seite neu, um sie anzuzeigen.", "room.settings_short": "Raumeinstellungen", "room.unnamed": "Unbenannter Raum", "marker.use_climate_temp": "Geräte-Temperatur im Raum berücksichtigen", diff --git a/src/i18n/en.json b/src/i18n/en.json index db18f07e..0116c99e 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -676,6 +676,7 @@ "preview.room_name": "Living room", "toast.cfg_reload_failed": "Could not reload the plan from the server: {err}", "toast.locale_load_failed": "Could not load the language pack. English is used until the page reloads.", + "toast.furniture_art_load_failed": "Could not load the furniture drawings. Reload the page to show them.", "room.settings_short": "Room settings", "room.unnamed": "Unnamed room", "marker.use_climate_temp": "Include the device temperature in the room", diff --git a/src/i18n/fr.json b/src/i18n/fr.json index ef70370b..b497a0b4 100644 --- a/src/i18n/fr.json +++ b/src/i18n/fr.json @@ -676,6 +676,7 @@ "preview.room_name": "Salon", "toast.cfg_reload_failed": "Impossible de recharger le plan depuis le serveur : {err}", "toast.locale_load_failed": "Impossible de charger le pack de langue. L'anglais est utilisé jusqu'au rechargement de la page.", + "toast.furniture_art_load_failed": "Impossible de charger les dessins de meubles. Rechargez la page pour les afficher.", "room.settings_short": "Paramètres de la pièce", "room.unnamed": "Pièce sans nom", "marker.use_climate_temp": "Inclure la température de l’appareil dans la pièce", diff --git a/src/i18n/ru.json b/src/i18n/ru.json index ace6367f..c54bce07 100644 --- a/src/i18n/ru.json +++ b/src/i18n/ru.json @@ -676,6 +676,7 @@ "preview.room_name": "Гостиная", "toast.cfg_reload_failed": "Не удалось перечитать план с сервера: {err}", "toast.locale_load_failed": "Не удалось загрузить языковой пакет. До перезагрузки страницы используется английский.", + "toast.furniture_art_load_failed": "Не удалось загрузить изображения мебели. Обновите страницу, чтобы их показать.", "room.settings_short": "Настройки комнаты", "room.unnamed": "Комната без имени", "marker.use_climate_temp": "Учитывать температуру устройства в комнате", diff --git a/test/bundle-assets.test.mjs b/test/bundle-assets.test.mjs index 95000396..7a357375 100644 --- a/test/bundle-assets.test.mjs +++ b/test/bundle-assets.test.mjs @@ -54,6 +54,7 @@ test('bundle manifest separates static initial graph from dynamic editor graph', imports: ['shared.js'], dynamicImports: [ 'houseplan-assets/editor.js', 'houseplan-assets/houseplan-onboarding-runtime-HASH.js', 'houseplan-assets/de-HASH.js', 'houseplan-assets/iso-scene-render-HASH.js', + 'houseplan-assets/furniture-plan-art.generated-HASH.js', ], }, 'shared.js': { @@ -62,7 +63,14 @@ test('bundle manifest separates static initial graph from dynamic editor graph', }, 'houseplan-assets/editor.js': { type: 'chunk', fileName: 'houseplan-assets/editor.js', code: 'editor', isEntry: false, - imports: ['shared.js'], dynamicImports: [], + // #474: the editor imports the furniture artwork statically; the View + // reaches the same chunk only dynamically, so it stays out of initial. + imports: ['shared.js', 'houseplan-assets/furniture-plan-art.generated-HASH.js'], dynamicImports: [], + }, + 'houseplan-assets/furniture-plan-art.generated-HASH.js': { + type: 'chunk', fileName: 'houseplan-assets/furniture-plan-art.generated-HASH.js', + code: 'furniture artwork', isEntry: false, imports: [], dynamicImports: [], + modules: { '/repo/src/furniture-plan-art.generated.ts': {} }, }, 'houseplan-assets/houseplan-onboarding-runtime-HASH.js': { type: 'chunk', fileName: 'houseplan-assets/houseplan-onboarding-runtime-HASH.js', @@ -81,14 +89,16 @@ test('bundle manifest separates static initial graph from dynamic editor graph', }, }, 'fingerprint'); assert.deepEqual(manifest.initialViewFiles, ['houseplan-card.js', 'shared.js']); - assert.deepEqual(manifest.lazyEditorFiles, ['houseplan-assets/editor.js']); assert.deepEqual(manifest.lazyOnboardingFiles, [ 'houseplan-assets/houseplan-onboarding-runtime-HASH.js', ]); assert.deepEqual(manifest.lazyLocaleFiles, ['houseplan-assets/de-HASH.js']); assert.deepEqual(manifest.lazyIsometricFiles, ['houseplan-assets/iso-scene-render-HASH.js']); + assert.deepEqual(manifest.lazyFurnitureArtFiles, ['houseplan-assets/furniture-plan-art.generated-HASH.js']); + assert.deepEqual(manifest.lazyEditorFiles, ['houseplan-assets/editor.js', 'houseplan-assets/furniture-plan-art.generated-HASH.js']); assert.deepEqual(manifest.lazyFiles, [ 'houseplan-assets/de-HASH.js', 'houseplan-assets/editor.js', + 'houseplan-assets/furniture-plan-art.generated-HASH.js', 'houseplan-assets/houseplan-onboarding-runtime-HASH.js', 'houseplan-assets/iso-scene-render-HASH.js', ]); @@ -143,7 +153,8 @@ test('retry URL points at the content-hashed runtime chunk after naming', () => + 'new URL("__HOUSEPLAN_ONBOARDING_RETRY_ASSET__", import.meta.url);' + 'new URL("__HOUSEPLAN_ISO_RETRY_ASSET__", import.meta.url);' + 'new URL("__HOUSEPLAN_DE_RETRY_ASSET__", import.meta.url);' - + 'new URL("__HOUSEPLAN_FR_RETRY_ASSET__", import.meta.url)', modules: {}, + + 'new URL("__HOUSEPLAN_FR_RETRY_ASSET__", import.meta.url);' + + 'new URL("__HOUSEPLAN_FURNITURE_ART_RETRY_ASSET__", import.meta.url)', modules: {}, }, 'houseplan-assets/houseplan-editor-runtime-HASH.js': { type: 'chunk', fileName: 'houseplan-assets/houseplan-editor-runtime-HASH.js', code: '', @@ -165,6 +176,10 @@ test('retry URL points at the content-hashed runtime chunk after naming', () => type: 'chunk', fileName: 'houseplan-assets/fr-HASH.js', code: '', modules: { '/repo/src/i18n/fr.ts': {} }, }, + 'houseplan-assets/furniture-plan-art.generated-HASH.js': { + type: 'chunk', fileName: 'houseplan-assets/furniture-plan-art.generated-HASH.js', code: '', + modules: { '/repo/src/furniture-plan-art.generated.ts': {} }, + }, }; plugin.generateBundle({}, bundle); assert.equal( @@ -173,7 +188,8 @@ test('retry URL points at the content-hashed runtime chunk after naming', () => + 'new URL("./houseplan-onboarding-runtime-HASH.js", import.meta.url);' + 'new URL("./iso-scene-render-HASH.js", import.meta.url);' + 'new URL("./de-HASH.js", import.meta.url);' - + 'new URL("./fr-HASH.js", import.meta.url)', + + 'new URL("./fr-HASH.js", import.meta.url);' + + 'new URL("./furniture-plan-art.generated-HASH.js", import.meta.url)', ); }); @@ -422,6 +438,7 @@ const runBudgetCli = (initialViewGzipBytes) => { writeFileSync(join(dir, 'dist/editor.js'), SUPPORT_LAZY_MARKERS.join('\n')); writeFileSync(join(dir, 'dist/locale.js'), 'lazy locale dictionary'); writeFileSync(join(dir, 'dist/isometric.js'), 'lazy isometric runtime'); + writeFileSync(join(dir, 'dist/furniture-art.js'), 'lazy furniture artwork'); writeFileSync(join(dir, 'dist/houseplan-assets.json'), JSON.stringify({ schema: 1, files: [], @@ -433,6 +450,8 @@ const runBudgetCli = (initialViewGzipBytes) => { lazyLocaleGzipBytes: 100, lazyIsometricFiles: ['isometric.js'], lazyIsometricGzipBytes: 100, + lazyFurnitureArtFiles: ['furniture-art.js'], + lazyFurnitureArtGzipBytes: 100, lazyOnboardingFiles: [], })); const script = fileURLToPath(new URL('../scripts/bundle-budget.mjs', import.meta.url)); diff --git a/test/furniture-art-runtime.test.mjs b/test/furniture-art-runtime.test.mjs new file mode 100755 index 00000000..096ca1a5 --- /dev/null +++ b/test/furniture-art-runtime.test.mjs @@ -0,0 +1,205 @@ +// #474: lazy designer furniture artwork. The runtime mirrors LanguageRuntime / +// EditorRuntimeLoader: pending → ready | fallback, fallback is settled, the +// second attempt goes through a nonce URL, a foreign build is terminal, and +// the editor hands the artwork over synchronously. +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { + FurnitureArtRuntime, configNeedsFurnitureArt, furnitureArtBootPending, + ensureFurnitureArtFor, composeUnsub, +} from '../test-build/furniture-art-runtime.js'; +import { resolveFurniturePlacement } from '../test-build/furniture-placement.js'; +import { furnitureGraphic, furnitureArtIsLazy, furnitureSymbol } from '../test-build/furniture.js'; + +const ART = Object.freeze({ sofa: { d: 'M0 0h1', viewW: 180, viewH: 90 } }); +const FP = 'build-A'; +const tick = () => new Promise((resolve) => setTimeout(resolve, 0)); + +const host = () => { + const h = { isConnected: true, updates: 0, requestUpdate() { this.updates++; } }; + return h; +}; + +const runtime = (loads, extra = {}) => { + const attempts = []; + return { + attempts, + runtime: new FurnitureArtRuntime({ + expectedFingerprint: FP, + warn: () => {}, + load: async (attempt) => { + attempts.push(attempt); + const step = loads[attempts.length - 1]; + if (step instanceof Error) throw step; + return step; + }, + ...extra, + }), + }; +}; + +test('pending until ensure; a successful load installs the artwork and re-renders hosts', async () => { + const { runtime: r, attempts } = runtime([{ GENERATED_FURNITURE_ART: ART, FURNITURE_ART_FINGERPRINT: FP }]); + const h = host(); + assert.equal(r.state(), 'pending'); + assert.equal(r.art('sofa', h), undefined); + await r.ensure(); + assert.equal(r.state(), 'ready'); + assert.deepEqual(r.art('sofa'), ART.sofa); + assert.equal(h.updates, 1, 'the host that rendered while pending is re-rendered once'); + await r.ensure(); + assert.equal(attempts.length, 1, 'ensure is idempotent once settled'); +}); + +test('two failed attempts settle into fallback: state is terminal-free, ensure resolves, hosts re-render', async () => { + const failed = []; + const { runtime: r, attempts } = runtime( + [new Error('net'), new Error('net again')], + { loadFailed: (terminal) => failed.push(terminal) }, + ); + const h = host(); + r.art('sofa', h); + await r.ensure(); + assert.equal(r.state(), 'fallback'); + assert.deepEqual(attempts, [0, 1], 'exactly one retry, through attempt 1'); + assert.equal(r.terminal, false); + assert.deepEqual(failed, [false]); + assert.equal(h.updates, 1, 'fallback re-renders the waiting host so it stops waiting'); + assert.equal(r.art('sofa'), undefined); + await r.ensure(); + assert.equal(attempts.length, 2, 'fallback is settled: no background retries'); +}); + +test('a foreign build fingerprint is terminal: no second import, fallback, loadFailed(true)', async () => { + const failed = []; + const { runtime: r, attempts } = runtime( + [{ GENERATED_FURNITURE_ART: ART, FURNITURE_ART_FINGERPRINT: 'build-B' }], + { loadFailed: (terminal) => failed.push(terminal) }, + ); + await r.ensure(); + assert.equal(r.state(), 'fallback'); + assert.equal(r.terminal, true); + assert.deepEqual(attempts, [0], 'a fingerprint mismatch does not retry — only a refresh helps'); + assert.deepEqual(failed, [true]); +}); + +test('the first attempt failing and the second succeeding is ready, not fallback', async () => { + const { runtime: r, attempts } = runtime([new Error('cached failure'), { GENERATED_FURNITURE_ART: ART, FURNITURE_ART_FINGERPRINT: FP }]); + await r.ensure(); + assert.equal(r.state(), 'ready'); + assert.deepEqual(attempts, [0, 1]); +}); + +test('adopt is synchronous, rejects a foreign fingerprint and is a no-op once ready', () => { + const warnings = []; + const { runtime: r } = runtime([], { warn: (message) => warnings.push(message) }); + const h = host(); + r.art('sofa', h); + assert.equal(r.adopt(ART, 'build-B'), false); + assert.equal(r.state(), 'pending'); + assert.equal(warnings.length, 1); + assert.equal(r.adopt(ART, FP), true); + assert.equal(r.state(), 'ready'); + assert.equal(h.updates, 1); + assert.equal(r.adopt({ other: { d: 'M0 0', viewW: 1, viewH: 1 } }, FP), true, 'repeated adopt is a no-op'); + assert.equal(r.art('other'), undefined); +}); + +test('adopt during an in-flight load wins and the load result is not re-installed', async () => { + let release; + const gate = new Promise((resolve) => { release = resolve; }); + const r = new FurnitureArtRuntime({ + expectedFingerprint: FP, warn: () => {}, + load: async () => { await gate; return { GENERATED_FURNITURE_ART: { late: { d: 'M0 0', viewW: 1, viewH: 1 } }, FURNITURE_ART_FINGERPRINT: FP }; }, + }); + const pending = r.ensure(); + r.adopt(ART, FP); + release(); + await pending; + assert.equal(r.state(), 'ready'); + assert.deepEqual(r.art('sofa'), ART.sofa); + assert.equal(r.art('late'), undefined); +}); + +test('onSettled fires once when the runtime leaves pending, and immediately when already settled', async () => { + const { runtime: r } = runtime([{ GENERATED_FURNITURE_ART: ART, FURNITURE_ART_FINGERPRINT: FP }]); + const calls = []; + r.onSettled(() => calls.push('a')); + await r.ensure(); + assert.deepEqual(calls, ['a']); + r.onSettled(() => calls.push('b')); + await tick(); + assert.deepEqual(calls, ['a', 'b']); +}); + +test('only a single in-flight load exists, however many callers ensure()', async () => { + const { runtime: r, attempts } = runtime([{ GENERATED_FURNITURE_ART: ART, FURNITURE_ART_FINGERPRINT: FP }]); + await Promise.all([r.ensure(), r.ensure(), r.ensure()]); + assert.equal(attempts.length, 1); +}); + +// ------------------------------------------------------------ config helpers + +const isDesigner = (symbol) => symbol === 'sofa'; + +test('configNeedsFurnitureArt: only designer furniture counts; legacy, other decor and empty plans do not', () => { + assert.equal(configNeedsFurnitureArt(null, isDesigner), false); + assert.equal(configNeedsFurnitureArt({ spaces: [] }, isDesigner), false); + assert.equal(configNeedsFurnitureArt({ spaces: [{ decor: [{ kind: 'rect' }] }] }, isDesigner), false); + assert.equal(configNeedsFurnitureArt({ spaces: [{ decor: [{ kind: 'furniture', symbol: 'fridge' }] }] }, isDesigner), false); + assert.equal(configNeedsFurnitureArt({ spaces: [null, { decor: null }, { decor: [{ kind: 'furniture', symbol: 'sofa' }] }] }, isDesigner), true); +}); + +test('boot gate waits only while pending AND the plan needs artwork; fallback counts as settled', async () => { + const withSofa = { spaces: [{ decor: [{ kind: 'furniture', symbol: 'sofa' }] }] }; + const { runtime: pendingRuntime } = runtime([]); + assert.equal(furnitureArtBootPending(pendingRuntime, withSofa, isDesigner), true); + assert.equal(furnitureArtBootPending(pendingRuntime, { spaces: [] }, isDesigner), false, 'a plan without furniture never waits'); + const { runtime: failed } = runtime([new Error('x'), new Error('y')]); + await failed.ensure(); + assert.equal(furnitureArtBootPending(failed, withSofa, isDesigner), false, 'fallback lifts the veil'); + const { runtime: ready } = runtime([]); + ready.adopt(ART, FP); + assert.equal(furnitureArtBootPending(ready, withSofa, isDesigner), false); +}); + +test('ensureFurnitureArtFor starts the load and registers the host only when the plan needs artwork', async () => { + const { runtime: r, attempts } = runtime([{ GENERATED_FURNITURE_ART: ART, FURNITURE_ART_FINGERPRINT: FP }]); + const h = host(); + ensureFurnitureArtFor(r, { spaces: [] }, isDesigner, h); + await tick(); + assert.equal(attempts.length, 0, 'no furniture — no request'); + ensureFurnitureArtFor(r, { spaces: [{ decor: [{ kind: 'furniture', symbol: 'sofa' }] }] }, isDesigner, h); + await r.ensure(); + assert.equal(attempts.length, 1); + assert.equal(h.updates, 1, 'the host registered at intake is re-rendered once the artwork lands'); +}); + +test('composeUnsub calls every handle once', () => { + const calls = []; + composeUnsub(() => calls.push(1), () => calls.push(2))(); + assert.deepEqual(calls, [1, 2]); +}); + +// ------------------------------------------------------- library integration + +test('the wall magnet places a designer piece while its artwork is still pending (AC6)', () => { + // The real page runtime is untouched here: nothing adopted, nothing ensured. + assert.equal(furnitureArtIsLazy('sofa'), true); + assert.ok(furnitureSymbol('sofa'), 'catalogue is eager'); + const placement = resolveFurniturePlacement({ + symbol: 'sofa', widthCm: 180, depthCm: 90, point: [0.5, 0.5], + canvasW: 1000, canvasH: 1000, cellCm: 5, gridPitch: 20, walls: [], wallReach: 0, free: true, + }); + assert.ok(placement, 'placement needs the catalogue, not the artwork'); + assert.equal(resolveFurniturePlacement({ + symbol: 'no_such_symbol', widthCm: 10, depthCm: 10, point: [0.5, 0.5], + canvasW: 1000, canvasH: 1000, cellCm: 5, gridPitch: 20, walls: [], wallReach: 0, free: true, + }), null, 'an unknown symbol is still refused'); +}); + +test('furnitureGraphic: legacy art is eager, designer art is undefined until the page runtime settles', () => { + assert.ok(furnitureGraphic('fridge')?.d, 'legacy primitive art needs no chunk'); + assert.equal(furnitureArtIsLazy('fridge'), false); + assert.equal(furnitureGraphic('no_such_symbol'), null, 'unknown id is data, not a crash'); +}); diff --git a/test/furniture-assets.test.mjs b/test/furniture-assets.test.mjs index a1b56a63..0cc05606 100644 --- a/test/furniture-assets.test.mjs +++ b/test/furniture-assets.test.mjs @@ -4,7 +4,8 @@ import fs from 'node:fs'; import path from 'node:path'; import { spawnSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; -import { GENERATED_FURNITURE_PLAN } from '../test-build/furniture-plan-art.generated.js'; +import { GENERATED_FURNITURE_CATALOG } from '../test-build/furniture-plan-catalog.generated.js'; +import { GENERATED_FURNITURE_ART } from '../test-build/furniture-plan-art.generated.js'; import { FURNITURE } from '../test-build/furniture.js'; const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); @@ -21,7 +22,9 @@ test('the vendored designer pack and generated modules stay in sync', () => { }); test('the designer pack has the reviewed cardinality and operations', () => { - assert.equal(GENERATED_FURNITURE_PLAN.length, 44); + assert.equal(GENERATED_FURNITURE_CATALOG.length, 44); + // #474: catalogue ids and lazy artwork keys are the same set. + assert.deepEqual(Object.keys(GENERATED_FURNITURE_ART).sort(), GENERATED_FURNITURE_CATALOG.map((s) => s.id).sort()); assert.equal(MANIFEST.menu_icons.length, 33); assert.equal(MANIFEST.symbols.filter((s) => s.operation === 'replace').length, 18); assert.equal(MANIFEST.symbols.filter((s) => s.operation === 'add').length, 26); diff --git a/test/furniture.test.mjs b/test/furniture.test.mjs index e643b8aa..a5a04c91 100644 --- a/test/furniture.test.mjs +++ b/test/furniture.test.mjs @@ -19,6 +19,12 @@ import { furnitureWallSurfacesFor, physicalFurnitureWallSurfaces, roomFurnitureWallSurfaces, } from '../test-build/furniture-wall-surface.js'; import { setWallThickness, wallCmToUnits } from '../test-build/wall-thickness.js'; +import { FURNITURE_ART_RUNTIME } from '../test-build/furniture-art-runtime.js'; +import { FURNITURE_ART_FINGERPRINT, GENERATED_FURNITURE_ART } from '../test-build/furniture-plan-art.generated.js'; + +// #474: designer artwork is lazy; these tests exercise the library with the +// artwork handed over the way the editor does it (synchronous adopt). +assert.equal(FURNITURE_ART_RUNTIME.adopt(GENERATED_FURNITURE_ART, FURNITURE_ART_FINGERPRINT), true); import { NORM_W, GRID_PITCH, GRID_N, GRID_STEP_N } from '../test-build/space-geometry.js'; const closeTo = (got, want, tol = 1e-9) => @@ -43,11 +49,13 @@ test('every symbol is well formed: unique id, a known group, positive default si for (const v of nums) assert.ok(v >= -0.001 && v <= 1.001, `${s.id}: ${v} outside the unit box`); } } else { - assert.deepEqual([s.art.viewW, s.art.viewH], [s.w, s.h], `${s.id}: manifest and SVG viewBox differ`); + const art = furnitureGraphic(s.id); + assert.equal(s.designer, true, `${s.id}: designer symbol without the lazy flag`); + assert.deepEqual([art.viewW, art.viewH], [s.w, s.h], `${s.id}: manifest and SVG viewBox differ`); } } assert.equal(FURNITURE.length, 56); - assert.equal(FURNITURE.filter((s) => s.art).length, 44); + assert.equal(FURNITURE.filter((s) => s.designer).length, 44); assert.equal(FURNITURE.filter((s) => s.g).length, 12); });