mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
План уходил base64 в WebSocket-кадре: файл больше ~3 МиБ давал кадр больше 4 МиБ, HA закрывал сокет до обработчика, и обещанные 8 МБ были недостижимы. - бэкенд: HouseplanPlanUploadView (POST /api/houseplan/plans/upload), потоковый предел MAX_PLAN_BYTES (read_bounded), общий writer store_plan_upload для view и ws_plan_set (контракт WS без изменений); - карточка: stagePlanFile/uploadPlanFile/renderPlanBackdropGuard в backdrop-pick.ts для обоих рантаймов; PlanFilePayload хранит Blob вместо b64; SVG больше предела — тост при выборе, растр — диалог #39 только с уменьшенной копией, копия больше предела не попадает в staging, 413 называет предел; - i18n toast.plan_too_large, backdrop.over_limit_body (en/ru/de/fr); USER-GUIDE ru/en, CHANGELOG ru/en, docs/testing-notes (#617); - тесты: test/plan-upload-limit.test.mjs, tests_backend/test_plan_upload.py, test_ha_upload.py (#617), smoke_plan_upload_limit.mjs; три смока переведены с b64/plan/set на blob/fetchWithAuth; мутанты plan-upload-*; - база монолита: hostRefs +3 (общий хелпер плана вместо двух копий в рантаймах, новый тост уменьшенной копии). Issue: #617 User-Visible: yes
2796 lines
1.1 MiB
Plaintext
2796 lines
1.1 MiB
Plaintext
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="e40dce8a0e21fa0d8552321bbcf22b164da42dda6875c015cf13dbdfe105abb4";import{e as t,i as e,E as i,s,a as o,n as a,f as n,b as r,l,o as h,r as c,A as d,c as p,d as u,g as _,h as m,j as g,k as f,m as b,p as v,v as y,q as w,t as $,u as k,w as x,x as M,y as C,z as S,B as P,T as I,C as D,D as L,F as T,G as R,H as F,I as z,J as N,K as E,L as A,M as O,N as B,O as H,P as W,Q as G,R as j,S as U,U as q,V as K,W as V,X as J,Y,Z,_ as X,$ as Q,a0 as tt,a1 as et,a2 as it,a3 as st,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 wt,am as $t,an as kt,ao as xt,ap as Mt,aq as Ct,ar as St,as as Pt,at as It,au as Dt,av as Lt,aw as Tt,ax as Rt,ay as Ft,az as zt,aA as Nt,aB as Et,aC as At,aD as Ot,aE as Bt,aF as Ht,aG as Wt,aH as Gt,aI as jt,aJ as Ut,aK as qt,aL as Kt,aM as Vt,aN as Jt,aO as Yt,aP as Zt,aQ as Xt,aR as Qt,aS as te,aT as ee,aU as ie,aV as se,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 we,bc as $e,bd as ke,be as xe,bf as Me,bg as Ce,bh as Se,bi as Pe,bj as Ie,bk as De,bl as Le,bm as Te,bn as Re,bo as Fe,bp as ze,bq as Ne,br as Ee,bs as Ae,bt as Oe,bu as Be,bv as He,bw as We,bx as Ge,by as je,bz as Ue,bA as qe,bB as Ke,bC as Ve,bD as Je,bE as Ye,bF as Ze,bG as Xe,bH as Qe,bI as ti,bJ as ei,bK as ii,bL as si,bM as oi,bN as ai,bO as ni,bP as ri,bQ as li,bR as hi,bS as ci,bT as di,bU as pi,bV as ui,bW as _i,bX as mi,bY as gi,bZ as fi,b_ as bi,b$ as vi,c0 as yi,c1 as wi,c2 as $i,c3 as ki,c4 as xi,c5 as Mi,c6 as Ci,c7 as Si,c8 as Pi,c9 as Ii,ca as Di,cb as Li,cc as Ti,cd as Ri,ce as Fi,cf as zi,cg as Ni,ch as Ei,ci as Ai,cj as Oi,ck as Bi,cl as Hi,cm as Wi,cn as Gi,co as ji,cp as Ui,cq as qi,cr as Ki,cs as Vi,ct as Ji,cu as Yi,cv as Zi,cw as Xi,cx as Qi,cy as ts,cz as es,cA as is,cB as ss,cC as os,cD as as,cE as ns,cF as rs,cG as ls,cH as hs,cI as cs,cJ as ds,cK as ps,cL as us,cM as _s,cN as ms,cO as gs,cP as fs,cQ as bs,cR as vs,cS as ys,cT as ws,cU as $s,cV as ks,cW as xs,cX as Ms,cY as Cs,cZ as Ss,c_ as Ps,c$ as Is,d0 as Ds,d1 as Ls,d2 as Ts,d3 as Rs,d4 as Fs,d5 as zs,d6 as Ns,d7 as Es,d8 as As,d9 as Os,da as Bs,db as Hs,dc as Ws,dd as Gs,de as js,df as Us,dg as qs,dh as Ks,di as Vs,dj as Js,dk as Ys,dl as Zs,dm as Xs,dn as Qs,dp as to,dq as eo,dr as io,ds as so,dt as oo,du as ao,dv as no,dw as ro,dx as lo,dy as ho,dz as co,dA as po,dB as uo,dC as _o,dD as mo,dE as go,dF as fo,dG as bo}from"./houseplan-card-B455eSod.js";import{n as vo,s as yo}from"./namespace-language-GX82QtbO.js";import{e as wo,s as $o,c as ko,t as xo,a as Mo,f as Co,b as So,d as Po,g as Io,h as Do,r as Lo,i as To,u as Ro,j as Fo,k as zo,l as No,m as Eo,n as Ao,o as Oo,p as Bo,q as Ho,v as Wo,F as Go,w as jo,x as Uo,S as qo,y as Ko,z as Vo,A as Jo,B as Yo,C as Zo,D as Xo,E as Qo,G as ta,H as ea}from"./backdrop-pick-cDazsrVi.js";import{h as ia,t as sa,m as oa,T as aa,a as na}from"./zigbee-topology-C-dRjC84.js";import{GENERATED_FURNITURE_ART as ra,FURNITURE_ART_FINGERPRINT as la}from"./furniture-plan-art.generated-BuiQkFDH.js";import"./form-kit.styles-C7T6wUDs.js";const ha={},ca=t(class extends e{constructor(){super(...arguments),this.ot=ha}render(t,e){return e()}update(t,[e,s]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return i}else if(this.ot===e)return i;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,s)}});var da={"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 pa=t=>new URL(`${t}?retry`,import.meta.url).href,ua=vo(da,{ru:t=>0===t?import("./support-ru-B0ZZj1TK.js"):import(pa("./support-ru-B0ZZj1TK.js")),de:t=>0===t?import("./support-de-CCL-sDiQ.js"):import(pa("./support-de-CCL-sDiQ.js")),fr:t=>0===t?import("./support-fr-WmnqLeEF.js"):import(pa("./support-fr-WmnqLeEF.js"))});function _a(t,e,i){return s(ua.dictionary(t)?.[e]??da[e]??e,i)}function ma(t,e,i,s,o){return{markerId:t,source:s,mapId:o,space:e.length?"":i}}function ga(t,e,i){return{...t,space:i.has(e)?e:""}}function fa(t,e=Math.random){const i=new Set(t);for(let t=0;t<64;t+=1){const t="vr_"+Math.floor(16777215*e()).toString(36).padStart(5,"0");if(!i.has(t))return t}return"vr_"+Date.now().toString(36)}function ba(t,e,i){return t.map(t=>t.id===e?{...t,calibration:i}:t)}const va=new WeakMap,ya=(t,e)=>{const i=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(i?.name||i?.id||e)};function wa(t,e,i){const s=t.host,n=l(s.hass,s._config?.language),r=(t,e)=>_a(n,t,e),u=e.marker?.vacuum||{},_=Array.isArray(u.map_routes),m=s._vacSource(e)||"",g=o(e.id,u,e.space,m),f=(s._serverCfg?.spaces||[]).filter(t=>"string"==typeof t?.id&&!!t.id).map(t=>({id:t.id,name:String(t.name||t.id)})),b=new Set(f.map(t=>t.id)),v=h(g,[m],t=>s._vacObservedMapId(e,t)),y=c({routes:g,observed:v,spaceIds:b}),w="ready"===y.kind||"needs_calibration"===y.kind||"missing_space"===y.kind?y.route.id:"",$=m?v[m]:void 0,k=async i=>{let o=_?u.map_routes??null:null;if(!o&&(o=function(t,e,i,s){if(!i)return null;const o=t?.calibration;if(!o||"object"!=typeof o)return null;const n=new Set,r=[];for(const t of Object.keys(o)){const l=a(o[t]);if(!l)continue;const h=s(n);n.add(h),r.push({id:h,source:i,map_id:t,space:e,calibration:l})}return r.length?r:null}(u,e.space,m,t=>fa(t))??[],!m&&Object.keys(u.calibration||{}).length))return!1;const n=i(o);return!!n&&(async i=>{const o=s._serverCfg;if(!o)return!1;const a=JSON.parse(JSON.stringify(o));a.markers=a.markers||[];let n=a.markers.find(t=>t.id===e.id);if(!n){if("device"!==e.bindingKind&&"entity"!==e.bindingKind||!e.bindingRef)return!1;n={id:e.id,binding:`${e.bindingKind}:${e.bindingRef}`,space:e.space||null,area:e.area||null,hidden:!!e.hidden},a.markers.push(n)}n.vacuum={...n.vacuum||{},map_routes:i},delete n.vacuum.calibration;const r=s._adoption.beginOptimistic(o,a);s._adoption.stageLocalConfig(a),s._regSignature="",s._maybeRebuildDevices(),s.requestUpdate(),s._saveConfigDebounced.pending()&&s._saveConfigDebounced.cancel();try{return await t._saveConfigNow(),!0}catch(t){return s._rollbackOptimistic(r),s._regSignature="",s._maybeRebuildDevices(),s.requestUpdate(),s._showToast(s._t("toast.cfg_save_failed",{err:s._errText(t)})),!1}})(n)},x=i.candidates.filter(t=>t.entityId!==m&&!g.some(e=>e.source===t.entityId)),M=async(t,e)=>{if(!e||e===t.space)return;await s._confirmDanger({key:"vacuum_route_space",kind:"warning",title:r("vac.route_space_title"),message:r("vac.route_space_body"),objectName:t.map_id||r("vac.route_map_default"),confirmLabel:r("vac.route_space_confirm"),cancelLabel:s._t("btn.cancel")})&&await k(i=>function(t,e,i,s){return t.map(t=>t.id===e?{...t,id:s,space:i,calibration:null}:t)}(i,t.id,e,fa(new Set(g.map(t=>t.id)))))},C=new Map(f.map((t,e)=>[t.id,e])),S=(t,e)=>t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)||t.id.localeCompare(e.id),P=g.filter(t=>b.has(t.space)).sort((t,e)=>(C.get(t.space)??0)-(C.get(e.space)??0)||S(t,e)),I=g.filter(t=>!b.has(t.space)).sort(S),D=[...P,...I],L=!!m&&void 0!==$&&!g.some(t=>t.source===m&&t.map_id===$);let T=va.get(t);const R=T?.source||"",F=T?.mapId||"",z=!!T&&g.some(t=>t.source===R&&t.map_id===F);T&&(T.markerId!==e.id||s._vacObservedMapId(e,T.source)!==T.mapId||z&&!T.saving)&&(va.delete(t),T=void 0),T?.space&&!b.has(T.space)&&(T=ga(T,"",b),va.set(t,T));const N=i=>p`
|
||
<li class="vacroute ${i.id===w?"on":""}" data-route-id=${i.id}>
|
||
========
|
||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="7ec6b12023747a2dd1b234bf6f39993245f064a827fc3f6e3bf62c6817451c0c";import{e as t,i as e,E as s,s as i,a as o,n as a,f as n,b as r,l,o as h,r as c,A as d,c as p,d as u,g as _,h as m,j as g,k as f,m as b,p as v,v as y,q as w,t as $,u as k,w as x,x as M,y as C,z as S,B as P,T as I,C as D,D as L,F as T,G as R,H as z,I as F,J as N,K as A,L as E,M as O,N as B,O as H,P as W,Q as j,R as G,S as q,U,V as K,W as V,X as J,Y as Z,Z as Y,_ as X,$ 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 wt,am as $t,an as kt,ao as xt,ap as Mt,aq as Ct,ar as St,as as Pt,at as It,au as Dt,av as Lt,aw as Tt,ax as Rt,ay as zt,az as Ft,aA as Nt,aB as At,aC as Et,aD as Ot,aE as Bt,aF as Ht,aG as Wt,aH as jt,aI as Gt,aJ as qt,aK as Ut,aL as Kt,aM as Vt,aN as Jt,aO as Zt,aP as Yt,aQ as Xt,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 we,bc as $e,bd as ke,be as xe,bf as Me,bg as Ce,bh as Se,bi as Pe,bj as Ie,bk as De,bl as Le,bm as Te,bn as Re,bo as ze,bp as Fe,bq as Ne,br as Ae,bs as Ee,bt as Oe,bu as Be,bv as He,bw as We,bx as je,by as Ge,bz as qe,bA as Ue,bB as Ke,bC as Ve,bD as Je,bE as Ze,bF as Ye,bG as Xe,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 ws,c2 as $s,c3 as ks,c4 as xs,c5 as Ms,c6 as Cs,c7 as Ss,c8 as Ps,c9 as Is,ca as Ds,cb as Ls,cc as Ts,cd as Rs,ce as zs,cf as Fs,cg as Ns,ch as As,ci as Es,cj as Os,ck as Bs,cl as Hs,cm as Ws,cn as js,co as Gs,cp as qs,cq as Us,cr as Ks,cs as Vs,ct as Js,cu as Zs,cv as Ys,cw as Xs,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 wi,cU as $i,cV as ki,cW as xi,cX as Mi,cY as Ci,cZ as Si,c_ as Pi,c$ as Ii,d0 as Di,d1 as Li,d2 as Ti,d3 as Ri,d4 as zi,d5 as Fi,d6 as Ni,d7 as Ai,d8 as Ei,d9 as Oi,da as Bi,db as Hi,dc as Wi,dd as ji,de as Gi,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji,dk as Zi,dl as Yi,dm as Xi,dn as Qi,dp as to,dq as eo,dr as so,ds as io,dt as oo,du as ao,dv as no,dw as ro,dx as lo,dy as ho,dz as co,dA as po,dB as uo,dC as _o,dD as mo,dE as go,dF as fo,dG as bo}from"./houseplan-card-6pfPfOB6.js";import{e as vo,s as yo,c as wo,t as $o,a as ko,f as xo,b as Mo,d as Co,g as So,h as Po,r as Io,i as Do,u as Lo,j as To,k as Ro,l as zo,m as Fo,n as No,o as Ao,p as Eo,q as Oo,v as Bo,F as Ho,w as Wo,x as jo,y as Go,z as qo,A as Uo,B as Ko,C as Vo,D as Jo,E as Zo,G as Yo,H as Xo,I as Qo,J as ta}from"./backdrop-pick-CUEetKrv.js";import{h as ea,t as sa,m as ia,T as oa}from"./zigbee-topology-CCkctuc2.js";import{GENERATED_FURNITURE_ART as aa,FURNITURE_ART_FINGERPRINT as na}from"./furniture-plan-art.generated-dHL7hKMf.js";import"./form-kit.styles-bTArvCsM.js";const ra={},la=t(class extends e{constructor(){super(...arguments),this.ot=ra}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return s}else if(this.ot===e)return s;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}});var ha={"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 ca={en:ha,ru:{"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.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.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 da(t,e,s){return i(ca[t]?.[e]??ha[e]??e,s)}function pa(t,e,s,i,o){return{markerId:t,source:i,mapId:o,space:e.length?"":s}}function ua(t,e,s){return{...t,space:s.has(e)?e:""}}function _a(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 ma(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const ga=new WeakMap,fa=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function ba(t,e,s){const i=t.host,n=l(i.hass,i._config?.language),r=(t,e)=>da(n,t,e),u=e.marker?.vacuum||{},_=Array.isArray(u.map_routes),m=i._vacSource(e)||"",g=o(e.id,u,e.space,m),f=(i._serverCfg?.spaces||[]).filter(t=>"string"==typeof t?.id&&!!t.id).map(t=>({id:t.id,name:String(t.name||t.id)})),b=new Set(f.map(t=>t.id)),v=h(g,[m],t=>i._vacObservedMapId(e,t)),y=c({routes:g,observed:v,spaceIds:b}),w="ready"===y.kind||"needs_calibration"===y.kind||"missing_space"===y.kind?y.route.id:"",$=m?v[m]:void 0,k=async s=>{let o=_?u.map_routes??null:null;if(!o&&(o=function(t,e,s,i){if(!s)return null;const o=t?.calibration;if(!o||"object"!=typeof o)return null;const n=new Set,r=[];for(const t of Object.keys(o)){const l=a(o[t]);if(!l)continue;const h=i(n);n.add(h),r.push({id:h,source:s,map_id:t,space:e,calibration:l})}return r.length?r:null}(u,e.space,m,t=>_a(t))??[],!m&&Object.keys(u.calibration||{}).length))return!1;const n=s(o);return!!n&&(async s=>{const o=i._serverCfg;if(!o)return!1;const a=JSON.parse(JSON.stringify(o));a.markers=a.markers||[];let n=a.markers.find(t=>t.id===e.id);if(!n){if("device"!==e.bindingKind&&"entity"!==e.bindingKind||!e.bindingRef)return!1;n={id:e.id,binding:`${e.bindingKind}:${e.bindingRef}`,space:e.space||null,area:e.area||null,hidden:!!e.hidden},a.markers.push(n)}n.vacuum={...n.vacuum||{},map_routes:s},delete n.vacuum.calibration;const r=i._adoption.beginOptimistic(o,a);i._adoption.stageLocalConfig(a),i._regSignature="",i._maybeRebuildDevices(),i.requestUpdate(),i._saveConfigDebounced.pending()&&i._saveConfigDebounced.cancel();try{return await t._saveConfigNow(),!0}catch(t){return i._rollbackOptimistic(r),i._regSignature="",i._maybeRebuildDevices(),i.requestUpdate(),i._showToast(i._t("toast.cfg_save_failed",{err:i._errText(t)})),!1}})(n)},x=s.candidates.filter(t=>t.entityId!==m&&!g.some(e=>e.source===t.entityId)),M=async(t,e)=>{if(!e||e===t.space)return;await i._confirmDanger({key:"vacuum_route_space",kind:"warning",title:r("vac.route_space_title"),message:r("vac.route_space_body"),objectName:t.map_id||r("vac.route_map_default"),confirmLabel:r("vac.route_space_confirm"),cancelLabel:i._t("btn.cancel")})&&await k(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,_a(new Set(g.map(t=>t.id)))))},C=new Map(f.map((t,e)=>[t.id,e])),S=(t,e)=>t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)||t.id.localeCompare(e.id),P=g.filter(t=>b.has(t.space)).sort((t,e)=>(C.get(t.space)??0)-(C.get(e.space)??0)||S(t,e)),I=g.filter(t=>!b.has(t.space)).sort(S),D=[...P,...I],L=!!m&&void 0!==$&&!g.some(t=>t.source===m&&t.map_id===$);let T=ga.get(t);const R=T?.source||"",z=T?.mapId||"",F=!!T&&g.some(t=>t.source===R&&t.map_id===z);T&&(T.markerId!==e.id||i._vacObservedMapId(e,T.source)!==T.mapId||F&&!T.saving)&&(ga.delete(t),T=void 0),T?.space&&!b.has(T.space)&&(T=ua(T,"",b),ga.set(t,T));const N=s=>p`
|
||
<li class="vacroute ${s.id===w?"on":""}" data-route-id=${s.id}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="vacroute-head">
|
||
<b>${i.map_id||r("vac.route_map_default")}</b>
|
||
${i.id===w?p`<span class="vacroute-active">${r("vac.route_active")}</span>`:d}
|
||
</div>
|
||
<small>${i.source}</small>
|
||
<div class="vacroute-status">${(t=>b.has(t.space)?t.calibration?"ambiguous"===y.kind&&y.routeIds.includes(t.id)?r("vac.route_status_ambiguous"):r("vac.route_status_ready"):r("vac.route_status_needs_calibration"):r("vac.route_status_missing_space"))(i)}</div>
|
||
<label class="srcrow">
|
||
<span>${r("vac.route_space")}</span>
|
||
<select class="areasel" @change=${t=>{const e=t.target,s=e.value;e.value=i.space,M(i,s)}}>
|
||
<option value="" ?selected=${!i.space}>${r("vac.route_space_none")}</option>
|
||
${f.map(t=>p`
|
||
<option value=${t.id} ?selected=${t.id===i.space}>${t.name}</option>`)}
|
||
</select>
|
||
</label>
|
||
<div class="vacbtns">
|
||
<button type="button" class="btn ghostbtn"
|
||
@click=${()=>t._vacStartFit(e,i.id)}>${s._t("vac.fit")}</button>
|
||
<button type="button" class="btn ghostbtn danger"
|
||
@click=${()=>{(async t=>{await s._confirmDanger({key:"vacuum_route_delete",kind:"destructive",title:r("vac.route_delete_title"),message:r("vac.route_delete_body"),objectName:t.map_id||r("vac.route_map_default"),confirmLabel:r("vac.route_delete_confirm"),cancelLabel:s._t("btn.cancel")})&&await k(e=>function(t,e){return t.filter(t=>t.id!==e)}(e,t.id))})(i)}}>${r("vac.route_delete")}</button>
|
||
</div>
|
||
</li>`,E=`vacroute-missing-${e.id.replace(/[^a-zA-Z0-9_-]/g,"-")}`;return p`
|
||
<label>${r("vac.routes_section")}</label>
|
||
<div class="bindbox vacroutes">
|
||
<div class="vacdiag" role="status">
|
||
<div><span>${r("vac.routes_current_map")}</span><b>${void 0===$?r("vac.routes_no_map"):$||r("vac.route_map_default")}</b></div>
|
||
<div><span>${r("vac.routes_status")}</span><b>${r(`vac.routes_state_${y.kind}`)}</b></div>
|
||
</div>
|
||
${P.length||T?p`<ul class="vacroute-list">
|
||
${T?p`
|
||
<li class="vacroute pending">
|
||
<div class="vacroute-head"><b>${T.mapId||r("vac.route_map_default")}</b></div>
|
||
<small>${T.source}</small>
|
||
<label class="srcrow">
|
||
<span>${r("vac.route_space")}</span>
|
||
<select class="areasel vacroute-draft-space" ?disabled=${!!T.saving}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
@change=${e=>(e=>{const i=va.get(t);i&&!i.saving&&(va.set(t,ga(i,e,b)),s.requestUpdate())})(e.target.value)}>
|
||
========
|
||
@change=${e=>(e=>{const s=ga.get(t);s&&!s.saving&&(ga.set(t,ua(s,e,b)),i.requestUpdate())})(e.target.value)}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<option value="" ?selected=${!T.space}>${r("vac.route_space_none")}</option>
|
||
${f.map(t=>p`
|
||
<option value=${t.id} ?selected=${t.id===T.space}>${t.name}</option>`)}
|
||
</select>
|
||
</label>
|
||
<div class="vacbtns">
|
||
<button type="button" class="btn ghostbtn" ?disabled=${!!T.saving}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
@click=${()=>{va.get(t)?.saving||(va.delete(t),s.requestUpdate())}}>${s._t("btn.cancel")}</button>
|
||
<button type="button" class="btn vacroute-draft-save"
|
||
?disabled=${!!T.saving||!b.has(T.space)}
|
||
@click=${()=>{(async()=>{const e=va.get(t);if(!e||e.saving||!b.has(e.space))return;va.set(t,{...e,saving:!0}),s.requestUpdate();const i=await k(t=>function(t,e,i,s){return e.source&&i.has(e.space)&&!t.some(t=>t.source===e.source&&t.map_id===e.mapId)?function(t,e,i){return[...t,{...e,id:i,calibration:e.calibration??null}]}(t,{source:e.source,map_id:e.mapId,space:e.space},s):null}(t,e,b,fa(new Set(t.map(t=>t.id))))),o=va.get(t);o?.markerId===e.markerId&&o.source===e.source&&o.mapId===e.mapId&&(i?va.delete(t):va.set(t,e)),s.requestUpdate()})()}}>${s._t("btn.save")}</button>
|
||
========
|
||
@click=${()=>{ga.get(t)?.saving||(ga.delete(t),i.requestUpdate())}}>${i._t("btn.cancel")}</button>
|
||
<button type="button" class="btn vacroute-draft-save"
|
||
?disabled=${!!T.saving||!b.has(T.space)}
|
||
@click=${()=>{(async()=>{const e=ga.get(t);if(!e||e.saving||!b.has(e.space))return;ga.set(t,{...e,saving:!0}),i.requestUpdate();const s=await k(t=>function(t,e,s,i){return e.source&&s.has(e.space)&&!t.some(t=>t.source===e.source&&t.map_id===e.mapId)?function(t,e,s){return[...t,{...e,id:s,calibration:e.calibration??null}]}(t,{source:e.source,map_id:e.mapId,space:e.space},i):null}(t,e,b,_a(new Set(t.map(t=>t.id))))),o=ga.get(t);o?.markerId===e.markerId&&o.source===e.source&&o.mapId===e.mapId&&(s?ga.delete(t):ga.set(t,e)),i.requestUpdate()})()}}>${i._t("btn.save")}</button>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
</div>
|
||
</li>`:d}
|
||
${P.map(N)}
|
||
</ul>`:d}
|
||
${I.length?p`
|
||
<section class="vacroute-missing-group" data-hp="vacuum-route-missing-group"
|
||
aria-labelledby=${E}>
|
||
<h4 class="vacroute-group-title" id=${E}>
|
||
${r("vac.route_missing_space_group")}
|
||
</h4>
|
||
<ul class="vacroute-list">${I.map(N)}</ul>
|
||
</section>`:d}
|
||
${D.length||T?d:p`<div class="rhint">${r("vac.routes_empty")}</div>`}
|
||
<div class="vacbtns">
|
||
<button type="button" class="btn vacroute-add-current" ?disabled=${!L||!!T}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
@click=${()=>{m&&void 0!==$&&(va.set(t,ma(e.id,g,e.space,m,$)),s.requestUpdate())}}>${r("vac.route_add_current")}</button>
|
||
========
|
||
@click=${()=>{m&&void 0!==$&&(ga.set(t,pa(e.id,g,e.space,m,$)),i.requestUpdate())}}>${r("vac.route_add_current")}</button>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
</div>
|
||
${x.length?p`<details class="vacroute-sources">
|
||
<summary class="btn ghostbtn">${r("vac.route_add_source")}</summary>
|
||
<div class="rhint">${r("vac.route_add_source_hint")}</div>
|
||
<div class="vacsource-list">
|
||
${x.map(i=>{const o=s._vacObservedMapId(e,i.entityId);return p`<button type="button" class="vacsource"
|
||
?disabled=${void 0===o||!!T}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
@click=${()=>(i=>{const o=s._vacObservedMapId(e,i.entityId);void 0!==o&&(va.set(t,ma(e.id,g,e.space,i.entityId,o)),s.requestUpdate())})(i)}>
|
||
<span><b>${i.name}</b><small>${i.entityId}</small></span>
|
||
========
|
||
@click=${()=>(s=>{const o=i._vacObservedMapId(e,s.entityId);void 0!==o&&(ga.set(t,pa(e.id,g,e.space,s.entityId,o)),i.requestUpdate())})(s)}>
|
||
<span><b>${s.name}</b><small>${s.entityId}</small></span>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<span class="vacsource-meta">${void 0===o?r("vac.route_source_no_map"):o||r("vac.route_map_default")}</span>
|
||
</button>`})}
|
||
</div>
|
||
</details>`:d}
|
||
${D.some(t=>!b.has(t.space))?p`
|
||
<div class="warn">${r("vac.route_missing_space_hint")}</div>`:d}
|
||
${g.some(t=>"default"===t.map_id)?p`
|
||
<div class="rhint">${r("vac.route_default_hint")}</div>`:d}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${D.length?p`<div class="rhint">${r("vac.route_target_hint",{space:ya(s,e.space)})}</div>`:d}
|
||
</div>`}const $a=new Set(["bindingOpen","bindingFilter","runFilter","controlsFilter","busy","tapHintAnnouncement","uploadId","autoIcon"]);function ka(t){return m(t,$a)}function xa(t){_(t,"marker")}const Ma=new Set(["ld2450","hlkld2450","hilinkld2450"]),Ca=()=>globalThis.crypto?.randomUUID?.()||`radar_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`,Sa=(t,e,i)=>{const s=!!t?.original;return{radar:s?t:null,radarEligible:s,radarTouched:s?e:e||!!t,radarRemove:s?i:i||!!t}},Pa=(t,e="")=>"number"==typeof t&&Number.isFinite(t)?String(t):e,Ia=t=>Array.from(new Set([...t.allEntities||t.entities||[],..."entity"===t.bindingKind&&t.bindingRef?[t.bindingRef]:[]])).filter(t=>/^[a-z0-9_]+\.[a-z0-9_]+$/.test(t)),Da=(t,e,i)=>{const s=t.split(".",2)[1]||"";return new RegExp(`(?:^|_)target_?${i}_${e}(?:_|$)`).test(s)||new RegExp(`(?:^|_)target_${e}_${i}(?:_|$)`).test(s)};function La(t,e){if(t.marker?.radar&&"object"==typeof t.marker.radar)return f(t.marker.radar)?{eligible:!0,profile:t.marker.radar.profile,reason:"saved"}:{eligible:!0,profile:"presence_v1",reason:"saved_unsupported"};const i="entity"===t.bindingKind?e?.entities?.[t.bindingRef||""]:null,s="device"===t.bindingKind?t.bindingRef:i?.device_id,o=s?e?.devices?.[s]:null,a=Ia(t);return Ma.has((n=o?.model||t.model,String(n||"").toLowerCase().replace(/[^a-z0-9]/g,"")))&&a.some(t=>Da(t,"x",1))&&a.some(t=>Da(t,"y",1))?{eligible:!0,profile:"esphome_ld2450_v1",reason:"ld2450"}:{eligible:!1,profile:"presence_v1",reason:"none"};var n}function Ta(t,e){return t.find(t=>e.some(e=>e.test(t)))||""}function Ra(t,e,i,s,o=!1){const a=La(t,s),n=f(t.marker?.radar)?t.marker.radar:null;if(!n&&!a.eligible&&!o)return null;const r=n?.profile||a.profile,l=o&&!a.eligible||"ld2450"!==a.reason?{xEntities:["","",""],yEntities:["","",""],distanceEntity:"",angleEntity:"",occupancyEntity:"",countEntity:"",zoneEntity:""}:function(t,e,i){const s=Ia(t).filter(t=>!!i?.states?.[t]),o=[],a=[];for(let t=1;t<=3;t++)o.push(s.find(e=>Da(e,"x",t))||""),a.push(s.find(e=>Da(e,"y",t))||"");const n=s.filter(t=>t.startsWith("binary_sensor.")),r=s.filter(t=>t.startsWith("sensor.")),l=Ta(n,[/(?:occupancy|presence|target)(?:_|$)/]);return{xEntities:o,yEntities:a,distanceEntity:Ta(r,[/(?:target_)?distance(?:_|$)/,/distance/]),angleEntity:Ta(r,[/(?:target_)?angle(?:_|$)/,/angle/]),occupancyEntity:l,countEntity:Ta(r,[/(?:target|people|presence)_count(?:_|$)/,/target_count/]),zoneEntity:"zones_v1"===e?Ta(n,[/(?:zone|region).*(?:occupancy|presence)/,/zone/]):""}}(t,r,s),h=n?.sources||{},c=h.slots||[],d=c.filter(t=>"x_entity"in t),p=c.filter(t=>"distance_entity"in t),u=h.ranges||[],_=h.zones?.[0],m="esphome_ld2450_v1"===r?3:"cartesian_v1"===r?Math.max(1,d.length):"polar_v1"===r?Math.max(1,p.length):1,g=n?.room_id||t.marker?.room_id||e.rooms.find(e=>e.area&&e.area===t.area)?.id||"";return{original:n,enabled:!0===n?.enabled,showLive:!1!==n?.show_live,profile:r,roomId:g,installationId:n?.mount?.installation_id||Ca(),mountX:Pa(null==n?.mount?.x?void 0:1e3*n.mount.x,Pa(i[0],"0")),mountY:Pa(null==n?.mount?.y?void 0:1e3*n.mount.y,Pa(i[1],"0")),heading:Pa(n?.mount?.heading_deg,"0"),rangeCm:Pa(n?.mount?.range_cm,"esphome_ld2450_v1"===r?"600":""),fovDeg:Pa(n?.mount?.fov_deg,"esphome_ld2450_v1"===r?"120":""),mirror:!0===n?.calibration?.mirror,unit:d[0]?.unit||p[0]?.unit||u[0]?.unit||("esphome_ld2450_v1"===r?"mm":"cm"),xEntities:Array.from({length:m},(t,e)=>d[e]?.x_entity||l.xEntities[e]||""),yEntities:Array.from({length:m},(t,e)=>d[e]?.y_entity||l.yEntities[e]||""),distanceEntities:Array.from({length:m},(t,e)=>p[e]?.distance_entity||(0===e?l.distanceEntity:"")),angleEntities:Array.from({length:m},(t,e)=>p[e]?.angle_entity||(0===e?l.angleEntity:"")),rangeEntities:u.length?u.map(t=>t.entity_id):[l.distanceEntity],slotPresenceEntities:Array.from({length:m},(t,e)=>(d[e]||p[e])?.presence_entity||""),rangePresenceEntities:(u.length?u:[{}]).map(t=>"presence_entity"in t&&t.presence_entity||""),swapXY:Array.from({length:m},(t,e)=>!0===d[e]?.swap_xy),xSigns:Array.from({length:m},(t,e)=>-1===d[e]?.x_sign?-1:1),ySigns:Array.from({length:m},(t,e)=>-1===d[e]?.y_sign?-1:1),angleUnit:p[0]?.angle_unit||"degrees",angleZero:p[0]?.angle_zero||"forward",angleClockwise:!1!==p[0]?.angle_clockwise,occupancyEntity:h.occupancy_entity||l.occupancyEntity,countEntity:h.count_entity||l.countEntity,availabilityEntity:h.availability_entity||"",zoneEntity:_?.entity_id||l.zoneEntity,zoneKind:_?.kind||"occupancy"}}const Fa=t=>JSON.stringify(t,(t,e)=>e&&"object"==typeof e&&!Array.isArray(e)?Object.fromEntries(Object.entries(e).sort(([t],[e])=>t<e?-1:t>e?1:0)):e),za=t=>{if(!t.trim())return null;const e=Number(t.replace(",","."));return Number.isFinite(e)?e:null};function Na(t,e){const i=za(t.mountX),s=za(t.mountY),o=za(t.heading);if(!t.roomId||null==i||null==s||null==o)return null;const a={...t.original?.sources||{}};if(delete a.slots,delete a.ranges,delete a.zones,delete a.occupancy_entity,delete a.count_entity,"esphome_ld2450_v1"===t.profile||"cartesian_v1"===t.profile){if(a.slots=t.xEntities.flatMap((e,i)=>{const s=t.yEntities[i]||"";return e&&s?[{id:`target_${i+1}`,x_entity:e,y_entity:s,unit:"esphome_ld2450_v1"===t.profile?"mm":t.unit,..."cartesian_v1"===t.profile&&t.swapXY[i]?{swap_xy:!0}:{},..."cartesian_v1"===t.profile&&-1===t.xSigns[i]?{x_sign:-1}:{},..."cartesian_v1"===t.profile&&-1===t.ySigns[i]?{y_sign:-1}:{},...t.slotPresenceEntities[i]?{presence_entity:t.slotPresenceEntities[i]}:{}}]:[]}),!a.slots.length)return null}else if("polar_v1"===t.profile){if(a.slots=t.distanceEntities.flatMap((e,i)=>{const s=t.angleEntities[i]||"";return e&&s?[{id:`target_${i+1}`,distance_entity:e,angle_entity:s,unit:t.unit,angle_unit:t.angleUnit,angle_zero:t.angleZero,angle_clockwise:t.angleClockwise,...t.slotPresenceEntities[i]?{presence_entity:t.slotPresenceEntities[i]}:{}}]:[]}),!a.slots.length)return null}else if("range_v1"===t.profile){if(a.ranges=t.rangeEntities.flatMap((e,i)=>e?[{id:`range_${i+1}`,entity_id:e,unit:t.unit,...t.rangePresenceEntities[i]?{presence_entity:t.rangePresenceEntities[i]}:{}}]:[]),!a.ranges.length)return null}else if("zones_v1"===t.profile){if(!t.zoneEntity)return null;a.zones=[{id:"zone_1",kind:t.zoneKind,entity_id:t.zoneEntity}]}else if("presence_v1"===t.profile&&!t.occupancyEntity)return null;t.occupancyEntity&&(a.occupancy_entity=t.occupancyEntity),t.countEntity&&(a.count_entity=t.countEntity),t.availabilityEntity&&(a.availability_entity=t.availabilityEntity);const n=za(t.rangeCm),r=za(t.fovDeg),l=(o%360+360)%360,h={...t.original?.mount||{},installation_id:t.installationId,x:i/1e3,y:s/1e3,heading_deg:l};null!=n&&n>0?h.range_cm=n:delete h.range_cm,null!=r&&r>0?h.fov_deg=r:delete h.fov_deg;const c=t.original,d="two_point"===c?.calibration?.method&&c.profile===t.profile&&Fa(c.sources)===Fa(a)&&c.mount.installation_id===t.installationId&&Math.abs(c.mount.x-h.x)<1e-12&&Math.abs(c.mount.y-h.y)<1e-12&&Math.abs(c.mount.heading_deg-l)<1e-9&&c.calibration.mirror===t.mirror&&Math.abs(c.calibration.cell_cm-e)<1e-9,p=t.calibrationOverride?{...t.calibrationOverride}:d?{...c.calibration}:{...c?.calibration||{},method:"zones_v1"===t.profile||"presence_v1"===t.profile?"not_required":"manual",mirror:t.mirror,cell_cm:e};t.calibrationOverride||d||(delete p.refs,delete p.rms_cm);const u={...t.original||{},version:1,enabled:t.enabled,profile:t.profile,sources:a,mount:h,room_id:t.roomId,calibration:p};return t.showLive?delete u.show_live:u.show_live=!1,u}const Ea={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon",value_static_icon:"display.value_static_icon"},Aa={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon",value_static_icon:"marker.display_hint_value_static_icon"},Oa=["top","right","bottom","left"];function Ba(t,e,i){return p`<span id=${d} class="hpf-note ${"warning"===e?"hpf-note-warning":""}"
|
||
role=${"warning"===e?"status":"note"}>
|
||
<ha-icon icon=${"warning"===e?"mdi:alert-outline":"mdi:information-outline"}></ha-icon><span>${t}</span>
|
||
</span>`}function Ha(){wo(this.host);const t=this.host._markerDialog,e=this.host._t.bind(this.host),{st:i,shelp:s}=$o(this.host),o="virtual"===t.bindingMode,a=this._bindingCandidates(),n=o?null:this.host._bindingStatus(t.binding),r=!o&&this.host._bindingHasHaPage(t.binding),l=this._markerPreviewDevice(t),h=this._effectiveMarkerTapAction(t,l),c=l?b(this.host._serverCfg?.spaces.find(t=>t.id===l.space)):null,u=l?this._markerPreviewDevices(l):this.host._devices,_="toggle"===h&&l?this._toggleIntent(l,u):null,m=this._toggleHintLines(_),f=l?v(this.host._planHass,l,{liveStates:!1!==this.host._config?.live_states,showTemperature:!1!==this.host._config?.show_temperature,showSignal:c?.showLqi??!1!==this.host._config?.show_signal,designPreview:!0,activityRuntime:this.host._activityRt.get(l.id),lightDevices:u,registryHass:this.host._fullRegistryHass,reducedMotion:this.host._reducedMotion}):null,E=l?y(this.host._planHass,l,u):[],A=l?w(this.host._planHass,l,E):null,O=t.valueBadgeTouched?t.valueBadgeEnabled:!!f?.valueBadge,B=t.valueBadgeTouched?t.valueBadgeSource:f?.valueBadge?.source||t.valueBadgeSource,H=t.valueBadgeTouched?t.valueBadgePosition:f?.valueBadge?.position||t.valueBadgePosition,W=$(B),G=!!B&&!E.some(t=>t.key===W),j=E.find(t=>t.key===W),U=$(t.valueSource),q=!(!t.valueSource||U&&E.some(t=>t.key===U)),K=E.find(t=>t.key===U),V=f?.valueSource?.sourceKey||"",J=this._markerAutoHasSpatialSource(t),Y=!!l&&k(this.host._planHass,{...l}),Z=x(t.lightRole,J,Y,t.glowMode),X=!Z.sourceExists,Q=!Z.fromSourceEnabled,tt=Z.passive,et=Z.effectiveMode,it="never"===t.lightRole?e("marker.glow_disabled_never"):"auto"!==t.lightRole||J?e(tt?"marker.glow_passive_hint":"marker.glow_disabled_no_entity"):e("marker.glow_disabled_auto"),st=l?M(l):[],ot=l&&C(l)||"",at=!!t.lightEntity&&!st.includes(t.lightEntity),nt=l?S(l):[],rt=!!t.toggleEntity&&!nt.includes(t.toggleEntity),lt="toggle"===h?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,ht=lt?[...lt.targets,...lt.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",ct=(()=>{if(o)return null;const e=a.find(e=>e.value===t.binding);if(e)return e.label;const[i,s]=t.binding.split(":");return"device"===i?this.host._fullRegistryHass.devices[s]?.name_by_user||this.host._fullRegistryHass.devices[s]?.name||s:this.host._fullRegistryHass.entities[s]?.name||this.host.hass.states[s]?.attributes?.friendly_name||s})(),dt=t=>this.host.hass.states[t]?.attributes?.friendly_name||this.host._fullRegistryHass.entities[t]?.name||t,pt=this.host._imperial?e("gs.unit_ft"):e("gs.unit_m"),ut=!!t.devId,_t=function(t,e=t.tapAction){const i=[];return"virtual"!==t.binding||t.name.trim()||i.push({field:"marker-name",message:"marker.error_virtual_name"}),"ha"!==t.bindingMode||t.binding&&"virtual"!==t.binding||i.push({field:"marker-binding",message:"marker.error_binding"}),"run"!==e||t.tapTarget||i.push({field:"marker-run-target",message:"marker.error_run_target"}),t.valueBadgeTouched&&t.valueBadgeEnabled&&!t.valueBadgeSource&&i.push({field:"marker-value-badge-source",message:"marker.error_value_badge_source"}),i}(t,h),mt=t=>_t.find(e=>e.field===t),gt=function(t,e){return g(t,"marker",ka(e))}(this.host,t),ft="ha"===t.bindingMode&&!t.devId&&"active"!==n?.kind,bt=!t.busy&&!this._radarSetup.isActive()&&0===_t.length&&!ft&&(!ut||gt),vt=_t[0]?i(_t[0].message):ft&&t.binding&&"virtual"!==t.binding?e("marker.ha_registry_limited"):"",yt=async e=>{if(!ut||!gt)return xa(this.host),void this._closeMarkerDialog();const s=e.currentTarget;await this.host._confirmDanger({key:"discard-marker-dialog",kind:"warning",title:i("dialog.discard_title"),message:i("dialog.discard_message"),objectName:t.name.trim()||l?.name||void 0,confirmLabel:i("dialog.discard_confirm"),cancelLabel:i("dialog.discard_keep"),icon:"mdi:content-save-off-outline",confirmIcon:"mdi:content-save-off-outline"})?(xa(this.host),this._closeMarkerDialog()):s?.rejectClose?.()},wt=mt("marker-binding"),$t=mt("marker-name"),kt=mt("marker-run-target"),xt=mt("marker-value-badge-source"),Mt="ha_disabled"===n?.kind?ko({kind:"warning",role:"status",icon:"mdi:power-plug-off-outline",text:e(`marker.ha_disabled_${n.reason}`),action:r?xo(e("btn.open_in_ha"),()=>this.host._openBindingInHa(t.binding)):void 0}):"unverified"===n?.kind&&t.binding?ko({kind:"warning",role:"status",icon:"mdi:shield-alert-outline",text:e("marker.ha_registry_limited")}):d,Ct="ha"===t.bindingMode?Mo({id:"marker-binding",open:t.bindingOpen,current:ct?{label:ct,sub:`${t.binding}${"ha_disabled"===n?.kind?` · ${e("marker.binding_disabled")}`:""}`}:null,placeholder:e("marker.pick_ph"),ariaLabel:e("marker.binding_label"),filter:t.bindingFilter,filterPlaceholder:e("marker.search_ph"),candidates:a,selected:t.binding,emptyText:e("marker.nothing_found"),onToggle:()=>this.host._markerDialog={...t,bindingOpen:!t.bindingOpen},onFilter:e=>this.host._markerDialog={...t,bindingFilter:e},onPick:e=>{if(e===t.binding)return void(this.host._markerDialog={...t,bindingOpen:!1});const i={...t,binding:e,bindingOpen:!1,controls:N(e,t.controls,this.host._bindingEntities(e)),autoIcon:this.host._autoIconForBinding(e),...Sa(t.radar,t.radarTouched,t.radarRemove)};this.host._markerDialog=this._announceToggleDraft({...i,...this._valueBadgeForBinding(i,e),valueSource:null,valueSourceTouched:!0})},toolbar:p`<label class="hpf-check" title=${e("marker.show_entities_tip")}>
|
||
========
|
||
${D.length?p`<div class="rhint">${r("vac.route_target_hint",{space:fa(i,e.space)})}</div>`:d}
|
||
</div>`}const va=new Set(["bindingOpen","bindingFilter","runFilter","controlsFilter","busy","tapHintAnnouncement","uploadId","autoIcon"]);function ya(t){return m(t,va)}function wa(t){_(t,"marker")}const $a=new Set(["ld2450","hlkld2450","hilinkld2450"]),ka=()=>globalThis.crypto?.randomUUID?.()||`radar_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`,xa=(t,e,s)=>{const i=!!t?.original;return{radar:i?t:null,radarEligible:i,radarTouched:i?e:e||!!t,radarRemove:i?s:s||!!t}},Ma=(t,e="")=>"number"==typeof t&&Number.isFinite(t)?String(t):e,Ca=t=>Array.from(new Set([...t.allEntities||t.entities||[],..."entity"===t.bindingKind&&t.bindingRef?[t.bindingRef]:[]])).filter(t=>/^[a-z0-9_]+\.[a-z0-9_]+$/.test(t)),Sa=(t,e,s)=>{const i=t.split(".",2)[1]||"";return new RegExp(`(?:^|_)target_?${s}_${e}(?:_|$)`).test(i)||new RegExp(`(?:^|_)target_${e}_${s}(?:_|$)`).test(i)};function Pa(t,e){if(t.marker?.radar&&"object"==typeof t.marker.radar)return f(t.marker.radar)?{eligible:!0,profile:t.marker.radar.profile,reason:"saved"}:{eligible:!0,profile:"presence_v1",reason:"saved_unsupported"};const s="entity"===t.bindingKind?e?.entities?.[t.bindingRef||""]:null,i="device"===t.bindingKind?t.bindingRef:s?.device_id,o=i?e?.devices?.[i]:null,a=Ca(t);return $a.has((n=o?.model||t.model,String(n||"").toLowerCase().replace(/[^a-z0-9]/g,"")))&&a.some(t=>Sa(t,"x",1))&&a.some(t=>Sa(t,"y",1))?{eligible:!0,profile:"esphome_ld2450_v1",reason:"ld2450"}:{eligible:!1,profile:"presence_v1",reason:"none"};var n}function Ia(t,e){return t.find(t=>e.some(e=>e.test(t)))||""}function Da(t,e,s,i,o=!1){const a=Pa(t,i),n=f(t.marker?.radar)?t.marker.radar:null;if(!n&&!a.eligible&&!o)return null;const r=n?.profile||a.profile,l=o&&!a.eligible||"ld2450"!==a.reason?{xEntities:["","",""],yEntities:["","",""],distanceEntity:"",angleEntity:"",occupancyEntity:"",countEntity:"",zoneEntity:""}:function(t,e,s){const i=Ca(t).filter(t=>!!s?.states?.[t]),o=[],a=[];for(let t=1;t<=3;t++)o.push(i.find(e=>Sa(e,"x",t))||""),a.push(i.find(e=>Sa(e,"y",t))||"");const n=i.filter(t=>t.startsWith("binary_sensor.")),r=i.filter(t=>t.startsWith("sensor.")),l=Ia(n,[/(?:occupancy|presence|target)(?:_|$)/]);return{xEntities:o,yEntities:a,distanceEntity:Ia(r,[/(?:target_)?distance(?:_|$)/,/distance/]),angleEntity:Ia(r,[/(?:target_)?angle(?:_|$)/,/angle/]),occupancyEntity:l,countEntity:Ia(r,[/(?:target|people|presence)_count(?:_|$)/,/target_count/]),zoneEntity:"zones_v1"===e?Ia(n,[/(?:zone|region).*(?:occupancy|presence)/,/zone/]):""}}(t,r,i),h=n?.sources||{},c=h.slots||[],d=c.filter(t=>"x_entity"in t),p=c.filter(t=>"distance_entity"in t),u=h.ranges||[],_=h.zones?.[0],m="esphome_ld2450_v1"===r?3:"cartesian_v1"===r?Math.max(1,d.length):"polar_v1"===r?Math.max(1,p.length):1,g=n?.room_id||t.marker?.room_id||e.rooms.find(e=>e.area&&e.area===t.area)?.id||"";return{original:n,enabled:!0===n?.enabled,showLive:!1!==n?.show_live,profile:r,roomId:g,installationId:n?.mount?.installation_id||ka(),mountX:Ma(null==n?.mount?.x?void 0:1e3*n.mount.x,Ma(s[0],"0")),mountY:Ma(null==n?.mount?.y?void 0:1e3*n.mount.y,Ma(s[1],"0")),heading:Ma(n?.mount?.heading_deg,"0"),rangeCm:Ma(n?.mount?.range_cm,"esphome_ld2450_v1"===r?"600":""),fovDeg:Ma(n?.mount?.fov_deg,"esphome_ld2450_v1"===r?"120":""),mirror:!0===n?.calibration?.mirror,unit:d[0]?.unit||p[0]?.unit||u[0]?.unit||("esphome_ld2450_v1"===r?"mm":"cm"),xEntities:Array.from({length:m},(t,e)=>d[e]?.x_entity||l.xEntities[e]||""),yEntities:Array.from({length:m},(t,e)=>d[e]?.y_entity||l.yEntities[e]||""),distanceEntities:Array.from({length:m},(t,e)=>p[e]?.distance_entity||(0===e?l.distanceEntity:"")),angleEntities:Array.from({length:m},(t,e)=>p[e]?.angle_entity||(0===e?l.angleEntity:"")),rangeEntities:u.length?u.map(t=>t.entity_id):[l.distanceEntity],slotPresenceEntities:Array.from({length:m},(t,e)=>(d[e]||p[e])?.presence_entity||""),rangePresenceEntities:(u.length?u:[{}]).map(t=>"presence_entity"in t&&t.presence_entity||""),swapXY:Array.from({length:m},(t,e)=>!0===d[e]?.swap_xy),xSigns:Array.from({length:m},(t,e)=>-1===d[e]?.x_sign?-1:1),ySigns:Array.from({length:m},(t,e)=>-1===d[e]?.y_sign?-1:1),angleUnit:p[0]?.angle_unit||"degrees",angleZero:p[0]?.angle_zero||"forward",angleClockwise:!1!==p[0]?.angle_clockwise,occupancyEntity:h.occupancy_entity||l.occupancyEntity,countEntity:h.count_entity||l.countEntity,availabilityEntity:h.availability_entity||"",zoneEntity:_?.entity_id||l.zoneEntity,zoneKind:_?.kind||"occupancy"}}const La=t=>JSON.stringify(t,(t,e)=>e&&"object"==typeof e&&!Array.isArray(e)?Object.fromEntries(Object.entries(e).sort(([t],[e])=>t<e?-1:t>e?1:0)):e),Ta=t=>{if(!t.trim())return null;const e=Number(t.replace(",","."));return Number.isFinite(e)?e:null};function Ra(t,e){const s=Ta(t.mountX),i=Ta(t.mountY),o=Ta(t.heading);if(!t.roomId||null==s||null==i||null==o)return null;const a={...t.original?.sources||{}};if(delete a.slots,delete a.ranges,delete a.zones,delete a.occupancy_entity,delete a.count_entity,"esphome_ld2450_v1"===t.profile||"cartesian_v1"===t.profile){if(a.slots=t.xEntities.flatMap((e,s)=>{const i=t.yEntities[s]||"";return e&&i?[{id:`target_${s+1}`,x_entity:e,y_entity:i,unit:"esphome_ld2450_v1"===t.profile?"mm":t.unit,..."cartesian_v1"===t.profile&&t.swapXY[s]?{swap_xy:!0}:{},..."cartesian_v1"===t.profile&&-1===t.xSigns[s]?{x_sign:-1}:{},..."cartesian_v1"===t.profile&&-1===t.ySigns[s]?{y_sign:-1}:{},...t.slotPresenceEntities[s]?{presence_entity:t.slotPresenceEntities[s]}:{}}]:[]}),!a.slots.length)return null}else if("polar_v1"===t.profile){if(a.slots=t.distanceEntities.flatMap((e,s)=>{const i=t.angleEntities[s]||"";return e&&i?[{id:`target_${s+1}`,distance_entity:e,angle_entity:i,unit:t.unit,angle_unit:t.angleUnit,angle_zero:t.angleZero,angle_clockwise:t.angleClockwise,...t.slotPresenceEntities[s]?{presence_entity:t.slotPresenceEntities[s]}:{}}]:[]}),!a.slots.length)return null}else if("range_v1"===t.profile){if(a.ranges=t.rangeEntities.flatMap((e,s)=>e?[{id:`range_${s+1}`,entity_id:e,unit:t.unit,...t.rangePresenceEntities[s]?{presence_entity:t.rangePresenceEntities[s]}:{}}]:[]),!a.ranges.length)return null}else if("zones_v1"===t.profile){if(!t.zoneEntity)return null;a.zones=[{id:"zone_1",kind:t.zoneKind,entity_id:t.zoneEntity}]}else if("presence_v1"===t.profile&&!t.occupancyEntity)return null;t.occupancyEntity&&(a.occupancy_entity=t.occupancyEntity),t.countEntity&&(a.count_entity=t.countEntity),t.availabilityEntity&&(a.availability_entity=t.availabilityEntity);const n=Ta(t.rangeCm),r=Ta(t.fovDeg),l=(o%360+360)%360,h={...t.original?.mount||{},installation_id:t.installationId,x:s/1e3,y:i/1e3,heading_deg:l};null!=n&&n>0?h.range_cm=n:delete h.range_cm,null!=r&&r>0?h.fov_deg=r:delete h.fov_deg;const c=t.original,d="two_point"===c?.calibration?.method&&c.profile===t.profile&&La(c.sources)===La(a)&&c.mount.installation_id===t.installationId&&Math.abs(c.mount.x-h.x)<1e-12&&Math.abs(c.mount.y-h.y)<1e-12&&Math.abs(c.mount.heading_deg-l)<1e-9&&c.calibration.mirror===t.mirror&&Math.abs(c.calibration.cell_cm-e)<1e-9,p=t.calibrationOverride?{...t.calibrationOverride}:d?{...c.calibration}:{...c?.calibration||{},method:"zones_v1"===t.profile||"presence_v1"===t.profile?"not_required":"manual",mirror:t.mirror,cell_cm:e};t.calibrationOverride||d||(delete p.refs,delete p.rms_cm);const u={...t.original||{},version:1,enabled:t.enabled,profile:t.profile,sources:a,mount:h,room_id:t.roomId,calibration:p};return t.showLive?delete u.show_live:u.show_live=!1,u}const za={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon",value_static_icon:"display.value_static_icon"},Fa={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon",value_static_icon:"marker.display_hint_value_static_icon"},Na=["top","right","bottom","left"];function Aa(t,e,s){return p`<span id=${d} class="hpf-note ${"warning"===e?"hpf-note-warning":""}"
|
||
role=${"warning"===e?"status":"note"}>
|
||
<ha-icon icon=${"warning"===e?"mdi:alert-outline":"mdi:information-outline"}></ha-icon><span>${t}</span>
|
||
</span>`}function Ea(){vo(this.host);const t=this.host._markerDialog,e=this.host._t.bind(this.host),{st:s,shelp:i}=yo(this.host),o="virtual"===t.bindingMode,a=this._bindingCandidates(),n=o?null:this.host._bindingStatus(t.binding),r=!o&&this.host._bindingHasHaPage(t.binding),l=this._markerPreviewDevice(t),h=this._effectiveMarkerTapAction(t,l),c=l?b(this.host._serverCfg?.spaces.find(t=>t.id===l.space)):null,u=l?this._markerPreviewDevices(l):this.host._devices,_="toggle"===h&&l?this._toggleIntent(l,u):null,m=this._toggleHintLines(_),f=l?v(this.host._planHass,l,{liveStates:!1!==this.host._config?.live_states,showTemperature:!1!==this.host._config?.show_temperature,showSignal:c?.showLqi??!1!==this.host._config?.show_signal,designPreview:!0,activityRuntime:this.host._activityRt.get(l.id),lightDevices:u,registryHass:this.host._fullRegistryHass,reducedMotion:this.host._reducedMotion}):null,A=l?y(this.host._planHass,l,u):[],E=l?w(this.host._planHass,l,A):null,O=t.valueBadgeTouched?t.valueBadgeEnabled:!!f?.valueBadge,B=t.valueBadgeTouched?t.valueBadgeSource:f?.valueBadge?.source||t.valueBadgeSource,H=t.valueBadgeTouched?t.valueBadgePosition:f?.valueBadge?.position||t.valueBadgePosition,W=$(B),j=!!B&&!A.some(t=>t.key===W),G=A.find(t=>t.key===W),q=$(t.valueSource),U=!(!t.valueSource||q&&A.some(t=>t.key===q)),K=A.find(t=>t.key===q),V=f?.valueSource?.sourceKey||"",J=this._markerAutoHasSpatialSource(t),Z=!!l&&k(this.host._planHass,{...l}),Y=x(t.lightRole,J,Z,t.glowMode),X=!Y.sourceExists,Q=!Y.fromSourceEnabled,tt=Y.passive,et=Y.effectiveMode,st="never"===t.lightRole?e("marker.glow_disabled_never"):"auto"!==t.lightRole||J?e(tt?"marker.glow_passive_hint":"marker.glow_disabled_no_entity"):e("marker.glow_disabled_auto"),it=l?M(l):[],ot=l&&C(l)||"",at=!!t.lightEntity&&!it.includes(t.lightEntity),nt=l?S(l):[],rt=!!t.toggleEntity&&!nt.includes(t.toggleEntity),lt="toggle"===h?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,ht=lt?[...lt.targets,...lt.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",ct=(()=>{if(o)return null;const e=a.find(e=>e.value===t.binding);if(e)return e.label;const[s,i]=t.binding.split(":");return"device"===s?this.host._fullRegistryHass.devices[i]?.name_by_user||this.host._fullRegistryHass.devices[i]?.name||i:this.host._fullRegistryHass.entities[i]?.name||this.host.hass.states[i]?.attributes?.friendly_name||i})(),dt=t=>this.host.hass.states[t]?.attributes?.friendly_name||this.host._fullRegistryHass.entities[t]?.name||t,pt=this.host._imperial?e("gs.unit_ft"):e("gs.unit_m"),ut=!!t.devId,_t=function(t,e=t.tapAction){const s=[];return"virtual"!==t.binding||t.name.trim()||s.push({field:"marker-name",message:"marker.error_virtual_name"}),"ha"!==t.bindingMode||t.binding&&"virtual"!==t.binding||s.push({field:"marker-binding",message:"marker.error_binding"}),"run"!==e||t.tapTarget||s.push({field:"marker-run-target",message:"marker.error_run_target"}),t.valueBadgeTouched&&t.valueBadgeEnabled&&!t.valueBadgeSource&&s.push({field:"marker-value-badge-source",message:"marker.error_value_badge_source"}),s}(t,h),mt=t=>_t.find(e=>e.field===t),gt=function(t,e){return g(t,"marker",ya(e))}(this.host,t),ft="ha"===t.bindingMode&&!t.devId&&"active"!==n?.kind,bt=!t.busy&&!this._radarSetup.isActive()&&0===_t.length&&!ft&&(!ut||gt),vt=_t[0]?s(_t[0].message):ft&&t.binding&&"virtual"!==t.binding?e("marker.ha_registry_limited"):"",yt=async e=>{if(!ut||!gt)return wa(this.host),void this._closeMarkerDialog();const i=e.currentTarget;await this.host._confirmDanger({key:"discard-marker-dialog",kind:"warning",title:s("dialog.discard_title"),message:s("dialog.discard_message"),objectName:t.name.trim()||l?.name||void 0,confirmLabel:s("dialog.discard_confirm"),cancelLabel:s("dialog.discard_keep"),icon:"mdi:content-save-off-outline",confirmIcon:"mdi:content-save-off-outline"})?(wa(this.host),this._closeMarkerDialog()):i?.rejectClose?.()},wt=mt("marker-binding"),$t=mt("marker-name"),kt=mt("marker-run-target"),xt=mt("marker-value-badge-source"),Mt="ha_disabled"===n?.kind?wo({kind:"warning",role:"status",icon:"mdi:power-plug-off-outline",text:e(`marker.ha_disabled_${n.reason}`),action:r?$o(e("btn.open_in_ha"),()=>this.host._openBindingInHa(t.binding)):void 0}):"unverified"===n?.kind&&t.binding?wo({kind:"warning",role:"status",icon:"mdi:shield-alert-outline",text:e("marker.ha_registry_limited")}):d,Ct="ha"===t.bindingMode?ko({id:"marker-binding",open:t.bindingOpen,current:ct?{label:ct,sub:`${t.binding}${"ha_disabled"===n?.kind?` · ${e("marker.binding_disabled")}`:""}`}:null,placeholder:e("marker.pick_ph"),ariaLabel:e("marker.binding_label"),filter:t.bindingFilter,filterPlaceholder:e("marker.search_ph"),candidates:a,selected:t.binding,emptyText:e("marker.nothing_found"),onToggle:()=>this.host._markerDialog={...t,bindingOpen:!t.bindingOpen},onFilter:e=>this.host._markerDialog={...t,bindingFilter:e},onPick:e=>{if(e===t.binding)return void(this.host._markerDialog={...t,bindingOpen:!1});const s={...t,binding:e,bindingOpen:!1,controls:N(e,t.controls,this.host._bindingEntities(e)),autoIcon:this.host._autoIconForBinding(e),...xa(t.radar,t.radarTouched,t.radarRemove)};this.host._markerDialog=this._announceToggleDraft({...s,...this._valueBadgeForBinding(s,e),valueSource:null,valueSourceTouched:!0})},toolbar:p`<label class="hpf-check" title=${e("marker.show_entities_tip")}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<input id="marker-show-entities" type="checkbox" .checked=${t.showEntities}
|
||
@change=${e=>this.host._markerDialog={...t,showEntities:e.target.checked}} />
|
||
<span>${e("marker.show_entities")}</span>
|
||
</label>`}):d,St=Co({id:"basics",title:e("marker.card_basics"),body:p`
|
||
${Mt}
|
||
${So({label:e("marker.name_label"),htmlFor:"marker-name",error:$t?i($t.message):void 0,control:p`<input id="marker-name" class="hpf-input" type="text" placeholder=${e("marker.name_ph")}
|
||
aria-invalid=${$t?"true":d}
|
||
.value=${t.name}
|
||
@input=${e=>this.host._markerDialog={...t,name:e.target.value}} />`})}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${So({label:e("marker.binding_label"),help:s("marker.binding.help"),error:wt?i(wt.message):void 0,hint:o?i("marker.binding_virtual_hint"):void 0,control:p`${Po({name:"bmode",value:t.bindingMode,ariaLabel:e("marker.binding_label"),options:[{value:"virtual",label:e("marker.virtual_option")},{value:"ha",label:e("marker.from_ha_option")}],onChange:e=>{if("virtual"===e){const e={...t,bindingMode:"virtual",binding:"virtual",bindingOpen:!1,controls:N("virtual",t.controls),autoIcon:this.host._autoIconForBinding("virtual"),...Sa(t.radar,t.radarTouched,t.radarRemove)};return void(this.host._markerDialog=this._announceToggleDraft({...e,...this._valueBadgeForBinding(e,"virtual"),valueSource:null,valueSourceTouched:!0}))}this.host._markerDialog=this._announceToggleDraft({...t,bindingMode:"ha",binding:"virtual"===t.binding?"":t.binding,bindingOpen:"virtual"===t.binding||!t.binding})}})}${Ct}`})}
|
||
${So({label:e("marker.room_label"),htmlFor:"marker-room",hint:t.room?i("marker.room_hint_override"):o?void 0:i("marker.room_hint_auto"),control:p`<select id="marker-room" class="hpf-select"
|
||
@change=${e=>{const i=e.target.value,s=P(i);this.host._markerDialog={...t,room:i,roomTouched:!0,radar:t.radar&&s?.space===(l?.space||"")&&s.roomId?{...t.radar,roomId:s.roomId}:t.radar,radarTouched:!(!t.radar||!s?.roomId)||t.radarTouched}}}>
|
||
========
|
||
${Mo({label:e("marker.binding_label"),help:i("marker.binding.help"),error:wt?s(wt.message):void 0,hint:o?s("marker.binding_virtual_hint"):void 0,control:p`${Co({name:"bmode",value:t.bindingMode,ariaLabel:e("marker.binding_label"),options:[{value:"virtual",label:e("marker.virtual_option")},{value:"ha",label:e("marker.from_ha_option")}],onChange:e=>{if("virtual"===e){const e={...t,bindingMode:"virtual",binding:"virtual",bindingOpen:!1,controls:N("virtual",t.controls),autoIcon:this.host._autoIconForBinding("virtual"),...xa(t.radar,t.radarTouched,t.radarRemove)};return void(this.host._markerDialog=this._announceToggleDraft({...e,...this._valueBadgeForBinding(e,"virtual"),valueSource:null,valueSourceTouched:!0}))}this.host._markerDialog=this._announceToggleDraft({...t,bindingMode:"ha",binding:"virtual"===t.binding?"":t.binding,bindingOpen:"virtual"===t.binding||!t.binding})}})}${Ct}`})}
|
||
${Mo({label:e("marker.room_label"),htmlFor:"marker-room",hint:t.room?s("marker.room_hint_override"):o?void 0:s("marker.room_hint_auto"),control:p`<select id="marker-room" class="hpf-select"
|
||
@change=${e=>{const s=e.target.value,i=P(s);this.host._markerDialog={...t,room:s,roomTouched:!0,radar:t.radar&&i?.space===(l?.space||"")&&i.roomId?{...t.radar,roomId:i.roomId}:t.radar,radarTouched:!(!t.radar||!i?.roomId)||t.radarTouched}}}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<option value="" ?selected=${!t.room}>
|
||
${e(o?"marker.room_choose":"marker.room_auto")}
|
||
</option>
|
||
${this.host._allRoomsFlat().map(e=>p`<option value=${e.value} ?selected=${e.value===t.room}>${e.label}</option>`)}
|
||
</select>`})}
|
||
${this._renderVacSection(t)}`}),Pt="toggle"===h&&(nt.length>1||rt)?p`<div class="markertoggleentity">${So({label:e("marker.toggle_entity_label"),htmlFor:"marker-toggle-entity",help:this._help("marker.toggle_entity.help"),control:p`<select id="marker-toggle-entity" class="hpf-select"
|
||
@change=${e=>{const i={...t,toggleEntity:e.target.value,toggleEntityTouched:!0};this.host._markerDialog=this._announceToggleDraft(i)}}>
|
||
<option value="" ?selected=${rt||!t.toggleEntity}>
|
||
${e("marker.toggle_entity_auto",{entity:ht||e("marker.toggle_entity_none")})}
|
||
</option>
|
||
${nt.map(e=>p`<option value=${e}
|
||
?selected=${!rt&&e===t.toggleEntity}>
|
||
${dt(e)} · ${e}
|
||
</option>`)}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</select>`,hint:rt?Ba(e("marker.toggle_entity_missing",{entity:t.toggleEntity,fallback:ht||e("marker.toggle_entity_none")}),"warning"):void 0})}</div>`:d,It="run"===h?(()=>{const s=t.runFilter.trim().toLowerCase(),o=this._runCandidates().filter(t=>!s||t.label.toLowerCase().includes(s)||t.value.includes(s)),a=t.tapTarget?this._runCandidates().find(e=>e.value===t.tapTarget):null;return So({label:e("marker.run_target_label"),htmlFor:"marker-run-target",error:kt?i(kt.message):void 0,control:p`
|
||
${t.tapTarget&&!a?ko({kind:"warning",role:"status",text:e("marker.run_target_gone",{id:t.tapTarget})}):d}
|
||
========
|
||
</select>`,hint:rt?Aa(e("marker.toggle_entity_missing",{entity:t.toggleEntity,fallback:ht||e("marker.toggle_entity_none")}),"warning"):void 0})}</div>`:d,It="run"===h?(()=>{const i=t.runFilter.trim().toLowerCase(),o=this._runCandidates().filter(t=>!i||t.label.toLowerCase().includes(i)||t.value.includes(i)),a=t.tapTarget?this._runCandidates().find(e=>e.value===t.tapTarget):null;return Mo({label:e("marker.run_target_label"),htmlFor:"marker-run-target",error:kt?s(kt.message):void 0,control:p`
|
||
${t.tapTarget&&!a?wo({kind:"warning",role:"status",text:e("marker.run_target_gone",{id:t.tapTarget})}):d}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<input id="marker-run-target" class="hpf-input" type="text" placeholder=${e("marker.run_search_ph")}
|
||
aria-invalid=${kt?"true":d}
|
||
.value=${a?a.label:t.runFilter}
|
||
@focus=${t=>{t.target.select()}}
|
||
@input=${e=>this.host._markerDialog={...t,runFilter:e.target.value,tapTarget:""}} />
|
||
${a?d:p`<div class="hpf-panel"><div class="hpf-list" role="listbox" aria-label=${e("marker.run_target_label")}>
|
||
${o.slice(0,40).map(e=>p`<button type="button" role="option" class="hpf-cand ${e.value===t.tapTarget?"sel":""}"
|
||
aria-selected=${e.value===t.tapTarget?"true":"false"}
|
||
@click=${()=>this.host._markerDialog={...t,tapTarget:e.value,runFilter:""}}>
|
||
<span>${e.label}</span><small>${e.sub}</small>
|
||
</button>`)}
|
||
${o.length?d:p`<p class="hpf-hint">${e("marker.nothing_found")}</p>`}
|
||
</div></div>`}`})})():d,Dt=t.controlsFilter.trim()?this._controlCandidates(t):[],Lt=Co({id:"tap",body:p`
|
||
${So({label:e("marker.tap_label"),htmlFor:"marker-tap-action",control:p`<select id="marker-tap-action" class="hpf-select"
|
||
aria-describedby=${"toggle"===h?"marker-toggle-hint":d}
|
||
@change=${e=>{const i={...t,tapAction:e.target.value,tapActionTouched:!0};this.host._markerDialog=this._announceToggleDraft(i)}}>
|
||
${I.map(t=>p`<option value=${t} ?selected=${t===h}>
|
||
${e(`tap.${t.replace("-","_")}`)}
|
||
</option>`)}
|
||
</select>`,hint:"toggle"===h?p`<span id="marker-toggle-hint">${m.map(t=>p`<span class="hpf-hint-line">${t}</span>`)}</span>
|
||
<span class="sr-only" role="status" aria-live="polite">${t.tapHintAnnouncement}</span>`:void 0})}
|
||
${Pt}
|
||
${It}
|
||
${"run"===h||"toggle"===h?Io({id:"marker-tap-confirm",icon:"mdi:check-decagram-outline",title:e("marker.tap_confirm"),caption:e("marker.tap_confirm_tip"),checked:t.tapConfirm,onChange:e=>this.host._markerDialog={...t,tapConfirm:e}}):d}
|
||
${So({label:e("marker.controls_label"),htmlFor:"marker-controls-filter",help:this._help("marker.controls.help"),control:p`
|
||
${t.controls.length?p`<div class="hpf-chips">
|
||
${t.controls.map(i=>{const s=this._controlRefInfo(i);return p`<span class="hpf-chip ${s.warning?"hpf-chip-warning":""}" title=${s.sub}>
|
||
<ha-icon icon=${s.icon} aria-hidden="true"></ha-icon><span>${s.label}</span>
|
||
<button type="button" aria-label=${`${e("btn.delete")}: ${s.label}`} title=${e("btn.delete")}
|
||
@click=${()=>this.host._markerDialog=this._announceToggleDraft({...t,controls:t.controls.filter(t=>t!==i)})}><ha-icon icon="mdi:close"></ha-icon></button>
|
||
</span>`})}
|
||
</div>`:d}
|
||
<div class="hpf-picker ${Dt.length||t.controlsFilter.trim()?"open":""}">
|
||
<input id="marker-controls-filter" class="hpf-input" type="text" autocomplete="off" placeholder=${e("marker.controls_filter")}
|
||
.value=${t.controlsFilter}
|
||
@input=${e=>this.host._markerDialog={...t,controlsFilter:e.target.value}} />
|
||
${t.controlsFilter.trim()?p`<div class="hpf-panel"><div class="hpf-list" role="listbox" aria-label=${e("marker.controls_label")}>
|
||
${Dt.map(e=>p`<button type="button" role="option" class="hpf-cand" aria-selected="false"
|
||
@click=${()=>this._addControlRef(t,e.value)}>
|
||
<span><ha-icon icon=${e.icon} aria-hidden="true"></ha-icon> ${e.label}</span>
|
||
<small>${e.sub}</small>
|
||
</button>`)}
|
||
${Dt.length?d:p`<p class="hpf-hint">${e("marker.nothing_found")}</p>`}
|
||
</div></div>`:d}
|
||
</div>`})}`}),Tt="auto"!==et?p`<div class="markerglowvalue">${So({label:e("marker.glow_color"),control:Do({hex:t.glowColor,disabled:X,picker:p`<hp-color-opacity .label=${e("marker.glow_color")} hide-label flat-swatch
|
||
.color=${t.glowColor} .opacity=${1} .showOpacity=${!1}
|
||
.pickerLabels=${this.host._colorPickerLabels}
|
||
.disabled=${X}
|
||
@hp-color-opacity-change=${e=>{this.host._markerDialog={...t,glowMode:et,glowColor:e.detail.color,glowColorDrafted:!0,glowTouched:!0}}}></hp-color-opacity>`})})}
|
||
${"fixed"===et?p`<div class="hpf-field">
|
||
<span class="hpf-label hpf-labelrow"><label for="marker-glow-brightness">${e("marker.glow_brightness")}</label></span>
|
||
${Lo({id:"marker-glow-brightness",min:1,max:100,step:1,value:Math.round(t.glowBrightness),unit:"%",ariaLabel:e("marker.glow_brightness"),disabled:X,slider:this._rangeInput(1,100,1,t.glowBrightness,e=>{this.host._markerDialog={...t,glowMode:et,glowBrightness:e,glowBrightnessDrafted:!0,glowTouched:!0}},X,e("marker.glow_brightness")),onInput:e=>{this.host._markerDialog={...t,glowMode:et,glowBrightness:e,glowBrightnessDrafted:!0,glowTouched:!0}}})}
|
||
</div>`:d}</div>`:d,Rt=Co({id:"light",title:e("marker.card_light"),body:p`
|
||
${So({label:e("marker.light_role_label"),help:this._help("marker.light_role.help"),control:Po({name:"marker-light-role",value:t.lightRole,ariaLabel:e("marker.light_role_label"),options:[{value:"auto",label:i("marker.light_role_seg_auto")},{value:"always",label:i("marker.light_role_seg_always")},{value:"never",label:i("marker.light_role_seg_never")}],onChange:t=>this._setMarkerLightRole(t)}),hint:"auto"===t.lightRole?e(J?"marker.light_role_auto_yes":"marker.light_role_auto_no"):void 0})}
|
||
${"always"===t.lightRole&&(st.length>1||at)?p`<div class="markerleadingentity">${So({label:e("marker.light_entity_label"),htmlFor:"marker-light-entity",help:this._help("marker.light_entity.help"),control:p`<select id="marker-light-entity" class="hpf-select"
|
||
@change=${e=>this.host._markerDialog={...t,lightEntity:e.target.value,lightEntityTouched:!0}}>
|
||
<option value="" ?selected=${at||!t.lightEntity}>
|
||
${e("marker.light_entity_auto",{entity:ot||e("marker.light_entity_none")})}
|
||
</option>
|
||
${st.map(e=>p`<option value=${e}
|
||
?selected=${!at&&e===t.lightEntity}>
|
||
${dt(e)} · ${e}
|
||
</option>`)}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</select>`,hint:at?Ba(e("marker.light_entity_missing",{entity:t.lightEntity,fallback:ot||"—"}),"warning"):void 0})}</div>`:d}
|
||
========
|
||
</select>`,hint:at?Aa(e("marker.light_entity_missing",{entity:t.lightEntity,fallback:ot||"—"}),"warning"):void 0})}</div>`:d}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="hpf-block markerglowblock ${X?"hpf-disabled":""}" aria-disabled=${X?"true":"false"}>
|
||
${To({title:e("marker.glow_color_label"),help:this._help("marker.glow_mode.help")})}
|
||
${Po({name:"marker-glow-mode",value:et,ariaLabel:e("marker.glow_color_label"),options:[{value:"auto",label:e("marker.glow_mode_auto"),disabled:Q,describedBy:Q?"marker-glow-disabled-hint":void 0},{value:"color",label:e("marker.glow_mode_color"),disabled:X,describedBy:X?"marker-glow-disabled-hint":void 0},{value:"fixed",label:e("marker.glow_mode_fixed"),disabled:X,describedBy:X?"marker-glow-disabled-hint":void 0}],onChange:t=>this._setMarkerGlowMode(t)})}
|
||
${Tt}
|
||
${So({label:e("marker.glow_radius_label"),htmlFor:"marker-glow-radius",help:this._help("marker.glow_radius.help"),hint:t.glowRadius.trim()?void 0:i("marker.glow_radius_empty_hint",{v:`${this.host._glowRadiusPlaceholder} ${pt}`}),control:Ro({id:"marker-glow-radius",unit:pt,min:.5,step:.5,value:t.glowRadius,placeholder:this.host._glowRadiusPlaceholder,ariaLabel:e("marker.glow_radius_label"),disabled:X,describedBy:X||tt?"marker-glow-disabled-hint":void 0,onInput:e=>this.host._markerDialog={...t,glowRadius:e}})})}
|
||
${X||tt?ko({id:"marker-glow-disabled-hint",kind:"info",role:"note",icon:"mdi:information-outline",text:it}):d}
|
||
</div>`}),Ft=customElements.get("ha-icon-picker")?p`<ha-icon-picker id="marker-icon" .hass=${this.host.hass} .value=${t.icon||t.autoIcon}
|
||
.placeholder=${t.autoIcon||"mdi:shape-outline"}
|
||
.fallbackPath=${void 0}
|
||
@value-changed=${e=>{const i=e.detail.value||"";(t.icon||i!==t.autoIcon)&&(this.host._markerDialog={...t,icon:i})}}></ha-icon-picker>`:p`<input id="marker-icon" class="hpf-input" type="text"
|
||
placeholder=${t.autoIcon||e("marker.icon_ph")}
|
||
.value=${t.icon}
|
||
@input=${e=>this.host._markerDialog={...t,icon:e.target.value}} />`,zt=D(t.display)||!E.length&&!t.valueBadgeSource,Nt=Co({id:"appearance",title:e("marker.card_appearance"),body:p`
|
||
${So({label:e("marker.icon_label"),htmlFor:"marker-icon",help:s("marker.icon.help"),control:p`<div class="hpf-iconfield">
|
||
<div class="hpf-iconfield-control">
|
||
${customElements.get("ha-icon-picker")?d:p`
|
||
<span class="hpf-iconpreview" aria-hidden="true"><ha-icon icon=${t.icon||t.autoIcon||"mdi:shape-outline"}></ha-icon></span>`}
|
||
${Ft}
|
||
</div>
|
||
${t.icon?p`<button class="btn ghost hpf-iconclear" type="button" aria-label=${e("btn.reset")} title=${e("btn.reset")}
|
||
@click=${()=>this.host._markerDialog={...t,icon:""}}><ha-icon icon="mdi:close"></ha-icon></button>`:d}
|
||
</div>`,hint:!t.icon&&t.autoIcon?p`<span class="iconauto"><ha-icon icon=${t.autoIcon} aria-hidden="true"></ha-icon> ${e("marker.icon_auto",{icon:t.autoIcon})}
|
||
${xo(e("marker.icon_pin_auto"),()=>this.host._markerDialog={...t,icon:t.autoIcon})}</span>`:t.icon?i("marker.icon_custom_hint"):void 0})}
|
||
${So({label:e("marker.display_label"),htmlFor:"marker-display",help:s("marker.display.help"),control:p`<select id="marker-display" class="hpf-select"
|
||
@change=${e=>this.host._markerDialog={...t,display:L(e.target.value)}}>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${T.map(i=>p`<option value=${i} ?selected=${i===t.display}>
|
||
${e(Ea[i])}
|
||
</option>`)}
|
||
</select>`,hint:e(Aa[t.display])})}
|
||
${"icon_ripple"===t.display?p`${So({label:e("marker.activity_color"),control:p`<div class="ripple-colorrow">${Do({hex:t.rippleColor||"#3ea6ff",picker:p`<hp-color-opacity .label=${e("marker.activity_color")} hide-label flat-swatch
|
||
========
|
||
${T.map(s=>p`<option value=${s} ?selected=${s===t.display}>
|
||
${e(za[s])}
|
||
</option>`)}
|
||
</select>`,hint:e(Fa[t.display])})}
|
||
${"icon_ripple"===t.display?p`${Mo({label:e("marker.activity_color"),control:p`<div class="ripple-colorrow">${Po({hex:t.rippleColor||"#3ea6ff",picker:p`<hp-color-opacity .label=${e("marker.activity_color")} hide-label flat-swatch
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
.pickerLabels=${this.host._colorPickerLabels}
|
||
.color=${t.rippleColor||"#3ea6ff"} .opacity=${1} .showOpacity=${!1}
|
||
@hp-color-opacity-change=${e=>{this.host._markerDialog={...t,rippleColor:e.detail.color}}}></hp-color-opacity>`})}</div>`})}
|
||
<div class="hpf-field ripple-sizerow">
|
||
<span class="hpf-label hpf-labelrow"><label for="marker-ripple-size">${e("marker.ripple_size")}</label></span>
|
||
${Lo({id:"marker-ripple-size",min:1,max:8,step:.5,value:t.rippleSize,unit:"×",ariaLabel:e("marker.ripple_size"),slider:this._rangeInput(1,8,.5,t.rippleSize,e=>this.host._markerDialog={...t,rippleSize:e},!1,e("marker.ripple_size")),onInput:e=>this.host._markerDialog={...t,rippleSize:e}})}
|
||
<p class="hpf-hint" role="note">${e("marker.activity_alarm_note")}</p>
|
||
</div>`:d}
|
||
${R(t.display)?p`<div class="markervaluesource">${So({label:e("marker.value_source"),htmlFor:"marker-value-source",help:this._help("marker.value_source.help"),control:p`<select id="marker-value-source" class="hpf-select" ?disabled=${o}
|
||
@change=${e=>this.host._markerDialog={...t,valueSource:F(e.target.value),valueSourceTouched:!0}}>
|
||
<option value="" ?selected=${!t.valueSource}>
|
||
${e("marker.value_source_auto")}
|
||
</option>
|
||
${q?p`<option value=${U||"__missing__"} selected>
|
||
${e("marker.value_badge_missing")}
|
||
</option>`:d}
|
||
${E.map(t=>p`<option value=${t.key}
|
||
?selected=${t.key===U}
|
||
title=${t.technical}>
|
||
${this._valueBadgeCandidateLabel(t)} · ${t.value}
|
||
</option>`)}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</select>`,hint:o?Ba(e("marker.preview.reason.value_virtual"),"info"):q?Ba(e("marker.value_source_missing_hint"),"warning"):K?p`<code class="hpf-mono">${K.technical}</code>`:void 0})}</div>`:d}
|
||
${D(t.display)&&this.host._bindingHasAlarm(t.binding)?ko({kind:"warning",role:"note",icon:"mdi:alert-outline",text:e("marker.static_alarm_warning")}):d}
|
||
========
|
||
</select>`,hint:o?Aa(e("marker.preview.reason.value_virtual"),"info"):U?Aa(e("marker.value_source_missing_hint"),"warning"):K?p`<code class="hpf-mono">${K.technical}</code>`:void 0})}</div>`:d}
|
||
${D(t.display)&&this.host._bindingHasAlarm(t.binding)?wo({kind:"warning",role:"note",icon:"mdi:alert-outline",text:e("marker.static_alarm_warning")}):d}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="hpf-block markerbadgegroup">
|
||
${To({title:e("marker.value_badge_title"),help:this._help("marker.value_badge.help")})}
|
||
${Io({id:"marker-value-badge",compact:!0,icon:D(t.display)?"mdi:eye-off-outline":"mdi:card-text-outline",title:e("marker.value_badge_enabled"),checked:O,disabled:zt,onChange:e=>{const i=B||A;this.host._markerDialog={...t,valueBadgeEnabled:e&&!!i,valueBadgeSource:i,valueBadgeTouched:!0}}})}
|
||
${D(t.display)?ko({kind:"info",role:"note",icon:"mdi:information-outline",text:e("marker.value_badge_static")}):E.length||t.valueBadgeSource?d:ko({kind:"info",role:"note",icon:"mdi:information-outline",text:e("marker.value_badge_empty")})}
|
||
${O?p`
|
||
${So({label:e("marker.value_badge_source"),htmlFor:"marker-value-badge-source",help:this._help("marker.value_badge_source.help"),error:xt?i(xt.message):void 0,control:p`<select id="marker-value-badge-source" class="hpf-select"
|
||
aria-invalid=${xt?"true":d}
|
||
@change=${e=>this.host._markerDialog={...t,valueBadgeSource:F(e.target.value),valueBadgeEnabled:!0,valueBadgeTouched:!0}}>
|
||
${G?p`<option value=${W} selected>
|
||
${e("marker.value_badge_missing")}
|
||
</option>`:d}
|
||
${E.map(t=>p`<option value=${t.key}
|
||
?selected=${t.key===W}
|
||
title=${t.technical}>
|
||
${this._valueBadgeCandidateLabel(t)} · ${t.value}
|
||
</option>`)}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</select>`,hint:G?Ba(e("marker.value_badge_missing_hint"),"warning"):R(t.display)&&W===V?Ba(e("marker.value_badge_duplicate"),"info"):j?p`<code class="hpf-mono">${j.technical}</code>`:void 0})}
|
||
${So({label:e("marker.value_badge_position"),help:this._help("marker.value_badge_position.help"),control:Po({name:"marker-value-badge-position",value:H,ariaLabel:e("marker.value_badge_position"),options:Oa.map(t=>({value:t,label:e(`marker.value_badge_${t}`)})),onChange:e=>this.host._markerDialog={...t,valueBadgeEnabled:O,valueBadgeSource:B,valueBadgePosition:e,valueBadgeTouched:!0}})})}
|
||
========
|
||
</select>`,hint:j?Aa(e("marker.value_badge_missing_hint"),"warning"):R(t.display)&&W===V?Aa(e("marker.value_badge_duplicate"),"info"):G?p`<code class="hpf-mono">${G.technical}</code>`:void 0})}
|
||
${Mo({label:e("marker.value_badge_position"),help:this._help("marker.value_badge_position.help"),control:Co({name:"marker-value-badge-position",value:H,ariaLabel:e("marker.value_badge_position"),options:Na.map(t=>({value:t,label:e(`marker.value_badge_${t}`)})),onChange:e=>this.host._markerDialog={...t,valueBadgeEnabled:O,valueBadgeSource:B,valueBadgePosition:e,valueBadgeTouched:!0}})})}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
`:d}
|
||
</div>
|
||
${f?p`<hp-device-preview
|
||
.hass=${this.host.hass}
|
||
.presentation=${f}
|
||
.registry=${this.host._haRegistry}
|
||
.deviceName=${t.name.trim()||l?.name||ct||""}>
|
||
</hp-device-preview>`:Fo({title:e("marker.preview.title"),body:p`<div class="devicepreview-empty">
|
||
<ha-icon icon="mdi:eye-outline"></ha-icon>
|
||
<span>${e("marker.preview.select_source")}</span>
|
||
</div>`})}
|
||
${To({title:e("marker.size_label"),help:s("marker.size.help")})}
|
||
${zo([p`<div class="hpf-field markersize">
|
||
<span class="hpf-label hpf-labelrow"><label for="marker-size">${i("marker.size_short")}</label></span>
|
||
${Lo({id:"marker-size",min:.5,max:3,step:.1,value:Number(t.size.toFixed(1)),unit:"×",ariaLabel:i("marker.size_short"),slider:this._rangeInput(.5,3,.1,t.size,e=>this.host._markerDialog={...t,size:e},!1,i("marker.size_short")),onInput:e=>this.host._markerDialog={...t,size:e}})}
|
||
${No("×0.5","×3")}
|
||
</div>`,p`<div class="hpf-field markerangle">
|
||
<span class="hpf-label hpf-labelrow"><label for="marker-angle">${e("marker.angle_label")}</label></span>
|
||
${""}
|
||
${Lo({id:"marker-angle",min:0,max:355,step:5,value:t.angle,unit:"°",ariaLabel:e("marker.angle_label"),slider:this._rangeInput(0,355,5,t.angle,e=>this.host._markerDialog={...t,angle:e},!1,e("marker.angle_label")),onInput:e=>this.host._markerDialog={...t,angle:e}})}
|
||
${No("0°","355°")}
|
||
</div>`])}`}),Et=Co({id:"details",title:e("marker.card_details"),body:p`
|
||
${zo([So({label:e("marker.model_label"),htmlFor:"marker-model",control:p`<input id="marker-model" class="hpf-input" type="text" placeholder=${e("marker.model_ph")}
|
||
.value=${t.model}
|
||
@input=${e=>this.host._markerDialog={...t,model:e.target.value}} />`}),So({label:e("marker.link_label"),htmlFor:"marker-link",control:p`<input id="marker-link" class="hpf-input" type="url" placeholder="https://…"
|
||
.value=${t.link}
|
||
@input=${e=>this.host._markerDialog={...t,link:e.target.value}} />`})])}
|
||
${So({label:e("marker.desc_label"),htmlFor:"marker-description",control:p`<textarea id="marker-description" class="hpf-input" rows="4" placeholder=${e("marker.desc_ph")}
|
||
.value=${t.description}
|
||
@input=${e=>this.host._markerDialog={...t,description:e.target.value}}></textarea>`})}
|
||
${So({label:e("marker.manuals_label"),control:p`
|
||
${t.pdfs.length?p`<div class="hpf-chips">
|
||
${t.pdfs.map(t=>p`<span class="hpf-chip"><ha-icon icon="mdi:file-pdf-box" aria-hidden="true"></ha-icon>
|
||
<a href="${z(this.host._display(t.url))||"#"}" target="_blank" rel="noreferrer noopener">${t.name}</a>
|
||
<button type="button" aria-label=${`${e("btn.delete")}: ${t.name}`} title=${e("btn.delete")}
|
||
@click=${()=>this._removeMarkerPdf(t.url)}><ha-icon icon="mdi:close"></ha-icon></button></span>`)}
|
||
</div>`:d}
|
||
<div class="hpf-actions">
|
||
<button class="btn ghost filebtn" type="button" @click=${t=>t.currentTarget.nextElementSibling?.click()}>
|
||
<ha-icon icon="mdi:paperclip"></ha-icon>${e("btn.attach")}
|
||
</button>
|
||
<input type="file" hidden multiple accept=".pdf,.png,.jpg,.jpeg,.webp,.txt,application/pdf"
|
||
@change=${t=>this._pickMarkerFiles(t)} />
|
||
</div>`})}
|
||
${o?d:To({title:e("radar.additional_actions")})}
|
||
${this._renderRadarSection(t,l,"additional")}
|
||
${this.host._bindingHasClimate(t.binding)?Io({id:"marker-use-climate-temp",icon:"mdi:thermometer",title:e("marker.use_climate_temp"),caption:e("marker.use_climate_temp_tip"),checked:t.useClimateTemp,onChange:e=>this.host._markerDialog={...t,useClimateTemp:e}}):d}`}),At=t.hideFromPlan||"ha_disabled"===n?.kind;return p`<hp-dialog id="marker-dialog" .hass=${this.host.hass} data-kind="marker" form-shell
|
||
.title=${t.devId?e("info.device_header"):e("marker.new_device")}
|
||
.badge=${l?this.host._spaceModelById(l.space)?.title??"":this.host._spaceModel()?.title??""}
|
||
icon="mdi:shape-plus" wide @hp-close=${yt}>
|
||
<div class="body hpf-form">
|
||
${St}${Lt}${Rt}${Nt}${Et}
|
||
</div>
|
||
<div class="row dialog-action-footer hpf-footer" slot="footer">
|
||
<div class="dialog-action-group markeractions">
|
||
${t.devId?p`<button class="btn ghost" type="button"
|
||
?disabled=${t.busy||this._radarSetup.isActive()}
|
||
aria-pressed=${At?"true":"false"}
|
||
title=${e(At?"marker.show_tip":"marker.hide_tip")}
|
||
@click=${this.host._toggleMarkerDialogVisibility}>
|
||
<ha-icon icon=${At?"mdi:eye-outline":"mdi:eye-off-outline"}></ha-icon>
|
||
${e(At?"marker.show":"marker.hide")}
|
||
</button>`:d}
|
||
${t.devId?p`<button class="btn ghost danger" type="button" ?disabled=${t.busy||this._radarSetup.isActive()}
|
||
title=${e("marker.delete_tip")} @click=${()=>this._deleteMarker()}>
|
||
<ha-icon icon="mdi:delete-outline"></ha-icon>${e("btn.delete")}
|
||
</button>`:d}
|
||
</div>
|
||
${Eo(_t.length?{action:xo(i("dialog.review_fields",{n:String(_t.length)}),()=>{const t=_t[0];if(!t)return;const e=this.host.renderRoot.querySelector(`#${t.field}`);e?.scrollIntoView({block:"center"}),e?.focus()})}:{})}
|
||
<div class="dialog-action-group dialog-action-commit">
|
||
<button class="btn ghost" data-hp="dialog-cancel" ?disabled=${t.busy} @click=${yt}>${e("btn.cancel")}</button>
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>{this._saveMarker()}}
|
||
?disabled=${!bt} title=${vt}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${t.busy?"…":e("btn.save")}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}const Wa=1e-6*A,Ga=6*A;function ja(t){return Number.isFinite(t)?Math.round(t/A)*A:t}const Ua=(t,e,i,s)=>Math.hypot(i-t,s-e),qa=(t,e,i,s,o,a,n,r)=>Math.hypot(Math.max(Math.abs(o-t),Math.abs(o+n-(t+i))),Math.max(Math.abs(a-e),Math.abs(a+r-(e+s)))),Ka=(t,e,i,s,o,a,n)=>{const r=Math.max(Number(s)||0,0)/2,l=Math.PI/180,h=Math.cos(i*l)*r,c=Math.sin(i*l)*r,d=Math.cos(n*l)*r,p=Math.sin(n*l)*r,u=Math.max(Ua(t+h,e+c,o+d,a+p),Ua(t-h,e-c,o-d,a-p)),_=Math.max(Ua(t+h,e+c,o-d,a-p),Ua(t-h,e-c,o+d,a+p));return Math.min(u,_)},Va=t=>{const e=Number(t?.cell_cm);return e>0?e:5};function Ja(t,e){const i=JSON.parse(JSON.stringify(t||[])),s=JSON.parse(JSON.stringify(e||{}));let o=0,a=0,n=0,r=0,l="",h=0,c=0;const d=(t,e)=>{Number.isFinite(t)&&Number.isFinite(e)&&t!==e&&Math.abs(e-t)<=Wa&&c++},p=(t,e)=>{d(t[0],e[0]),d(t[1],e[1])},u={};let _=5;for(const t of i){const e=Va(t);null!=t?.id&&(u[String(t.id)]=e),e>_&&(_=e)}const m=(t,e,i,s=!1)=>{if(!(t>Wa||s))return;o++,t>n&&(n=t);const a=t*O*e;a>r&&(r=a,l=i)};for(const t of i){const e=Va(t),i=null!=t?.id?String(t.id):"";for(const s of t.rooms||[]){a++;let t=0;if(s.poly?.length)s.poly=s.poly.map(e=>{const i=[ja(e[0]),ja(e[1])];return t=Math.max(t,Ua(e[0],e[1],i[0],i[1])),p(e,i),i});else if(null!=s.x&&null!=s.y){const e=s.x,i=s.y,o=s.w||0,a=s.h||0,n=ja(e+o),r=ja(i+a),l=ja(e),h=ja(i),c=Math.max(A,n-l),p=Math.max(A,r-h);t=qa(e,i,o,a,l,h,c,p),s.x=l,s.y=h,s.w=c,s.h=p,d(e,l),d(i,h),d(e+o,l+c),d(i+a,h+p)}m(t,e,i)}for(const s of t.partitions||[]){a++;const o=[s.a[0],s.a[1]],n=[s.b[0],s.b[1]],r=[ja(o[0]),ja(o[1])],l=[ja(n[0]),ja(n[1])];let h=Math.max(Ua(o[0],o[1],r[0],r[1]),Ua(n[0],n[1],l[0],l[1]));const c=Ua(r[0],r[1],l[0],l[1]),d=(t.openings||[]).filter(t=>"partition"===t.host?.kind&&t.host.id===s.id).every(t=>{const e=Number(t.length),i=Number(t.host.t),s=i*c;return Number.isFinite(e)&&e>0&&Number.isFinite(i)&&i>=0&&i<=1&&s-e/2>=-Wa&&s+e/2<=c+Wa});c>Wa&&d?(s.a=r,s.b=l,p(o,r),p(n,l)):h=0,m(h,e,i)}for(const s of t.wall_columns||[]){a++;const t=[s.center[0],s.center[1]],o=[ja(t[0]),ja(t[1])],n=Ua(t[0],t[1],o[0],o[1]);s.center=o,p(t,o),m(n,e,i)}for(const s of t.decor||[]){if("furniture"===s.kind||"image"===s.kind)continue;a++;let t=0;if("line"===s.kind){const e=[s.x1,s.y1],i=[s.x2,s.y2],o=[ja(e[0]),ja(e[1])],a=[ja(i[0]),ja(i[1])];t=Math.max(Ua(e[0],e[1],o[0],o[1]),Ua(i[0],i[1],a[0],a[1])),s.x1=o[0],s.y1=o[1],s.x2=a[0],s.y2=a[1],p(e,o),p(i,a)}else{const e=s.x,i=s.y,o=s.w,a=s.h,n=ja(e),r=ja(i);if(null!=s.w&&null!=s.h){const l=ja(e+o),h=ja(i+a),c=Math.max(A,l-n),p=Math.max(A,h-r);t=qa(e,i,o,a,n,r,c,p),s.w=c,s.h=p,d(e+o,n+c),d(i+a,r+p)}else t=Ua(e,i,n,r);s.x=n,s.y=r,d(e,n),d(i,r)}m(t,e,i)}for(const s of t.openings||[]){if(a++,"partition"===s.host?.kind){const o=(t.partitions||[]).find(t=>t.id===s.host.id),a=Number(s.host.t);if(!o||!Number.isFinite(a)||a<0||a>1)continue;const n=o.b[0]-o.a[0],r=o.b[1]-o.a[1];if(Math.hypot(n,r)<=Wa)continue;const l=o.a[0]+n*a,c=o.a[1]+r*a;let d=180*Math.atan2(r,n)/Math.PI;d>=90?d-=180:d<-90&&(d+=180);const p=Number(s.angle),u=!(Number.isFinite(p)&&p===d),_=Ka(s.x,s.y,Number.isFinite(p)?p:d,Number(s.length)||0,l,c,d);s.x=l,s.y=c,s.angle=d,u&&h++,m(_,e,i,u);continue}const o=E([s.x,s.y],t.rooms||[],Ga,{step:A,length:Number(s.length)||0});if(!o)continue;const n=Number(s.angle),r=!(Number.isFinite(n)&&n===o.angle),l=Ka(s.x,s.y,Number.isFinite(n)?n:o.angle,Number(s.length)||0,o.x,o.y,o.angle);s.x=o.x,s.y=o.y,s.angle=o.angle,r&&h++,m(l,e,i,r)}}for(const[t,e]of Object.entries(s)){if(!e||"object"!=typeof e)continue;const i=e;if("number"!=typeof i.x||"number"!=typeof i.y)continue;a++;const o=ja(i.x),n=ja(i.y),r=Ua(i.x,i.y,o,n);s[t]={...i,x:o,y:n},d(i.x,o),d(i.y,n);const l="string"==typeof i.s?i.s:"";m(r,u[l]??_,l)}return{spaces:i,layout:s,report:{moved:o,coordsCanonicalized:c,total:a,maxShift:n,maxShiftCm:r,maxSpace:l,rotated:h},changed:o>0||c>0}}function Ya(t,e){const i=e.base+t*e.span;return Math.min(1,Math.max(0,i))}const Za=t=>Array.isArray(t)&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),Xa=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1]);function Qa(t,e,i){const s=i[0]-e[0],o=i[1]-e[1],a=s*s+o*o;if(a<=0)return Xa(t,e);let n=((t[0]-e[0])*s+(t[1]-e[1])*o)/a;return n=Math.max(0,Math.min(1,n)),Math.hypot(t[0]-(e[0]+s*n),t[1]-(e[1]+o*n))}function tn(t,e,i,s,o){for(const s of e)if(s&&!i.has(s.id)&&Za(s.a)&&Za(s.b)&&(Xa(t,s.a)<=o||Xa(t,s.b)<=o))return!0;for(const e of s?.roomPolygons||[])for(let i=0;i<e.length;i++){const s=e[i],a=e[(i+1)%e.length];if(Za(s)&&Za(a)&&Qa(t,s,a)<=o)return!0}for(const e of s?.columns||[])if(Za(e?.center)&&Xa(t,e.center)<=o)return!0;return!1}function en(t,e,i,s){if(t.cm!==e.cm)return null;const o=[t.b[0]-t.a[0],t.b[1]-t.a[1]],a=[e.b[0]-e.a[0],e.b[1]-e.a[1]],n=Math.hypot(o[0],o[1]),r=Math.hypot(a[0],a[1]);if(!(n>0&&r>0))return null;if(Math.abs(o[0]/n*(a[1]/r)-o[1]/n*(a[0]/r))>i)return null;for(const[i,o]of[[t.a,e.a],[t.a,e.b],[t.b,e.a],[t.b,e.b]])if(Xa(i,o)<=s)return[(i[0]+o[0])/2,(i[1]+o[1])/2];return null}function sn(t,e){const i=.05*(Number(e.pitch)>0?Number(e.pitch):1),s=new Map;let o=(t||[]).filter(t=>!!t&&"string"==typeof t.id&&Za(t.a)&&Za(t.b));if(o.length<2)return{partitions:[...t||[]],merged:0,openingMoves:[]};const a=e.seedIds&&e.seedIds.length?new Set(e.seedIds):null;let n=0;for(let t=0;t<o.length+1;t++){let t=null;for(let s=0;s<o.length&&!t;s++)for(let n=s+1;n<o.length;n++){const r=en(o[s],o[n],.02,i);if(r&&((!a||a.has(o[s].id)||a.has(o[n].id))&&!tn(r,o,new Set([o[s].id,o[n].id]),e.geometry,i))){t={i:s,j:n,at:r};break}}if(!t)break;const r=o[t.i],l=o[t.j],h=[r.a,r.b,l.a,l.b].filter(e=>Xa(e,t.at)>i);let c=h[0]??r.a,d=h[h.length-1]??l.b;if(h.length<2&&(c=r.a,d=l.b),d[0]<c[0]||d[0]===c[0]&&d[1]<c[1]){const t=c;c=d,d=t}const p={...r,a:[c[0],c[1]],b:[d[0],d[1]]},u=Xa(c,d),_=u>0?(d[0]-c[0])/u:0,m=u>0?(d[1]-c[1])/u:0,g=t=>u>0?((t[0]-c[0])*_+(t[1]-c[1])*m)/u:0;for(const t of[r,l]){const e=g(t.a),i=g(t.b)-e;for(const[o,a]of s)a.toId===t.id&&s.set(o,{fromId:a.fromId,toId:p.id,base:e+a.base*i,span:a.span*i});s.set(t.id,{fromId:t.id,toId:p.id,base:e,span:i})}a&&a.add(p.id),o=o.filter((e,i)=>i!==t.i&&i!==t.j),o.splice(t.i,0,p),n++}return{partitions:o,merged:n,openingMoves:[...s.values()]}}function on(t,e,i,s){if(!t?.length||!i.length)return 0;const o=new Map(i.map(t=>[t.fromId,t]));let a=0;for(const i of t){const t=i?.host;if(!t||"partition"!==t.kind)continue;const n=o.get(t.id);if(!n)continue;i.host={...t,id:n.toId,t:Ya(t.t,n)},a++;const r=H(i,e,s.coordScale,s.cellCm,s.gridPitch).resolved;r&&Object.assign(i,W(i,r,s.coordScale))}return a}function an(t){return{roomPolygons:(t?.rooms||[]).map(t=>B(t)).filter(t=>!!t),columns:t?.wall_columns||[]}}const nn=t=>!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),rn=(t,e)=>t[0]-e[0]||t[1]-e[1],ln=(t,e,i,s)=>[t[0]+e*s,t[1]+i*s],hn=(t,e,i,s)=>(t[0]-e[0])*i+(t[1]-e[1])*s,cn=(t,e,i,s,o)=>{const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(!(r>o))return null;const l=a/r,h=n/r,c=e=>Math.abs((e[0]-t[0])*h-(e[1]-t[1])*l);if(c(i)>o||c(s)>o)return null;const d=hn(i,t,l,h),p=hn(s,t,l,h),u=Math.max(0,Math.min(d,p)),_=Math.min(r,Math.max(d,p));return _-u>o?{lo:u,hi:_}:null},dn=(t,e,i)=>Math.min(t.hi,e.hi)-Math.max(t.lo,e.lo)>i,pn=t=>{const e=new Set(["id","a","b","cm"]);return Object.keys(t||{}).every(t=>e.has(t))},un=(t,e,i,s)=>{const o=t.b[0]-t.a[0],a=t.b[1]-t.a[1],n=Math.hypot(o,a);if(!(n>s))return!0;const r=o/n,l=a/n,h=X(t.cm,i.cellCm,i.gridPitch)/2;return e.some(e=>{const o=e?.center;if(!nn(o))return!0;const a=hn(o,t.a,r,l),c=Math.abs((o[0]-t.a[0])*l-(o[1]-t.a[1])*r),d=X(Number(e.cm),i.cellCm,i.gridPitch)*("square"===e.shape?Math.SQRT1_2:.5);return!(Number.isFinite(d)&&d>0)||a>=-d-s&&a<=n+d+s&&c<=h+d+s})},_n=(t,e,i)=>{if(t.host){const s=H(t,e,i.coordScale,i.cellCm,i.gridPitch).resolved;return s?{center:s.center,angle:s.angle,length:s.length}:null}const s=Number(t.x)*i.coordScale,o=Number(t.y)*i.coordScale,a=Number(t.angle),n=Number(t.length)*i.coordScale;return[s,o,a,n].every(Number.isFinite)&&n>0?{center:[s,o],angle:a,length:n}:null},mn=(t,e,i)=>{const s=t.angle*Math.PI/180,o=Math.cos(s),a=Math.sin(s),n=e.angle*Math.PI/180,r=Math.cos(n),l=Math.sin(n);if(Math.abs(o*l-a*r)>1e-6)return!1;const h=e.center[0]-t.center[0],c=e.center[1]-t.center[1];if(Math.abs(h*a-c*o)>i)return!1;const d=h*o+c*a;return Math.max(-t.length/2,d-e.length/2)<Math.min(t.length/2,d+e.length/2)-i},gn=(t,e)=>({...t,a:[t.a[0]*e,t.a[1]*e],b:[t.b[0]*e,t.b[1]*e]}),fn=(t,e,i,s)=>{const o=`~r-${(t=>{let e=2166136261;for(let i=0;i<t.length;i++)e^=t.charCodeAt(i),e=Math.imul(e,16777619)>>>0;return e.toString(36)})(`${t}|${e[0].toFixed(9)},${e[1].toFixed(9)}|${i[0].toFixed(9)},${i[1].toFixed(9)}`)}`,a=`${t.slice(0,Math.max(1,64-o.length))}${o}`;let n=a;for(let t=2;s.has(n);t++){const e=`-${t}`;n=`${a.slice(0,64-e.length)}${e}`}return s.add(n),n},bn=(t,e)=>{const i=[];for(const s of t){const t=i[i.length-1];!(t&&Math.abs(t.hi-s.lo)<=e&&t.safe===s.safe)||s.safe&&t.signature!==s.signature?i.push({lo:s.lo,hi:s.hi,a:s.a,b:s.b,safe:s.safe,signature:s.signature,roomIds:s.roomIds,finalCm:s.finalCm}):(t.hi=s.hi,t.b=s.b)}return i};function vn(t,e,i,s,o){const a=i||[],n=Array.isArray(t?.partitions)?t.partitions:[],r=Array.isArray(t?.openings)?t.openings:[],l={walls:a,partitions:n,openings:r,partitionsReconciled:0,openingsRehosted:0};if(!n.length)return l;const h=Math.max(2e-4*o.gridPitch,1e-9);let c=a,d=n,p=r,u=0,_=0;const m=o.partitionIds?new Set(o.partitionIds):null,g=new Map(e.partitions.map(t=>[t.id,t]));for(const t of[...n].sort((t,e)=>t.id.localeCompare(e.id))){if(m&&!m.has(t.id))continue;if(!d.some(e=>e.id===t.id))continue;if(!pn(t))continue;const i=g.get(t.id);if(!(i&&nn(i.a)&&nn(i.b)&&Number.isFinite(i.cm)&&(o.allowCoincidentPartitions?!(i.cm<0):i.cm>0)))continue;const[a,n]=rn(i.a,i.b)<=0?[[i.a[0],i.a[1]],[i.b[0],i.b[1]]]:[[i.b[0],i.b[1]],[i.a[0],i.a[1]]],r=n[0]-a[0],l=n[1]-a[1],f=Math.hypot(r,l);if(!(f>h))continue;const b=r/f,v=l/f,y=G(e.rooms,c,s,o.pitch,o.cellCm,o.gridPitch,o.coordScale),w=y.flatMap(t=>{if(t.open||"outer"!==t.kind&&"shared"!==t.kind)return[];const e=cn(a,n,t.a,t.b,h);return e?[{interval:t,range:e}]:[]});if(!w.length)continue;const $=p.filter(t=>"partition"===t.host?.kind&&t.host.id===i.id).map(t=>({opening:t,resolved:H(t,e.partitions,o.coordScale,o.cellCm,o.gridPitch).resolved}));if($.some(t=>!t.resolved))continue;const k=[0,f];for(const{range:t}of w)k.push(t.lo,t.hi);const x=k.slice(),M=new Map;for(const{opening:t,resolved:e}of $){const i=hn(e.center,a,b,v),s={lo:i-e.length/2,hi:i+e.length/2};M.set(t.id,s),x.push(Math.max(0,s.lo),Math.min(f,s.hi))}const C=[...new Set(x.filter(t=>Number.isFinite(t)&&t>=-h&&t<=f+h).map(t=>Math.max(0,Math.min(f,t)).toFixed(9)))].map(Number).sort((t,e)=>t-e),S=d.map(t=>gn(t,o.coordScale)).filter(t=>t.id!==i.id),P=[];for(let t=0;t+1<C.length;t++){const s=C[t],n=C[t+1];if(!(n-s>h))continue;const r=ln(a,b,v,s),l=ln(a,b,v,n),c=w.filter(({range:t})=>t.lo<=s+h&&t.hi>=n-h).map(({interval:t})=>t),d=new Map;for(const t of c)d.set(t.roomId,t);const p=[...d.values()],u=new Set(p.map(t=>t.kind)),_=new Set(p.map(t=>o.allowCoincidentPartitions||t.cm>0?t.cm:j)),m=p[0]?.kind,g=[...d.keys()].sort(),f=1===u.size&&1===_.size&&("outer"===m&&1===g.length||"shared"===m&&2===g.length),y={id:i.id,a:r,b:l,cm:i.cm},$=S.some(t=>!!cn(r,l,t.a,t.b,h)),k=f&&(o.allowCoincidentPartitions||!$)&&!un(y,e.wall_columns,o,h),x=f?o.allowCoincidentPartitions||p[0].cm>0?p[0].cm:j:0,M=f?Math.max(x,i.cm):i.cm;P.push({lo:s,hi:n,a:r,b:l,safe:k,signature:k?`${m}|${g.join(",")}|${M}`:"",roomIds:g,roomCm:x,finalCm:M})}if(!P.some(t=>t.safe))continue;const I=new Map;for(const{opening:t,resolved:e}of $){const s=M.get(t.id),a=k.some(t=>t>s.lo+h&&t<s.hi-h),n=P.filter(t=>dn(t,s,h)),r=new Set(n.filter(t=>t.safe).map(t=>t.signature));if(!a&&n.length>0&&n.every(t=>t.safe)&&1===r.size&&U(e,y,h)){I.set(t.id,{resolved:e,signature:[...r][0]});continue}const l=q(i,o.cellCm,o.gridPitch),c={lo:s.lo-l,hi:s.hi+l};for(const t of P)dn(t,c,h)&&(t.safe=!1,t.signature="")}let D=!0;for(;D;){D=!1;for(const[t,e]of[...I.entries()]){const s=M.get(t),a=P.filter(t=>dn(t,s,h));if(a.length>0&&a.every(t=>t.safe)&&a.every(t=>t.signature===e.signature))continue;I.delete(t);const n=q(i,o.cellCm,o.gridPitch),r={lo:s.lo-n,hi:s.hi+n};for(const t of P)dn(t,r,h)&&(t.safe=!1,t.signature="");D=!0}}const L=bn(P,h),T=L.filter(t=>t.safe),R=L.filter(t=>!t.safe);if(!T.length)continue;if(d.length-1+R.length>2e3)continue;let F=c;for(const t of T){const[e,s]=rn(i.a,i.b)<=0?[t.a,t.b]:[t.b,t.a];F=K(F,e,s,t.finalCm,o.pitch,o.coordScale)}if(F=V(e.rooms,F,s,o.pitch,o.cellCm,o.gridPitch,o.coordScale),F.length>500)continue;const z=new Set(d.map(t=>t.id));z.delete(i.id);const N=R.map((t,e)=>{const s=[t.a[0]/o.coordScale,t.a[1]/o.coordScale],a=[t.b[0]/o.coordScale,t.b[1]/o.coordScale],n=0===e?i.id:fn(i.id,s,a,z);return z.add(n),{id:n,a:s,b:a,cm:i.cm}}),E=d.findIndex(t=>t.id===i.id),A=d.slice();A.splice(E,1,...N);const O=A.map(t=>gn(t,o.coordScale)),B=new Map;let X=!0;for(const{opening:t,resolved:e}of $){const i=I.get(t.id);if(i){const e=W(t,i.resolved,o.coordScale),{host:s,...a}=e;B.set(t.id,a);continue}const s=M.get(t.id),a=N[R.findIndex(t=>t.lo<=s.lo+h&&t.hi>=s.hi-h)],n=a&&O.find(t=>t.id===a.id);if(!a||!n){X=!1;break}const r=n.b[0]-n.a[0],l=n.b[1]-n.a[1],c=Math.hypot(r,l),d=hn(e.center,n.a,r/c,l/c),p={...W(t,e,o.coordScale),host:{kind:"partition",id:a.id,t:d/c}};if(!J(p,O,o.coordScale,o.cellCm,o.gridPitch).resolved){X=!1;break}B.set(t.id,p)}if(!X)continue;const Q=p.map(t=>B.get(t.id)||t),tt=[...I.keys()].map(t=>B.get(t)),et=tt.map(t=>_n(t,O,o));if(et.some(t=>!t))continue;let it=!1;for(let t=0;t<et.length;t++)for(let e=t+1;e<et.length;e++)mn(et[t],et[e],h)&&(it=!0);const st=new Set(tt.map(t=>t.id));for(const t of Q){if(st.has(t.id))continue;const e=_n(t,O,o);e&&et.some(t=>mn(t,e,h))&&(it=!0)}if(it)continue;const ot=Y(e.rooms,F,s,o.pitch,o.cellCm,o.gridPitch,o.coordScale);[...I.entries()].every(([t,e])=>{const i=B.get(t),s=Z(ot,{x:i.x*o.coordScale,y:i.y*o.coordScale,angle:i.angle,length:i.length*o.coordScale},!0),a=[s.negative,s.positive].filter(t=>!!t?.full),n=e.signature.split("|")[1].split(","),r=new Set(a.map(t=>t.roomId));return a.length===n.length&&r.size===n.length&&n.every(t=>r.has(t))})&&(c=F,d=A,p=Q,u+=T.length,_+=I.size)}return{walls:c,partitions:d,openings:p,partitionsReconciled:u,openingsRehosted:_}}const yn=t=>JSON.parse(JSON.stringify(t)),wn=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),$n=(t,e)=>e.length>0&&e.length<=35&&("space"===t?/^[a-z0-9_-]+$/.test(e):/^[A-Za-z0-9_-]+$/.test(e));function kn(t,e){let i=String(e??"");const s=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o=new RegExp(`^${s}_(.+)_([0-9a-f]{8})$`);let a=0;for(;a<16;a++){const t=o.exec(i);if(!t)return{root:i,layers:a,bounded:!1};i=t[1]}return{root:i,layers:a,bounded:o.test(i)}}const xn=(t,e,i)=>{const s=t.get(e)||[];s.push(i),t.set(e,s)};const Mn=1e-9;class Cn extends Error{constructor(t,e=""){super(e?`${t}: ${e}`:t),this.reason=t,this.name="WallSegmentModelError"}}const Sn=t=>JSON.parse(JSON.stringify(t)),Pn=t=>Array.isArray(t)&&t.length>=2&&Number.isFinite(Number(t[0]))&&Number.isFinite(Number(t[1])),In=t=>[Number(t[0]),Number(t[1])],Dn=t=>`${Number(t[0]).toFixed(12)},${Number(t[1]).toFixed(12)}`,Ln=(t,e)=>{const i=Dn(t),s=Dn(e);return i<s?`${i}|${s}`:`${s}|${i}`},Tn=(t,e)=>Dn(t)<=Dn(e)?[In(t),In(e)]:[In(e),In(t)],Rn=(t,e)=>Math.hypot(e[0]-t[0],e[1]-t[1]),Fn=(t,e=[])=>{const i=new Set,s=t=>{const e=Number(t);if(!Number.isFinite(e))return;const s=e/A;Math.abs(s-Math.round(s))>=ot&&i.add(e.toFixed(12))};for(const e of Array.isArray(t?.rooms)?t.rooms:[])for(const t of B(e)||[])s(t[0]),s(t[1]);for(const e of[t?.wall_segments,t?.walls])for(const t of Array.isArray(e)?e:[])s(t?.a?.[0]),s(t?.a?.[1]),s(t?.b?.[0]),s(t?.b?.[1]);for(const t of e)s(t?.[0]),s(t?.[1]);return i.size},zn=(t,e,i)=>{const s=i[0]-e[0],o=i[1]-e[1],a=s*s+o*o;return a>1e-18?((t[0]-e[0])*s+(t[1]-e[1])*o)/a:0},Nn=(t,e,i)=>{const s=Math.max(0,Math.min(1,zn(t,e,i)));return Math.hypot(t[0]-(e[0]+(i[0]-e[0])*s),t[1]-(e[1]+(i[1]-e[1])*s))},En=(t,e,i,s,o=1e-9)=>{const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(r<=o)return 0;const l=e=>Math.abs((e[0]-t[0])*n-(e[1]-t[1])*a)/r;if(l(i)>o||l(s)>o)return 0;const h=zn(i,t,e),c=zn(s,t,e);return Math.max(0,Math.min(1,Math.max(h,c))-Math.max(0,Math.min(h,c)))*r},An=t=>{const e=(new TextEncoder).encode(t),i=8*e.length,s=64*Math.ceil((e.length+9)/64),o=new Uint8Array(s);o.set(e),o[e.length]=128;const a=new DataView(o.buffer);a.setUint32(s-8,Math.floor(i/4294967296),!1),a.setUint32(s-4,i>>>0,!1);const n=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),r=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),l=new Uint32Array(64),h=(t,e)=>t>>>e|t<<32-e;for(let t=0;t<s;t+=64){for(let e=0;e<16;e++)l[e]=a.getUint32(t+4*e,!1);for(let t=16;t<64;t++){const e=l[t-15],i=l[t-2],s=h(e,7)^h(e,18)^e>>>3,o=h(i,17)^h(i,19)^i>>>10;l[t]=l[t-16]+s+l[t-7]+o>>>0}let[e,i,s,o,c,d,p,u]=r;for(let t=0;t<64;t++){const a=u+(h(c,6)^h(c,11)^h(c,25))+(c&d^~c&p)+n[t]+l[t]>>>0,r=e&i^e&s^i&s;u=p,p=d,d=c,c=o+a>>>0,o=s,s=i,i=e,e=a+((h(e,2)^h(e,13)^h(e,22))+r>>>0)>>>0}r[0]=r[0]+e>>>0,r[1]=r[1]+i>>>0,r[2]=r[2]+s>>>0,r[3]=r[3]+o>>>0,r[4]=r[4]+c>>>0,r[5]=r[5]+d>>>0,r[6]=r[6]+p>>>0,r[7]=r[7]+u>>>0}const c=new Uint8Array(32),d=new DataView(c.buffer);for(let t=0;t<r.length;t++)d.setUint32(4*t,r[t],!1);return c},On=t=>{const e="abcdefghijklmnopqrstuvwxyz234567";let i=0,s=0,o="";for(const a of t)for(s=s<<8|a,i+=8;i>=5;)o+=e[s>>>i-5&31],i-=5;return i&&(o+=e[s<<5-i&31]),o},Bn=(t,e,i,s,o="")=>{const[a,n]=Tn(e,i),r=`${t}|${Dn(a)}|${Dn(n)}|${[...s].sort().join(",")}${o}`;return`wall-${On(An(r)).slice(0,20)}`};let Hn=0;const Wn=t=>{for(let e=0;e<1e3;e++){const e=globalThis.crypto?.randomUUID?.(),i=`wall-${e||On(An(`${Date.now()}|${Hn++}|${Math.random()}`)).slice(0,26)}`;if(!t.has(i))return i}throw new Cn("duplicate-id","id factory exhausted")},Gn=t=>{const e=new Map;for(const i of Array.isArray(t?.wall_segments)?t.wall_segments:[])if(i&&"string"==typeof i.id&&Pn(i.a)&&Pn(i.b)){if(e.has(i.id))throw new Cn("duplicate-id",i.id);e.set(i.id,i)}return e},jn=(t,e,i)=>{const s=(i,s)=>{const o=t[0]-i[0],a=t[1]-i[1];return Math.abs(e[0]-s[0]-o)<=Mn&&Math.abs(e[1]-s[1]-a)<=Mn?[o,a]:null};return s(i.a,i.b)||s(i.b,i.a)},Un=(t,e)=>{const i=Array.isArray(t.rooms)?t.rooms:[],s=et(t.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]),o=s.length?s:it(i,null,1,.04*A,!0),a=[];for(const t of i){const i=B(t),s=Array.isArray(t?.wall_ids)?t.wall_ids:[];if(i&&s.length===i.length)for(let t=0;t<s.length;t++){const o="string"==typeof s[t]?e.get(s[t]):null;0===Number(o?.cm)&&a.push([i[t][0],i[t][1],i[(t+1)%i.length][0],i[(t+1)%i.length][1]])}}const n=[...a,...o],r=o.length?(Array.isArray(t.openings)?t.openings:[]).filter(t=>"partition"!==t.host?.kind&&[Number(t.x),Number(t.y)].every(Number.isFinite)&&Number.isFinite(Number(t.angle))&&Number(t.length)>0&&o.some(e=>Nn([Number(t.x),Number(t.y)],[e[0],e[1]],[e[2],e[3]])<=.04*A)):[],l=r.map(t=>{const e=Number(t.angle)*Math.PI/180,i=[Math.cos(e),Math.sin(e)],s=Number(t.length)/2,o=[Number(t.x),Number(t.y)];return{a:[o[0]-i[0]*s,o[1]-i[1]*s],b:[o[0]+i[0]*s,o[1]+i[1]*s]}}),h=(t,e)=>r.some(i=>{const s=[Number(i.x),Number(i.y)];if(!at(t,e,Number(i.angle)))return!1;if(Nn(s,t,e)>.02*A)return!1;const o=Rn(t,e),a=zn(s,t,e)*o,n=Number(i.length)/2;return a+n>=-1e-9&&a-n<=o+Mn}),c=new Map,d=[];for(const s of i){const r=String(s?.id||""),p=B(s);if(!r||!p||p.length<3)throw new Cn("invalid-room",r);const u=st(i,r,n,A,1,[...t.walls||[],...l]);if(!u||u.poly.length<3)throw new Cn("invalid-room",r);const _=Array.isArray(s.wall_ids)?s.wall_ids:[],m=_.length===p.length;let g=null,f=m;if(f)for(let t=0;t<p.length;t++){const i=e.get(_[t]),s=i?jn(p[t],p[(t+1)%p.length],i):null;if(!s||g&&(Math.abs(s[0]-g[0])>Mn||Math.abs(s[1]-g[1])>Mn)){f=!1;break}g=s}const b=[];for(let t=0;t<u.poly.length;t++){const i=u.poly[t],s=u.poly[(t+1)%u.poly.length];if(Rn(i,s)<=Mn)throw new Cn("zero-length",r);const n=Ln(i,s);let l=c.get(n);if(!l){const[t,e]=Tn(i,s);l={key:n,a:t,b:e,owners:new Set,preferredIds:new Set,positionalIds:new Set,preferredCarriers:new Map,parentKeys:new Set,zeroWall:!1},c.set(n,l)}if(l.owners.add(r),l.owners.size>2)throw new Cn("third-owner",n);const d=m?_[u.parent[t]]:void 0;if("string"==typeof d&&d){const o=e.get(d);f||!o||En(i,s,o.a,o.b)>Mn?l.preferredIds.add(d):l.positionalIds.add(d),l.preferredCarriers.set(d,{a:In(p[u.parent[t]]),b:In(p[(u.parent[t]+1)%p.length])})}const g=u.parent[t];l.parentKeys.add(tt(p[g],p[(g+1)%p.length],A));const v=[(i[0]+s[0])/2,(i[1]+s[1])/2],y=t=>t.some(t=>Nn(v,[t[0],t[1]],[t[2],t[3]])<=.04*A);l.zeroWall||=y(a)||y(o)&&!h(i,s),b.push(n)}const v={...s};delete v.wall_ids,d.push({...v,poly:u.poly.map(t=>[t[0],t[1]]),wall_ids:b})}return{atoms:[...c.values()].sort((t,e)=>t.key.localeCompare(e.key)),rooms:d}},qn=(t,e,i,s,o)=>{const a=new Map([...i.values()].map(t=>[Ln(t.a,t.b),t])),n=(t=>{const e=new Map;for(const i of t)"wall"===i.host?.kind&&e.set(i.host.id,(e.get(i.host.id)||0)+1);return e})(t.openings||[]),r=new Map;for(const t of e){const e=o?.get(t.key);if(e){const s=i.get(e);if(!s)throw new Cn("duplicate-id",e);r.set(t,s);continue}if(t.preferredIds.size>1)throw new Cn("duplicate-id",[...t.preferredIds].sort().join(","));const s=[...t.preferredIds][0],l=s?i.get(s):void 0;if(l){r.set(t,l);continue}const h=s?t.preferredCarriers.get(s):void 0;if(s&&h){r.set(t,{id:s,a:h.a,b:h.b,cm:0});continue}const c=a.get(t.key);if(c){r.set(t,c);continue}const d=[...i.values()].filter(e=>En(t.a,t.b,e.a,e.b)>Mn),p=[...new Map(d.map(t=>[t.id,t])).values()];if(p.sort((t,e)=>(n.get(e.id)||0)-(n.get(t.id)||0)||Rn(e.a,e.b)-Rn(t.a,t.b)||t.id.localeCompare(e.id)),p[0])r.set(t,p[0]);else if(1===t.positionalIds.size){const e=i.get([...t.positionalIds][0]);e&&r.set(t,e)}}const l=new Map;for(const[t,e]of r){const i=l.get(e.id)||[];i.push(t),l.set(e.id,i)}for(const[t,e]of l){const s=i.get(t)||r.get(e[0]);if(!s)throw new Cn("duplicate-id",t);const o=[(s.a[0]+s.b[0])/2,(s.a[1]+s.b[1])/2];e.sort((t,e)=>{const i=Nn(o,t.a,t.b)<=Mn?0:1,a=Nn(o,e.a,e.b)<=Mn?0:1;if(i!==a)return i-a;return(Nn(s.a,t.a,t.b)<=Mn?0:1)-(Nn(s.a,e.a,e.b)<=Mn?0:1)||t.key.localeCompare(e.key)}),e[0].id=t}const h=(t=>{const e=new Set;for(const i of[t.rooms,t.openings,t.decor,t.room_drafts,t.partitions,t.wall_columns])for(const t of Array.isArray(i)?i:[])"string"==typeof t?.id&&t.id&&e.add(t.id);for(const i of Array.isArray(t.room_drafts)?t.room_drafts:[])for(const t of Array.isArray(i?.segments)?i.segments:[])"string"==typeof t?.id&&t.id&&e.add(t.id);return e})(t);for(const t of e)if(t.id){if(h.has(t.id))throw new Cn("duplicate-id",t.id);h.add(t.id)}const c=e.filter(t=>!t.id);if(s){const e=c.map(e=>{const[i,s]=Tn(e.a,e.b),o=`${String(t.id||"")}|${Dn(i)}|${Dn(s)}|${[...e.owners].sort().join(",")}`,a=On(An(o));return{atom:e,seed:o,digest:a,base:`wall-${a.slice(0,20)}`}}).sort((t,e)=>t.digest.localeCompare(e.digest)||t.atom.key.localeCompare(e.atom.key)),i=new Map;for(const t of e){const e=i.get(t.digest);if(e&&e!==t.seed)throw new Cn("duplicate-id",t.digest);i.set(t.digest,t.seed);let s=1,o=t.base;for(;h.has(o);)o=`${t.base}-${++s}`;t.atom.id=o,h.add(o)}}else for(const t of c)t.id=Wn(h),h.add(t.id)},Kn=(t,e)=>{if("partition"===t.host?.kind)return null;const i=[Number(t.x),Number(t.y)];if(!i.every(Number.isFinite))return null;const s=e=>{if(!(Number(e.cm)>0))return!1;const s=zn(i,e.a,e.b),o=Rn(e.a,e.b),a=Number(t.length)/2;return s>=-1e-9&&s<=1+Mn&&Nn(i,e.a,e.b)<=.02*A&&at(e.a,e.b,Number(t.angle))&&Number.isFinite(a)&&a>=0&&s*o-a>=-1e-9&&s*o+a<=o+Mn},o="wall"===t.host?.kind?e.find(e=>e.id===t.host.id):null,a=o&&s(o)?[o]:e.filter(s);if(1!==a.length)return null;const n=a[0];return{kind:"wall",id:n.id,t:Math.max(0,Math.min(1,zn(i,n.a,n.b)))}},Vn=(t,e)=>{const i=[Number(t.x),Number(t.y)];if(!i.every(Number.isFinite))return null;const s=Number(t.length)/2,o=e.filter(e=>{if(!(Number(e.cm)>0))return!1;const o=zn(i,e.a,e.b),a=Rn(e.a,e.b);return o>=-1e-9&&o<=1+Mn&&Nn(i,e.a,e.b)<=.02*A&&at(e.a,e.b,Number(t.angle))&&Number.isFinite(s)&&s>=0&&o*a-s>=-1e-9&&o*a+s<=a+Mn}),a=(e=>{if(!e.length)return null;const s="wall"===t.host?.kind?e.find(e=>e.id===t.host.id):null;return s||[...e].sort((t,e)=>Nn(i,t.a,t.b)-Nn(i,e.a,e.b)||Number(e.cm)-Number(t.cm)||(t.id<e.id?-1:t.id>e.id?1:0))[0]})(o);return a?{kind:"wall",id:a.id,t:Math.max(0,Math.min(1,zn(i,a.a,a.b)))}:null},Jn=/^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/,Yn=t=>{if("number"!=typeof t&&"string"!=typeof t)return null;if("string"==typeof t&&!Jn.test(t.trim()))return null;const e=Number(t);return Number.isFinite(e)?e:null},Zn=t=>{if(!Array.isArray(t)||t.length<2)return null;const e=Yn(t[0]),i=Yn(t[1]);return null==e||null==i?null:[e,i]},Xn=t=>"string"==typeof t?t:"",Qn=t=>{if(!Object.prototype.hasOwnProperty.call(t,"room_drafts"))return{drafts:0,segments:0};const e=Array.isArray(t.room_drafts)?t.room_drafts:[];if(!e.length)return delete t.room_drafts,{drafts:0,segments:0};const i=new Set;for(const e of[t.rooms,t.openings,t.decor,t.partitions,t.wall_columns,t.wall_segments])for(const t of Array.isArray(e)?e:[])"string"==typeof t?.id&&t.id&&i.add(t.id);for(const t of e)"string"==typeof t?.id&&t.id&&i.add(t.id);const s=Array.isArray(t.partitions)?[...t.partitions]:[];let o=0;for(const a of e){const e=Xn(a?.id),n=Array.isArray(a?.points)?a.points:[],r=Array.isArray(a?.segments)?a.segments:[];if(n.length<2||r.length!==n.length-1)throw new Cn("zero-length",e);for(let a=0;a+1<n.length;a++){const l=Zn(n[a]),h=Zn(n[a+1]),c=r[a];if(!l||!h||nt(l,h,.001))throw new Cn("zero-length",e);const d=Yn(c?.cm);if(null==d||d<0||d>100)throw new Cn("thickness-conflict",e);let p="string"==typeof c?.id&&c.id?c.id:"";if(!p||i.has(p)){const s=Bn(Xn(t.id),l,h,[`draft:${e}:${a}`]);p=s;for(let t=2;i.has(p);t++)p=`${s}-${t}`}i.add(p),s.push({id:p,a:In(l),b:In(h),cm:d}),o++}}return s.length?t.partitions=s:delete t.partitions,delete t.room_drafts,{drafts:e.length,segments:o}},tr=t=>Qn(t),er=(t,e,i)=>{const s=Qn(t),o=Gn(t),{atoms:a,rooms:n}=Un(t,o);qn(t,a,o,e,i);const r=a.map(e=>{const i=e.id?o.get(e.id):void 0,s=((t,e,i)=>{if(e.zeroWall)return 0;const s=Array.isArray(t.walls)?t.walls:[],o=tt(e.a,e.b,A),a=s.filter(t=>Number(t.cm)>0&&(!(t.key!==o&&!e.parentKeys.has(t.key))||!(!Pn(t.a)||!Pn(t.b))&&En(e.a,e.b,t.a,t.b)>=Rn(e.a,e.b)-Mn)).map(t=>Math.max(1,Math.min(100,Number(t.cm))));if(new Set(a.map(t=>t.toFixed(9))).size>1)throw new Cn("thickness-conflict",e.key);if(a.length)return a[0];const n=rt(s,e.a,e.b,A,1);return n>0?n:Number(i?.cm)>0?Number(i.cm):0})(t,e,i);return{...i||{},id:e.id,a:[...e.a],b:[...e.b],cm:s}}),l=new Map(a.map(t=>[t.key,t.id]));for(const t of n)t.wall_ids=t.wall_ids.map(t=>l.get(t));t.rooms=n,t.wall_segments=r,t.walls=r.filter(t=>t.cm>0).map(t=>({key:tt(t.a,t.b,A),cm:t.cm,a:[...t.a],b:[...t.b]})),t.walls.length||delete t.walls,delete t.open_spans;for(const e of t.rooms)delete e.open_to;return((t,e,i)=>{const s=Array.isArray(t.openings)?t.openings:[];for(const t of s){if("partition"===t.host?.kind)continue;if(!t.host&&!i){const i=Kn(t,e);i&&(t.host=i);continue}const s=Kn(t,e)??(i?Vn(t,e):null);if(s)t.host=s;else{if(!i)throw new Cn("opening-host",t.id);delete t.host}}})(t,r,e),{wallSegments:r.reduce((t,e)=>t+(o.has(e.id)?0:1),0),drafts:s.drafts,draftSegments:s.segments}};function ir(t,e={}){const i=JSON.stringify(t),s=Sn(t);Q(s);let o=0,a=0,n=0;const r=Number(s?.model_version||0)<10;for(const t of Array.isArray(s?.spaces)?s.spaces:[]){const i=e.lineageSpaceId===String(t?.id||"")?e.lineageHints:void 0,s=er(t,r,i);o+=s.wallSegments,a+=s.drafts,n+=s.draftSegments}return s.model_version=10,Q(s),{config:s,changed:i!==JSON.stringify(s),migratedSegments:o,migratedDrafts:a,migratedDraftSegments:n}}const sr=t=>!!t&&"object"==typeof t&&!Array.isArray(t);function or(t,e){const i=(t,e)=>{if(Array.isArray(t)&&Array.isArray(e)){const s=new Map;for(const e of t)sr(e)&&"string"==typeof e.id&&e.id&&s.set(e.id,e);const o=e.map((e,o)=>{if(sr(e)&&"string"==typeof e.id&&e.id){const t=s.get(e.id);return t?i(t,e):Sn(e)}return o<t.length?i(t[o],e):Sn(e)});return t.splice(0,t.length,...o),t}if(sr(t)&&sr(e)){const s=Object.entries(e).map(([e,s])=>[e,e in t?i(t[e],s):Sn(s)]);for(const e of Object.keys(t))delete t[e];for(const[e,i]of s)t[e]=i;return t}return Sn(e)};return i(t,e)}const ar=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),nr=(t,e,i)=>Math.min(i,Math.max(e,t)),rr=t=>$t({spaces:[t]})[0],lr=(t,e,i)=>{const s=i>0?i:1,o=t=>`${(t[0]/s).toFixed(12)},${(t[1]/s).toFixed(12)}`,a=o(t),n=o(e);return a<n?`${a}|${n}`:`${n}|${a}`};function hr(t,e,i,s,o,a,n=1){if(!e?.length)return[];const r=n>0?n:1,l=Math.max(s*r*.02,1e-9),h=[];for(const e of t||[])for(const t of B(e)||[])h.push([t[0],t[1]]);const c=[];for(const t of i||[])Array.isArray(t)&&t.length>=4&&t.slice(0,4).every(Number.isFinite)&&c.push([t[0],t[1]],[t[2],t[3]]);const d=(t,e)=>e.some(e=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l),p=new Map;for(const n of t||[]){if(!n?.id)continue;const u=kt(t,n.id,e,i,s,o,a,r);if(u)for(let t=0;t<u.orig.length;t++){const e=[];for(let i=0;i<u.parent.length;i++)u.parent[i]===t&&e.push(i);for(let t=1;t+1<e.length;t++){const i=e[t-1],s=e[t],o=e[t+1];if(null===u.kinds[i]||null===u.kinds[s]||null===u.kinds[o])continue;const n=u.cms[i],_=u.cms[s],m=u.cms[o];if(!(n>0&&_>0&&n===m&&_!==n))continue;const g=u.poly[s],f=u.poly[(s+1)%u.poly.length],b=Math.hypot(f[0]-g[0],f[1]-g[1]);if(!(b>l&&b<.5*a-1e-9*a))continue;if(d(g,c)||d(f,c))continue;if(d(g,h)&&d(f,h))continue;const v=lr(g,f,r),y=p.get(v);y?y.targets.add(n):p.set(v,{a:[g[0],g[1]],b:[f[0],f[1]],targets:new Set([n])})}}}let u=e.slice();const _=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l,m=(t,e)=>{if(!Array.isArray(t.a)||!Array.isArray(t.b)||t.a.length<2||t.b.length<2)return!1;const i=[Number(t.a[0])*r,Number(t.a[1])*r],s=[Number(t.b[0])*r,Number(t.b[1])*r];return!![...i,...s].every(Number.isFinite)&&(_(i,e.a)&&_(s,e.b)||_(i,e.b)&&_(s,e.a))};for(const t of[...p.values()].filter(t=>1===t.targets.size).sort((t,e)=>lr(t.a,t.b,r).localeCompare(lr(e.a,e.b,r)))){const e=[...t.targets][0],i=u.filter(e=>m(e,t));if(new Set(i.map(t=>t.cm)).size>1)continue;let o=!1;u=u.map(i=>m(i,t)?(o=!0,i.cm===e?i:{...i,cm:e}):i),o||(u=K(u,t.a,t.b,e,s,r))}return u}const cr=t=>{const e=[];for(const i of t||[]){const t=B(i);if(t?.length)for(let i=0;i<t.length;i++)e.push([[t[i][0],t[i][1]],[t[(i+1)%t.length][0],t[(i+1)%t.length][1]]])}return e};function dr(t,e,i={},s={}){const o=s.reconcileCoincidentPartitions??vn,a=function(t,e,i={}){const s=yn(t||{spaces:[],markers:[],settings:{}}),o=yn(e||{}),a=JSON.stringify(s),n=JSON.stringify(o),r=Array.isArray(s.spaces)?s.spaces:[],l=Array.isArray(s.markers)?s.markers:[],h=r.map(t=>"string"==typeof t?.id?t.id:"").filter(Boolean),c=new Set(h),d=new Map;for(const t of h){const e=kn("space",t);e.layers>0&&$n("space",e.root)&&xn(d,e.root,t)}const p=new Map,u=new Map,_=new Map,m=new Map;for(const t of r){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i=new Map;for(const s of Array.isArray(t.rooms)?t.rooms:[]){const t="string"==typeof s?.id?s.id:"";if(!t)continue;const o=kn("room",t);o.layers>0&&$n("room",o.root)&&xn(i,o.root,t),u.has(t)||u.set(t,e),_.has(t)||_.set(t,String(s.name||""));const a="string"==typeof s.area?s.area:"";if(a){const i=m.get(a)||[];i.push({spaceId:e,roomId:t}),m.set(a,i)}}p.set(e,i)}const g=new Set(u.keys()),f=new Map,b=new Map;for(const t of l)"string"==typeof t?.id&&t.id&&(!0===t.removed?b.set(t.id,t):f.set(t.id,t));const v={spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0,positionsUnresolved:0,nestedRefsUnresolved:0,deadSpaceIds:[],orphanRoomLabelsRemoved:0,orphanDevicePositionsRemoved:0,orphanGroupPositionsRemoved:0,liveMissingPositionsRemoved:0,removedPositions:[],liveMissingPositions:[],unverifiedPositions:[]},y=new Set,w=t=>c.has(t)?null:(()=>{const e=kn("space",t).root;if(!$n("space",e))return null;const i=d.get(e)||[];return 1===i.length?i[0]:null})(),$=(t,e)=>{const i=kn("room",t).root;if(!$n("room",i))return null;const s=p.get(e)?.get(i)||[];return 1===s.length?s[0]:null},k=t=>{const e=i.effectiveAreaByMarker?.[t]||"",s=e&&m.get(e)||[];return 1===s.length?s[0]:null},x=(t,e,i)=>{if("string"==typeof t.room_id&&t.room_id&&!g.has(t.room_id)){const s=e?$(t.room_id,e):null;s?(t.room_id=s,v.roomRefsRemapped++):i?(t.room_id=i.roomId,v.roomRefsRemapped++):!0!==t.removed&&delete t.room_id}const s=t.vacuum?.segment_map;if(s&&"object"==typeof s&&!Array.isArray(s))for(const t of Object.keys(s)){const i=s[t];if("string"!=typeof i||!i||g.has(i))continue;const o=e?$(i,e):null;o?(s[t]=o,v.roomRefsRemapped++):v.nestedRefsUnresolved++}};for(const t of l){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i="string"==typeof t.space?t.space:"",s=i&&!c.has(i),a=o[e],n="string"==typeof a?.s?a.s:"",r=n&&!c.has(n),l=!0===t.removed;let h=i&&c.has(i)?i:null,d=null,p=!1;if(s){const s=w(i);s?(t.space=s,h=s,p=!0,v.spaceRefsRemapped++):l||"virtual"===t.binding?l||(delete t.space,h=null,v.markersDetached++):(d=k(e),d?(t.space=d.spaceId,h=d.spaceId,v.spaceRefsRemapped++):(delete t.space,h=null,v.markersDetached++))}l&&!p||x(t,h,d),r&&p&&n===i&&h&&(o[e]={...a,s:h},v.positionsRemapped++,y.add(e))}for(const t of Object.keys(o)){if(y.has(t))continue;const e=o[t],i="string"==typeof e?.s?e.s:"";if(!i||c.has(i))continue;const s=w(i);if(s){if(t.startsWith("rl_")){const i=t.slice(3),a=$(i,s);if(a){const i=`rl_${a}`;wn(o,i)||(o[i]={...e,s:s}),delete o[t],v.roomRefsRemapped++,v.positionsRemapped++;continue}}o[t]={...e,s:s},v.positionsRemapped++}}const M=i.ownerRoster,C=!0===M?.authoritative,S=new Set(M?.deviceIds||[]),P=new Set(M?.entityIds||[]),I=new Set(Array.isArray(s.settings?.known_devices)?s.settings.known_devices.filter(t=>"string"==typeof t):[]),D=(t,e="")=>{const i=String(M?.names?.[t]||e||"").trim();return i&&i!==t?i:""},L=(t,e,i,s="",o)=>({id:t,spaceId:e,kind:i,name:D(t,s),...o?{reason:o}:{}}),T=t=>{"room_label"===t?v.orphanRoomLabelsRemoved++:"group"===t?v.orphanGroupPositionsRemoved++:v.orphanDevicePositionsRemoved++},R=new Set;for(const[t,e]of Object.entries(o)){const s="string"==typeof e?.s?e.s:"";if(!s||c.has(s))continue;let a,n;const r=f.get(t),l=b.get(t);if(r)a=L(t,s,"device",String(r.name||"")),n="live";else if(l)a=L(t,s,"device",String(l.name||"")),n="absent";else if(t.startsWith("rl_")){const e=t.slice(3);a=L(t,s,"room_label",_.get(e)||""),n=g.has(e)?"live":"absent"}else if(t.startsWith("lg_")){const e=t.slice(3);a=L(t,s,"group"),n=P.has(e)?"live":C?"absent":"unverified","unverified"===n&&(a.reason="registry_unavailable")}else S.has(t)?(a=L(t,s,"device"),n="live"):I.has(t)?(a=L(t,s,"device"),n=C?"absent":"unverified","unverified"===n&&(a.reason="registry_unavailable")):(a=L(t,s,"unknown","","unknown_owner"),n="unverified");if("absent"!==n){if("live"===n){if(v.liveMissingPositions.push(a),!0===i.removeLiveMissingPositions){delete o[t],v.liveMissingPositionsRemoved++,T(a.kind),v.removedPositions.push(a);continue}}else v.unverifiedPositions.push(a);v.positionsUnresolved++,R.add(s)}else delete o[t],T(a.kind),v.removedPositions.push(a)}return v.deadSpaceIds=[...R].sort((t,e)=>t.localeCompare(e)),{config:s,layout:o,report:v,changed:JSON.stringify(s)!==a||JSON.stringify(o)!==n}}(t,e,i),n=a.config,r=lt(n,a.layout);Q(n),ht(a.layout);const l=JSON.stringify(t||{}),h=JSON.stringify(e||{}),c=Number.isInteger(Number(n.model_version))?Number(n.model_version):0,d=(t=>{let e=0,i=0,s=0;for(const i of t.markers||[]){if("ripple"===i.display&&(i.display="icon_ripple",e++),Array.isArray(i.controls)){const t="string"==typeof i.binding&&i.binding.startsWith("entity:")?i.binding.slice(7):"",s=t?i.controls.filter(e=>e!==t):i.controls;JSON.stringify(s)!==JSON.stringify(i.controls)&&(i.controls=s.length?s:null,e++)}const t=i.vacuum;t&&ar(t,"trail")&&(["never","cleaning","always"].includes(t.trail_mode)||(t.trail_mode=!1===t.trail?"never":"cleaning"),delete t.trail,e++)}for(const o of t.spaces||[]){const t=o.settings;"glow"===t?.fill_mode&&("boolean"!=typeof t.glow_enabled&&(t.glow_enabled=!0),t.fill_mode="none",e++,i++);for(const t of o.rooms||[]){const i=t.settings;"glow"===i?.fill_mode&&("boolean"!=typeof i.glow&&(i.glow=!0),delete i.fill_mode,e++,s++)}if(ar(o,"segments")&&(delete o.segments,e++),ar(o,"plan_scale")){const t=Number(o.plan_scale);Number.isFinite(t)&&t>=gt&&t<=ft&&(ar(o,"plan_scale_x")||(o.plan_scale_x=t),ar(o,"plan_scale_y")||(o.plan_scale_y=t),delete o.plan_scale,e++)}const a=Number(o.cell_cm);ar(o,"cell_cm")&&(!Number.isFinite(a)||a<.1||a>1e3)&&(o.cell_cm=Number.isFinite(a)&&a>0?nr(a,.1,1e3):5,e++);const n=Number(o.cell_cm),r=Number.isFinite(n)&&n>0?n:5;for(const t of o.wall_columns||[])if("circle"===t.shape)ar(t,"angle")&&(delete t.angle,e++);else if("square"===t.shape&&ar(t,"angle")){const i=((Number(t.angle)||0)%90+90)%90;t.angle!==i&&(t.angle=i,e++)}for(const t of o.decor||[]){if(ar(t,"width")){const i=Number(t.width);(ar(t,"width_cm")||Number.isFinite(i))&&(ar(t,"width_cm")||(t.width_cm=Number(nr(i/_t*r,.1,100).toFixed(6))),delete t.width,e++)}if("rect"!==t?.kind&&"ellipse"!==t?.kind||!0!==t.fill||(ar(t,"fill_color")||(t.fill_color=t.color||"#607d8b",e++),ar(t,"fill_opacity")||(t.fill_opacity=.25,e++)),"text"!==t?.kind)continue;void 0===t.size_cm?(t.size_cm=Number(nr(bt*vt(t)/_t*r,.1,2e3).toFixed(6)),delete t.scale,delete t.size,e++):(ar(t,"scale")||ar(t,"size"))&&(delete t.scale,delete t.size,e++);let i=String(t.text??"");const s=[...i.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!yt(t[1]));if(!(ar(t,"entity")||ar(t,"attr")||ar(t,"unit")))continue;const o=String(t.unit??"").trim(),a="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,n=s||o?"":wt(t.entity,a);if(s||n){if(n){const e=i.indexOf("{}");i=e>=0?i.slice(0,e)+n+i.slice(e+2):`${i}${i?" ":""}${n}`,t.text=i}delete t.entity,delete t.attr,delete t.unit,e++}}}return{total:e,glowSpaces:i,glowRooms:s}})(n);let p=d.total,u=0,_=0,m=0;if(c<10)for(const t of Array.isArray(n.spaces)?n.spaces:[]){const e=tr(t);_+=e.drafts,m+=e.segments}const g=(f=n.spaces||[],JSON.parse(JSON.stringify(f)));var f;const b=Ja(n.spaces||[],a.layout);let v=0,y=0,w=0,$="";const k=b.spaces.map(t=>{const e=ct(t);v+=e.report.wallsStraightened,y+=e.report.wallsStraightenSkipped;const i=Number(t?.cell_cm)>0?Number(t.cell_cm):5,s=e.report.maxStraightenShift/A*i;return s>w&&(w=s,$=String(t?.id||"")),e.space}),x=v?Ja(k,b.layout):{...b,spaces:k};n.spaces=x.spaces;const M=v?{...b.report,moved:b.report.moved+x.report.moved,coordsCanonicalized:b.report.coordsCanonicalized+x.report.coordsCanonicalized,maxShift:Math.max(b.report.maxShift,x.report.maxShift),maxShiftCm:Math.max(b.report.maxShiftCm,x.report.maxShiftCm),maxSpace:x.report.maxShiftCm>b.report.maxShiftCm?x.report.maxSpace:b.report.maxSpace,rotated:b.report.rotated+x.report.rotated}:{...b.report};let C=0,S=0,P=0,I=0,D=0,L=0,T=0;for(let t=0;t<n.spaces.length;t++){const e=g[t],i=n.spaces[t],s=JSON.stringify({zero:(e.wall_segments||[]).filter(t=>0===Number(t.cm)),walls:e.walls||[]}),a=rr(e),r=rr(i);if(!a||!r)continue;const l=cr(a.rooms),h=cr(r.rooms),c=.02*_t,d=(e.wall_segments||[]).filter(t=>0===Number(t.cm)).map(t=>({...t,key:tt(t.a,t.b,A),cm:0})),p=new Set(d.map(t=>t.key)),u=dt(e,a.rooms,pt,c);S+=u.length;for(const t of u){const e=[t[0]/pt,t[1]/pt],i=[t[2]/pt,t[3]/pt],s=tt(e,i,A);p.has(s)||(p.add(s),d.push({key:s,a:e,b:i,cm:0}))}const _=d.length,m=ut(d,l,h,A,pt),f=(t,e,i)=>{const s=i[0]-e[0],o=i[1]-e[1],a=s*s+o*o;if(!(a>0))return Math.hypot(t[0]-e[0],t[1]-e[1]);const n=Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*o)/a));return Math.hypot(t[0]-(e[0]+s*n),t[1]-(e[1]+o*n))},b=m.filter(t=>{if(!Array.isArray(t.a)||!Array.isArray(t.b))return!1;const e=t.a.map(t=>t*pt),i=t.b.map(t=>t*pt);return h.some(([t,s])=>f(e,t,s)<=4*c&&f(i,t,s)<=4*c)});P+=Math.max(0,_-b.length);const v=(i.wall_segments||[]).filter(t=>Number(t.cm)>0);i.wall_segments=[...v,...b.map(({key:t,...e})=>e)];const y=b.map(t=>[t.a[0]*pt,t.a[1]*pt,t.b[0]*pt,t.b[1]*pt]),w=Array.isArray(e.walls)?e.walls.length:0;let $=ut(e.walls,l,h,A,pt);$=hr(r.rooms,$,y,A,Number(i.cell_cm)>0?Number(i.cell_cm):5,_t,pt),$=V(r.rooms,$,y,A,Number(i.cell_cm)>0?Number(i.cell_cm):5,_t,pt),$=mt($,i.rooms||[],A,1,y.map(t=>[t[0]/pt,t[1]/pt,t[2]/pt,t[3]/pt])),C+=Math.max(0,w-$.length),$.length?i.walls=$:delete i.walls;const k=sn(i.partitions||[],{pitch:A,geometry:an(i)});k.merged&&(I+=k.merged,i.partitions=k.partitions,on(i.openings,i.partitions,k.openingMoves,{coordScale:pt,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,gridPitch:_t}));const x=rr(i);if(x){const t=o(i,x,i.walls||[],y,{pitch:A,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,gridPitch:_t,coordScale:pt});t.partitionsReconciled&&(D+=t.partitionsReconciled,L+=t.openingsRehosted,t.partitions.length?i.partitions=t.partitions:delete i.partitions,t.openings.length?i.openings=t.openings:delete i.openings,t.walls.length?i.walls=t.walls:delete i.walls)}JSON.stringify({zero:(i.wall_segments||[]).filter(t=>0===Number(t.cm)),walls:i.walls||[]})!==s&&T++}if(c<=10){const t=function(t){const e=ir(t);return or(t,e.config),{...e,config:t}}(n);u+=t.migratedSegments,_+=t.migratedDrafts,m+=t.migratedDraftSegments}const R=Q(n),F=ht(x.layout),z=JSON.stringify(R)!==l||JSON.stringify(F)!==h;c<10&&z&&(R.model_version=10);const N=JSON.stringify(R)!==l||JSON.stringify(F)!==h,E=Number.isInteger(Number(R.model_version))?Number(R.model_version):c,O=N?M:{...M,moved:0,coordsCanonicalized:0,maxShift:0,maxShiftCm:0,maxSpace:"",rotated:0},B=N?a.report:{...a.report,spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0,orphanRoomLabelsRemoved:0,orphanDevicePositionsRemoved:0,orphanGroupPositionsRemoved:0,liveMissingPositionsRemoved:0};return{config:R,layout:F,report:{...O,modelFrom:c,modelTo:E,migrated:N?p:0,glowSpacesMigrated:N?d.glowSpaces:0,glowRoomsMigrated:N?d.glowRooms:0,canonicalized:N?T:0,wallSegmentsMigrated:N?u:0,roomDraftsMigrated:N?_:0,roomDraftSegmentsMigrated:N?m:0,legacyZeroWallsMigrated:N?S:0,wallsMerged:N?C:0,spansMerged:N?P:0,partitionsMerged:N?I:0,partitionsReconciled:N?D:0,openingsRehosted:N?L:0,wallsStraightened:N?v:0,wallsStraightenSkipped:y,maxStraightenShiftCm:N?w:0,maxStraightenSpace:N?$:"",latticeCoordinatesCanonicalized:N?r.canonicalized:0,latticeCoordinatesFar:N?r.far:0,latticeMaxShift:N?r.maxShift:0,latticeMaxShiftCm:N?r.maxShiftCm:0,latticeSpaces:N?r.spaces:[],...B},changed:N}}async function pr(t,e,i){t._saveConfigDebounced.pending()&&t._saveConfigDebounced.flush(),await t._writeChain;const s=await t.hass.callWS({type:"houseplan/plan/optimize",config:e,layout:i,expected_config_rev:t._cfgRev,expected_layout_rev:t._layoutRev});t._adoption.acceptPairWrite(e,i,s),t._geometryHistory.clear(),t._cancelDeviceDrag(),t._devicePositionHistory.clear(),t._canOptimizeUndo=!0===s.can_undo,t._undoKind=!0===s.can_undo?"optimize":null,t._dirtyPos.clear(),t._sentPos.clear(),t._cfgEpoch++,t._modelCache=null,t._frame=null,t._regSignature="",t._maybeRebuildDevices(),t._cacheSnapshot(),t.requestUpdate()}const ur=Object.freeze({spaces:50,partitions:2e3,openings:500,decor:1e3,columns:500});class _r extends Error{constructor(t){super(t),this.code=t,this.name="SpaceCopyError"}}const mr=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),gr=t=>void 0===t?t:JSON.parse(JSON.stringify(t)),fr=t=>null===t||"object"!=typeof t||Array.isArray(t)?null:t;function br(t,e=!1){if(void 0===t&&!e)return[];if(!Array.isArray(t))throw new _r("source_invalid");return t.map(t=>{const e=fr(t);if(!e||"string"!=typeof e.id||!e.id)throw new _r("source_invalid");return e})}const vr=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(t));function yr(t,e,i){const s=String(t??"").trim()||i,o=new Set(e.map(t=>{const e=fr(t);return String(e?.title??"").trim()}));let a=2;for(;o.has(`${s} (${a})`);)a++;return`${s} (${a})`}const wr=["settings","zero_wall_style","cell_cm","view_box","plan_url","plan_aspect","plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"];const $r={source_missing:"space.copy_error_source_missing",source_invalid:"space.copy_error_source_invalid",spaces_limit:"space.copy_error_spaces_limit",partitions_limit:"space.copy_error_partitions_limit",openings_limit:"space.copy_error_openings_limit",decor_limit:"space.copy_error_decor_limit",columns_limit:"space.copy_error_columns_limit",opening_host_missing:"space.copy_error_opening_host",opening_host_unknown:"space.copy_error_opening_host",geometry_unsafe:"space.copy_error_geometry"};let kr=0;function xr(t,e,i){const s=t._spaceDialog;return!(!s?.copy||s.copy.token!==e)&&(t._spaceDialog={...s,busy:i,copy:{...s.copy,busy:i}},!0)}function Mr(t){t._cfgEpoch++,t._modelCache=null,t._frame=null,t._regSignature="",t._maybeRebuildDevices(),t.requestUpdate()}async function Cr(t,e){const i=t._spaceDialog;if(!i?.copy||"edit"!==i.mode||i.busy||i.copy.busy||!i.copy.title.trim()||!i.spaceId||!t._serverCfg)return;const s=++kr,o=i.spaceId,a=i.copy.title.trim();t._spaceDialog={...i,busy:!0,copy:{...i.copy,title:a,busy:!0,token:s}};let n=!1;try{if(t._saveConfigDebounced.pending()&&t._saveConfigDebounced.flush(),await t._writeChain,!xr(t,s,!0)||!t._serverCfg)return;const i=t._cfgRev,r=t._layoutRev,l=xt(t._serverCfg),h=xt(t._layout);let c;try{c=(e.optimize??dr)(t._serverCfg,t._layout,e.optimizeReferenceContext())}catch(i){return xr(t,s,!1),void e.showWallModelMigrationBlocked(i)}if(c.changed){const d=t._checkOptimizeGeometry(c.config);if(e.reportPreflightFailure(d,c.config),!d.ok)return xr(t,s,!1),void t._showToast(t._t("space.copy_error_optimize_geometry"));const p=await t._confirmDanger({key:`copy-space:${o}`,kind:"warning",title:t._t("space.copy_optimize_title"),message:t._t("space.copy_optimize_body",{name:a}),objectName:a,confirmLabel:t._t("space.copy_optimize_confirm"),cancelLabel:t._t("btn.cancel"),icon:"mdi:broom"});if(!xr(t,s,p))return;if(!p)return;if(t._cfgRev!==i||t._layoutRev!==r||!t._serverCfg||xt(t._serverCfg)!==l||xt(t._layout)!==h)return xr(t,s,!1),void t._showToast(t._t("space.copy_error_changed"));e.clearGeometryGesture(),await pr(t,c.config,c.layout),n=!0}if(!xr(t,s,!0)||!t._serverCfg)return;const d=t._serverCfg,p=function(t,e,i,s){const o=t.spaces;if(!i.trim())throw new _r("source_invalid");if(o.length>=ur.spaces)throw new _r("spaces_limit");const a=o.findIndex(t=>t.id===e);if(a<0)throw new _r("source_missing");const n=o[a];if(!Array.isArray(n.view_box))throw new _r("source_invalid");const r=br(n.wall_segments,!0),l=br(n.partitions),h=br(n.openings),c=br(n.decor),d=br(n.wall_columns);if(r.length+l.length>ur.partitions)throw new _r("partitions_limit");if(h.length>ur.openings)throw new _r("openings_limit");if(c.length>ur.decor)throw new _r("decor_limit");if(d.length>ur.columns)throw new _r("columns_limit");let p=0;const u=t=>`${t}${s}${(p++).toString(36)}`,_=new Map,m=new Map,g=[];for(const t of r){if(_.has(t.id)||!vr(t.a)||!vr(t.b)||"number"!=typeof t.cm||!Number.isFinite(t.cm))throw new _r("source_invalid");const e=u("cw");_.set(t.id,e),g.push({id:e,a:gr(t.a),b:gr(t.b),cm:t.cm})}for(const t of l){if(m.has(t.id)||!vr(t.a)||!vr(t.b)||"number"!=typeof t.cm||!Number.isFinite(t.cm))throw new _r("source_invalid");const e=u("cp");m.set(t.id,e),g.push({id:e,a:gr(t.a),b:gr(t.b),cm:t.cm})}const f=h.map(t=>{const e=fr(t.host);if(!e||"string"!=typeof e.id||"string"!=typeof e.kind)throw new _r("opening_host_missing");const i="wall"===e.kind?_.get(e.id):"partition"===e.kind?m.get(e.id):void 0;if(!i)throw new _r("opening_host_unknown");const s={...gr(t),id:u("co"),host:{...gr(e),kind:"partition",id:i}};return delete s.contact,delete s.lock,s}),b=c.map(t=>({...gr(t),id:u("cd")})),v=d.map(t=>({...gr(t),id:u("cc")})),y=`s${s}`;if(o.some(t=>t.id===y))throw new _r("source_invalid");const w={id:y,title:i.trim(),rooms:[],wall_segments:[],view_box:gr(n.view_box)};for(const t of wr)"view_box"!==t&&mr(n,t)&&(w[t]=gr(n[t]));g.length&&(w.partitions=g),f.length&&(w.openings=f),b.length&&(w.decor=b),v.length&&(w.wall_columns=v);const $=gr(t);return $.spaces.splice(a+1,0,w),{config:$,space:w,sourceIndex:a}}(d,o,a,e.newSeed?.()??function(t=Date.now(),e=Math.random()){const i=Math.floor(16777216*Math.max(0,Math.min(.999999999,e))).toString(36).padStart(5,"0");return`${Math.max(0,Math.floor(t)).toString(36)}${i}`}());let u=!1;try{u=t._checkSpacePhysicalGeometry(p.config,p.space.id).ok}catch{u=!1}if(!u||t._junctionLimitViolations(p.config,p.space.id).length)throw new _r("geometry_unsafe");const _=t._adoption.beginOptimistic(d,p.config);t._adoption.stageLocalConfig(p.config),Mr(t);try{await e.saveConfigNow(_)}catch(e){throw t._rollbackOptimistic(_)&&Mr(t),"conflict"!==e?.code&&await t._reloadConfigOnly(!0),e}t._canOptimizeUndo=!1,t._undoKind=null,e.clearGeometryGesture(),t._selId=null,t._physicalSel=null,t._spaceDialog=null,t._commitSpace(p.space.id,!0),e.setMode("plan"),t._tool="draw",t._path=[],t._cursorPt=null,t._activeWallChainId=null,t._activeWallChainPartitionIds=[],t._primeDrawWallField(),t._saveNav(),t.requestUpdate(),t._showToast(t._t("toast.space_copied",{name:a}))}catch(e){"conflict"===e?.code&&await Promise.all([t._reloadConfigOnly(!0),t._reloadLayoutOnly()]),xr(t,s,!1),function(t,e){if(e instanceof _r)return void t._showToast(t._t($r[e.code]));const i=e?.code;"wall_model_client_outdated"!==i?t._showToast(t._t("toast.error",{err:t._errText(e)})):t._showToast(t._t("toast.wall_model_client_outdated"))}(t,e),n&&t.requestUpdate()}}function Sr(){if(this.host._spaceDialog.copy)return function(t,e){const i=t._spaceDialog.copy,s=()=>function(t){const e=t._spaceDialog;!e?.copy||e.busy||e.copy.busy||(t._spaceDialog={...e,copy:void 0})}(t);return p`<hp-dialog .hass=${t.hass} data-kind="space"
|
||
========
|
||
</hp-dialog>`}const Oa=1e-6*E,Ba=6*E;function Ha(t){return Number.isFinite(t)?Math.round(t/E)*E:t}const Wa=(t,e,s,i)=>Math.hypot(s-t,i-e),ja=(t,e,s,i,o,a,n,r)=>Math.hypot(Math.max(Math.abs(o-t),Math.abs(o+n-(t+s))),Math.max(Math.abs(a-e),Math.abs(a+r-(e+i)))),Ga=(t,e,s,i,o,a,n)=>{const r=Math.max(Number(i)||0,0)/2,l=Math.PI/180,h=Math.cos(s*l)*r,c=Math.sin(s*l)*r,d=Math.cos(n*l)*r,p=Math.sin(n*l)*r,u=Math.max(Wa(t+h,e+c,o+d,a+p),Wa(t-h,e-c,o-d,a-p)),_=Math.max(Wa(t+h,e+c,o-d,a-p),Wa(t-h,e-c,o+d,a+p));return Math.min(u,_)},qa=t=>{const e=Number(t?.cell_cm);return e>0?e:5};function Ua(t,e){const s=JSON.parse(JSON.stringify(t||[])),i=JSON.parse(JSON.stringify(e||{}));let o=0,a=0,n=0,r=0,l="",h=0,c=0;const d=(t,e)=>{Number.isFinite(t)&&Number.isFinite(e)&&t!==e&&Math.abs(e-t)<=Oa&&c++},p=(t,e)=>{d(t[0],e[0]),d(t[1],e[1])},u={};let _=5;for(const t of s){const e=qa(t);null!=t?.id&&(u[String(t.id)]=e),e>_&&(_=e)}const m=(t,e,s,i=!1)=>{if(!(t>Oa||i))return;o++,t>n&&(n=t);const a=t*O*e;a>r&&(r=a,l=s)};for(const t of s){const e=qa(t),s=null!=t?.id?String(t.id):"";for(const i of t.rooms||[]){a++;let t=0;if(i.poly?.length)i.poly=i.poly.map(e=>{const s=[Ha(e[0]),Ha(e[1])];return t=Math.max(t,Wa(e[0],e[1],s[0],s[1])),p(e,s),s});else if(null!=i.x&&null!=i.y){const e=i.x,s=i.y,o=i.w||0,a=i.h||0,n=Ha(e+o),r=Ha(s+a),l=Ha(e),h=Ha(s),c=Math.max(E,n-l),p=Math.max(E,r-h);t=ja(e,s,o,a,l,h,c,p),i.x=l,i.y=h,i.w=c,i.h=p,d(e,l),d(s,h),d(e+o,l+c),d(s+a,h+p)}m(t,e,s)}for(const i of t.partitions||[]){a++;const o=[i.a[0],i.a[1]],n=[i.b[0],i.b[1]],r=[Ha(o[0]),Ha(o[1])],l=[Ha(n[0]),Ha(n[1])];let h=Math.max(Wa(o[0],o[1],r[0],r[1]),Wa(n[0],n[1],l[0],l[1]));const c=Wa(r[0],r[1],l[0],l[1]),d=(t.openings||[]).filter(t=>"partition"===t.host?.kind&&t.host.id===i.id).every(t=>{const e=Number(t.length),s=Number(t.host.t),i=s*c;return Number.isFinite(e)&&e>0&&Number.isFinite(s)&&s>=0&&s<=1&&i-e/2>=-Oa&&i+e/2<=c+Oa});c>Oa&&d?(i.a=r,i.b=l,p(o,r),p(n,l)):h=0,m(h,e,s)}for(const i of t.wall_columns||[]){a++;const t=[i.center[0],i.center[1]],o=[Ha(t[0]),Ha(t[1])],n=Wa(t[0],t[1],o[0],o[1]);i.center=o,p(t,o),m(n,e,s)}for(const i of t.decor||[]){if("furniture"===i.kind||"image"===i.kind)continue;a++;let t=0;if("line"===i.kind){const e=[i.x1,i.y1],s=[i.x2,i.y2],o=[Ha(e[0]),Ha(e[1])],a=[Ha(s[0]),Ha(s[1])];t=Math.max(Wa(e[0],e[1],o[0],o[1]),Wa(s[0],s[1],a[0],a[1])),i.x1=o[0],i.y1=o[1],i.x2=a[0],i.y2=a[1],p(e,o),p(s,a)}else{const e=i.x,s=i.y,o=i.w,a=i.h,n=Ha(e),r=Ha(s);if(null!=i.w&&null!=i.h){const l=Ha(e+o),h=Ha(s+a),c=Math.max(E,l-n),p=Math.max(E,h-r);t=ja(e,s,o,a,n,r,c,p),i.w=c,i.h=p,d(e+o,n+c),d(s+a,r+p)}else t=Wa(e,s,n,r);i.x=n,i.y=r,d(e,n),d(s,r)}m(t,e,s)}for(const i of t.openings||[]){if(a++,"partition"===i.host?.kind){const o=(t.partitions||[]).find(t=>t.id===i.host.id),a=Number(i.host.t);if(!o||!Number.isFinite(a)||a<0||a>1)continue;const n=o.b[0]-o.a[0],r=o.b[1]-o.a[1];if(Math.hypot(n,r)<=Oa)continue;const l=o.a[0]+n*a,c=o.a[1]+r*a;let d=180*Math.atan2(r,n)/Math.PI;d>=90?d-=180:d<-90&&(d+=180);const p=Number(i.angle),u=!(Number.isFinite(p)&&p===d),_=Ga(i.x,i.y,Number.isFinite(p)?p:d,Number(i.length)||0,l,c,d);i.x=l,i.y=c,i.angle=d,u&&h++,m(_,e,s,u);continue}const o=A([i.x,i.y],t.rooms||[],Ba,{step:E,length:Number(i.length)||0});if(!o)continue;const n=Number(i.angle),r=!(Number.isFinite(n)&&n===o.angle),l=Ga(i.x,i.y,Number.isFinite(n)?n:o.angle,Number(i.length)||0,o.x,o.y,o.angle);i.x=o.x,i.y=o.y,i.angle=o.angle,r&&h++,m(l,e,s,r)}}for(const[t,e]of Object.entries(i)){if(!e||"object"!=typeof e)continue;const s=e;if("number"!=typeof s.x||"number"!=typeof s.y)continue;a++;const o=Ha(s.x),n=Ha(s.y),r=Wa(s.x,s.y,o,n);i[t]={...s,x:o,y:n},d(s.x,o),d(s.y,n);const l="string"==typeof s.s?s.s:"";m(r,u[l]??_,l)}return{spaces:s,layout:i,report:{moved:o,coordsCanonicalized:c,total:a,maxShift:n,maxShiftCm:r,maxSpace:l,rotated:h},changed:o>0||c>0}}function Ka(t,e){const s=e.base+t*e.span;return Math.min(1,Math.max(0,s))}const Va=t=>Array.isArray(t)&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),Ja=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1]);function Za(t,e,s){const i=s[0]-e[0],o=s[1]-e[1],a=i*i+o*o;if(a<=0)return Ja(t,e);let n=((t[0]-e[0])*i+(t[1]-e[1])*o)/a;return n=Math.max(0,Math.min(1,n)),Math.hypot(t[0]-(e[0]+i*n),t[1]-(e[1]+o*n))}function Ya(t,e,s,i,o){for(const i of e)if(i&&!s.has(i.id)&&Va(i.a)&&Va(i.b)&&(Ja(t,i.a)<=o||Ja(t,i.b)<=o))return!0;for(const e of i?.roomPolygons||[])for(let s=0;s<e.length;s++){const i=e[s],a=e[(s+1)%e.length];if(Va(i)&&Va(a)&&Za(t,i,a)<=o)return!0}for(const e of i?.columns||[])if(Va(e?.center)&&Ja(t,e.center)<=o)return!0;return!1}function Xa(t,e,s,i){if(t.cm!==e.cm)return null;const o=[t.b[0]-t.a[0],t.b[1]-t.a[1]],a=[e.b[0]-e.a[0],e.b[1]-e.a[1]],n=Math.hypot(o[0],o[1]),r=Math.hypot(a[0],a[1]);if(!(n>0&&r>0))return null;if(Math.abs(o[0]/n*(a[1]/r)-o[1]/n*(a[0]/r))>s)return null;for(const[s,o]of[[t.a,e.a],[t.a,e.b],[t.b,e.a],[t.b,e.b]])if(Ja(s,o)<=i)return[(s[0]+o[0])/2,(s[1]+o[1])/2];return null}function Qa(t,e){const s=.05*(Number(e.pitch)>0?Number(e.pitch):1),i=new Map;let o=(t||[]).filter(t=>!!t&&"string"==typeof t.id&&Va(t.a)&&Va(t.b));if(o.length<2)return{partitions:[...t||[]],merged:0,openingMoves:[]};const a=e.seedIds&&e.seedIds.length?new Set(e.seedIds):null;let n=0;for(let t=0;t<o.length+1;t++){let t=null;for(let i=0;i<o.length&&!t;i++)for(let n=i+1;n<o.length;n++){const r=Xa(o[i],o[n],.02,s);if(r&&((!a||a.has(o[i].id)||a.has(o[n].id))&&!Ya(r,o,new Set([o[i].id,o[n].id]),e.geometry,s))){t={i:i,j:n,at:r};break}}if(!t)break;const r=o[t.i],l=o[t.j],h=[r.a,r.b,l.a,l.b].filter(e=>Ja(e,t.at)>s);let c=h[0]??r.a,d=h[h.length-1]??l.b;if(h.length<2&&(c=r.a,d=l.b),d[0]<c[0]||d[0]===c[0]&&d[1]<c[1]){const t=c;c=d,d=t}const p={...r,a:[c[0],c[1]],b:[d[0],d[1]]},u=Ja(c,d),_=u>0?(d[0]-c[0])/u:0,m=u>0?(d[1]-c[1])/u:0,g=t=>u>0?((t[0]-c[0])*_+(t[1]-c[1])*m)/u:0;for(const t of[r,l]){const e=g(t.a),s=g(t.b)-e;for(const[o,a]of i)a.toId===t.id&&i.set(o,{fromId:a.fromId,toId:p.id,base:e+a.base*s,span:a.span*s});i.set(t.id,{fromId:t.id,toId:p.id,base:e,span:s})}a&&a.add(p.id),o=o.filter((e,s)=>s!==t.i&&s!==t.j),o.splice(t.i,0,p),n++}return{partitions:o,merged:n,openingMoves:[...i.values()]}}function tn(t,e,s,i){if(!t?.length||!s.length)return 0;const o=new Map(s.map(t=>[t.fromId,t]));let a=0;for(const s of t){const t=s?.host;if(!t||"partition"!==t.kind)continue;const n=o.get(t.id);if(!n)continue;s.host={...t,id:n.toId,t:Ka(t.t,n)},a++;const r=H(s,e,i.coordScale,i.cellCm,i.gridPitch).resolved;r&&Object.assign(s,W(s,r,i.coordScale))}return a}function en(t){return{roomPolygons:(t?.rooms||[]).map(t=>B(t)).filter(t=>!!t),columns:t?.wall_columns||[]}}const sn=t=>!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),on=(t,e)=>t[0]-e[0]||t[1]-e[1],an=(t,e,s,i)=>[t[0]+e*i,t[1]+s*i],nn=(t,e,s,i)=>(t[0]-e[0])*s+(t[1]-e[1])*i,rn=(t,e,s,i,o)=>{const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(!(r>o))return null;const l=a/r,h=n/r,c=e=>Math.abs((e[0]-t[0])*h-(e[1]-t[1])*l);if(c(s)>o||c(i)>o)return null;const d=nn(s,t,l,h),p=nn(i,t,l,h),u=Math.max(0,Math.min(d,p)),_=Math.min(r,Math.max(d,p));return _-u>o?{lo:u,hi:_}:null},ln=(t,e,s)=>Math.min(t.hi,e.hi)-Math.max(t.lo,e.lo)>s,hn=t=>{const e=new Set(["id","a","b","cm"]);return Object.keys(t||{}).every(t=>e.has(t))},cn=(t,e,s,i)=>{const o=t.b[0]-t.a[0],a=t.b[1]-t.a[1],n=Math.hypot(o,a);if(!(n>i))return!0;const r=o/n,l=a/n,h=X(t.cm,s.cellCm,s.gridPitch)/2;return e.some(e=>{const o=e?.center;if(!sn(o))return!0;const a=nn(o,t.a,r,l),c=Math.abs((o[0]-t.a[0])*l-(o[1]-t.a[1])*r),d=X(Number(e.cm),s.cellCm,s.gridPitch)*("square"===e.shape?Math.SQRT1_2:.5);return!(Number.isFinite(d)&&d>0)||a>=-d-i&&a<=n+d+i&&c<=h+d+i})},dn=(t,e,s)=>{if(t.host){const i=H(t,e,s.coordScale,s.cellCm,s.gridPitch).resolved;return i?{center:i.center,angle:i.angle,length:i.length}:null}const i=Number(t.x)*s.coordScale,o=Number(t.y)*s.coordScale,a=Number(t.angle),n=Number(t.length)*s.coordScale;return[i,o,a,n].every(Number.isFinite)&&n>0?{center:[i,o],angle:a,length:n}:null},pn=(t,e,s)=>{const i=t.angle*Math.PI/180,o=Math.cos(i),a=Math.sin(i),n=e.angle*Math.PI/180,r=Math.cos(n),l=Math.sin(n);if(Math.abs(o*l-a*r)>1e-6)return!1;const h=e.center[0]-t.center[0],c=e.center[1]-t.center[1];if(Math.abs(h*a-c*o)>s)return!1;const d=h*o+c*a;return Math.max(-t.length/2,d-e.length/2)<Math.min(t.length/2,d+e.length/2)-s},un=(t,e)=>({...t,a:[t.a[0]*e,t.a[1]*e],b:[t.b[0]*e,t.b[1]*e]}),_n=(t,e,s,i)=>{const o=`~r-${(t=>{let e=2166136261;for(let s=0;s<t.length;s++)e^=t.charCodeAt(s),e=Math.imul(e,16777619)>>>0;return e.toString(36)})(`${t}|${e[0].toFixed(9)},${e[1].toFixed(9)}|${s[0].toFixed(9)},${s[1].toFixed(9)}`)}`,a=`${t.slice(0,Math.max(1,64-o.length))}${o}`;let n=a;for(let t=2;i.has(n);t++){const e=`-${t}`;n=`${a.slice(0,64-e.length)}${e}`}return i.add(n),n},mn=(t,e)=>{const s=[];for(const i of t){const t=s[s.length-1];!(t&&Math.abs(t.hi-i.lo)<=e&&t.safe===i.safe)||i.safe&&t.signature!==i.signature?s.push({lo:i.lo,hi:i.hi,a:i.a,b:i.b,safe:i.safe,signature:i.signature,roomIds:i.roomIds,finalCm:i.finalCm}):(t.hi=i.hi,t.b=i.b)}return s};function gn(t,e,s,i,o){const a=s||[],n=Array.isArray(t?.partitions)?t.partitions:[],r=Array.isArray(t?.openings)?t.openings:[],l={walls:a,partitions:n,openings:r,partitionsReconciled:0,openingsRehosted:0};if(!n.length)return l;const h=Math.max(2e-4*o.gridPitch,1e-9);let c=a,d=n,p=r,u=0,_=0;const m=o.partitionIds?new Set(o.partitionIds):null,g=new Map(e.partitions.map(t=>[t.id,t]));for(const t of[...n].sort((t,e)=>t.id.localeCompare(e.id))){if(m&&!m.has(t.id))continue;if(!d.some(e=>e.id===t.id))continue;if(!hn(t))continue;const s=g.get(t.id);if(!(s&&sn(s.a)&&sn(s.b)&&Number.isFinite(s.cm)&&(o.allowCoincidentPartitions?!(s.cm<0):s.cm>0)))continue;const[a,n]=on(s.a,s.b)<=0?[[s.a[0],s.a[1]],[s.b[0],s.b[1]]]:[[s.b[0],s.b[1]],[s.a[0],s.a[1]]],r=n[0]-a[0],l=n[1]-a[1],f=Math.hypot(r,l);if(!(f>h))continue;const b=r/f,v=l/f,y=j(e.rooms,c,i,o.pitch,o.cellCm,o.gridPitch,o.coordScale),w=y.flatMap(t=>{if(t.open||"outer"!==t.kind&&"shared"!==t.kind)return[];const e=rn(a,n,t.a,t.b,h);return e?[{interval:t,range:e}]:[]});if(!w.length)continue;const $=p.filter(t=>"partition"===t.host?.kind&&t.host.id===s.id).map(t=>({opening:t,resolved:H(t,e.partitions,o.coordScale,o.cellCm,o.gridPitch).resolved}));if($.some(t=>!t.resolved))continue;const k=[0,f];for(const{range:t}of w)k.push(t.lo,t.hi);const x=k.slice(),M=new Map;for(const{opening:t,resolved:e}of $){const s=nn(e.center,a,b,v),i={lo:s-e.length/2,hi:s+e.length/2};M.set(t.id,i),x.push(Math.max(0,i.lo),Math.min(f,i.hi))}const C=[...new Set(x.filter(t=>Number.isFinite(t)&&t>=-h&&t<=f+h).map(t=>Math.max(0,Math.min(f,t)).toFixed(9)))].map(Number).sort((t,e)=>t-e),S=d.map(t=>un(t,o.coordScale)).filter(t=>t.id!==s.id),P=[];for(let t=0;t+1<C.length;t++){const i=C[t],n=C[t+1];if(!(n-i>h))continue;const r=an(a,b,v,i),l=an(a,b,v,n),c=w.filter(({range:t})=>t.lo<=i+h&&t.hi>=n-h).map(({interval:t})=>t),d=new Map;for(const t of c)d.set(t.roomId,t);const p=[...d.values()],u=new Set(p.map(t=>t.kind)),_=new Set(p.map(t=>o.allowCoincidentPartitions||t.cm>0?t.cm:G)),m=p[0]?.kind,g=[...d.keys()].sort(),f=1===u.size&&1===_.size&&("outer"===m&&1===g.length||"shared"===m&&2===g.length),y={id:s.id,a:r,b:l,cm:s.cm},$=S.some(t=>!!rn(r,l,t.a,t.b,h)),k=f&&(o.allowCoincidentPartitions||!$)&&!cn(y,e.wall_columns,o,h),x=f?o.allowCoincidentPartitions||p[0].cm>0?p[0].cm:G:0,M=f?Math.max(x,s.cm):s.cm;P.push({lo:i,hi:n,a:r,b:l,safe:k,signature:k?`${m}|${g.join(",")}|${M}`:"",roomIds:g,roomCm:x,finalCm:M})}if(!P.some(t=>t.safe))continue;const I=new Map;for(const{opening:t,resolved:e}of $){const i=M.get(t.id),a=k.some(t=>t>i.lo+h&&t<i.hi-h),n=P.filter(t=>ln(t,i,h)),r=new Set(n.filter(t=>t.safe).map(t=>t.signature));if(!a&&n.length>0&&n.every(t=>t.safe)&&1===r.size&&q(e,y,h)){I.set(t.id,{resolved:e,signature:[...r][0]});continue}const l=U(s,o.cellCm,o.gridPitch),c={lo:i.lo-l,hi:i.hi+l};for(const t of P)ln(t,c,h)&&(t.safe=!1,t.signature="")}let D=!0;for(;D;){D=!1;for(const[t,e]of[...I.entries()]){const i=M.get(t),a=P.filter(t=>ln(t,i,h));if(a.length>0&&a.every(t=>t.safe)&&a.every(t=>t.signature===e.signature))continue;I.delete(t);const n=U(s,o.cellCm,o.gridPitch),r={lo:i.lo-n,hi:i.hi+n};for(const t of P)ln(t,r,h)&&(t.safe=!1,t.signature="");D=!0}}const L=mn(P,h),T=L.filter(t=>t.safe),R=L.filter(t=>!t.safe);if(!T.length)continue;if(d.length-1+R.length>2e3)continue;let z=c;for(const t of T){const[e,i]=on(s.a,s.b)<=0?[t.a,t.b]:[t.b,t.a];z=K(z,e,i,t.finalCm,o.pitch,o.coordScale)}if(z=V(e.rooms,z,i,o.pitch,o.cellCm,o.gridPitch,o.coordScale),z.length>500)continue;const F=new Set(d.map(t=>t.id));F.delete(s.id);const N=R.map((t,e)=>{const i=[t.a[0]/o.coordScale,t.a[1]/o.coordScale],a=[t.b[0]/o.coordScale,t.b[1]/o.coordScale],n=0===e?s.id:_n(s.id,i,a,F);return F.add(n),{id:n,a:i,b:a,cm:s.cm}}),A=d.findIndex(t=>t.id===s.id),E=d.slice();E.splice(A,1,...N);const O=E.map(t=>un(t,o.coordScale)),B=new Map;let X=!0;for(const{opening:t,resolved:e}of $){const s=I.get(t.id);if(s){const e=W(t,s.resolved,o.coordScale),{host:i,...a}=e;B.set(t.id,a);continue}const i=M.get(t.id),a=N[R.findIndex(t=>t.lo<=i.lo+h&&t.hi>=i.hi-h)],n=a&&O.find(t=>t.id===a.id);if(!a||!n){X=!1;break}const r=n.b[0]-n.a[0],l=n.b[1]-n.a[1],c=Math.hypot(r,l),d=nn(e.center,n.a,r/c,l/c),p={...W(t,e,o.coordScale),host:{kind:"partition",id:a.id,t:d/c}};if(!J(p,O,o.coordScale,o.cellCm,o.gridPitch).resolved){X=!1;break}B.set(t.id,p)}if(!X)continue;const Q=p.map(t=>B.get(t.id)||t),tt=[...I.keys()].map(t=>B.get(t)),et=tt.map(t=>dn(t,O,o));if(et.some(t=>!t))continue;let st=!1;for(let t=0;t<et.length;t++)for(let e=t+1;e<et.length;e++)pn(et[t],et[e],h)&&(st=!0);const it=new Set(tt.map(t=>t.id));for(const t of Q){if(it.has(t.id))continue;const e=dn(t,O,o);e&&et.some(t=>pn(t,e,h))&&(st=!0)}if(st)continue;const ot=Z(e.rooms,z,i,o.pitch,o.cellCm,o.gridPitch,o.coordScale);[...I.entries()].every(([t,e])=>{const s=B.get(t),i=Y(ot,{x:s.x*o.coordScale,y:s.y*o.coordScale,angle:s.angle,length:s.length*o.coordScale},!0),a=[i.negative,i.positive].filter(t=>!!t?.full),n=e.signature.split("|")[1].split(","),r=new Set(a.map(t=>t.roomId));return a.length===n.length&&r.size===n.length&&n.every(t=>r.has(t))})&&(c=z,d=E,p=Q,u+=T.length,_+=I.size)}return{walls:c,partitions:d,openings:p,partitionsReconciled:u,openingsRehosted:_}}const fn=t=>JSON.parse(JSON.stringify(t)),bn=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),vn=(t,e)=>e.length>0&&e.length<=35&&("space"===t?/^[a-z0-9_-]+$/.test(e):/^[A-Za-z0-9_-]+$/.test(e));function yn(t,e){let s=String(e??"");const i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o=new RegExp(`^${i}_(.+)_([0-9a-f]{8})$`);let a=0;for(;a<16;a++){const t=o.exec(s);if(!t)return{root:s,layers:a,bounded:!1};s=t[1]}return{root:s,layers:a,bounded:o.test(s)}}const wn=(t,e,s)=>{const i=t.get(e)||[];i.push(s),t.set(e,i)};const $n=1e-9;class kn extends Error{constructor(t,e=""){super(e?`${t}: ${e}`:t),this.reason=t,this.name="WallSegmentModelError"}}const xn=t=>JSON.parse(JSON.stringify(t)),Mn=t=>Array.isArray(t)&&t.length>=2&&Number.isFinite(Number(t[0]))&&Number.isFinite(Number(t[1])),Cn=t=>[Number(t[0]),Number(t[1])],Sn=t=>`${Number(t[0]).toFixed(12)},${Number(t[1]).toFixed(12)}`,Pn=(t,e)=>{const s=Sn(t),i=Sn(e);return s<i?`${s}|${i}`:`${i}|${s}`},In=(t,e)=>Sn(t)<=Sn(e)?[Cn(t),Cn(e)]:[Cn(e),Cn(t)],Dn=(t,e)=>Math.hypot(e[0]-t[0],e[1]-t[1]),Ln=(t,e=[])=>{const s=new Set,i=t=>{const e=Number(t);if(!Number.isFinite(e))return;const i=e/E;Math.abs(i-Math.round(i))>=ot&&s.add(e.toFixed(12))};for(const e of Array.isArray(t?.rooms)?t.rooms:[])for(const t of B(e)||[])i(t[0]),i(t[1]);for(const e of[t?.wall_segments,t?.walls])for(const t of Array.isArray(e)?e:[])i(t?.a?.[0]),i(t?.a?.[1]),i(t?.b?.[0]),i(t?.b?.[1]);for(const t of e)i(t?.[0]),i(t?.[1]);return s.size},Tn=(t,e,s)=>{const i=s[0]-e[0],o=s[1]-e[1],a=i*i+o*o;return a>1e-18?((t[0]-e[0])*i+(t[1]-e[1])*o)/a:0},Rn=(t,e,s)=>{const i=Math.max(0,Math.min(1,Tn(t,e,s)));return Math.hypot(t[0]-(e[0]+(s[0]-e[0])*i),t[1]-(e[1]+(s[1]-e[1])*i))},zn=(t,e,s,i,o=1e-9)=>{const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(r<=o)return 0;const l=e=>Math.abs((e[0]-t[0])*n-(e[1]-t[1])*a)/r;if(l(s)>o||l(i)>o)return 0;const h=Tn(s,t,e),c=Tn(i,t,e);return Math.max(0,Math.min(1,Math.max(h,c))-Math.max(0,Math.min(h,c)))*r},Fn=t=>{const e=(new TextEncoder).encode(t),s=8*e.length,i=64*Math.ceil((e.length+9)/64),o=new Uint8Array(i);o.set(e),o[e.length]=128;const a=new DataView(o.buffer);a.setUint32(i-8,Math.floor(s/4294967296),!1),a.setUint32(i-4,s>>>0,!1);const n=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),r=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),l=new Uint32Array(64),h=(t,e)=>t>>>e|t<<32-e;for(let t=0;t<i;t+=64){for(let e=0;e<16;e++)l[e]=a.getUint32(t+4*e,!1);for(let t=16;t<64;t++){const e=l[t-15],s=l[t-2],i=h(e,7)^h(e,18)^e>>>3,o=h(s,17)^h(s,19)^s>>>10;l[t]=l[t-16]+i+l[t-7]+o>>>0}let[e,s,i,o,c,d,p,u]=r;for(let t=0;t<64;t++){const a=u+(h(c,6)^h(c,11)^h(c,25))+(c&d^~c&p)+n[t]+l[t]>>>0,r=e&s^e&i^s&i;u=p,p=d,d=c,c=o+a>>>0,o=i,i=s,s=e,e=a+((h(e,2)^h(e,13)^h(e,22))+r>>>0)>>>0}r[0]=r[0]+e>>>0,r[1]=r[1]+s>>>0,r[2]=r[2]+i>>>0,r[3]=r[3]+o>>>0,r[4]=r[4]+c>>>0,r[5]=r[5]+d>>>0,r[6]=r[6]+p>>>0,r[7]=r[7]+u>>>0}const c=new Uint8Array(32),d=new DataView(c.buffer);for(let t=0;t<r.length;t++)d.setUint32(4*t,r[t],!1);return c},Nn=t=>{const e="abcdefghijklmnopqrstuvwxyz234567";let s=0,i=0,o="";for(const a of t)for(i=i<<8|a,s+=8;s>=5;)o+=e[i>>>s-5&31],s-=5;return s&&(o+=e[i<<5-s&31]),o},An=(t,e,s,i,o="")=>{const[a,n]=In(e,s),r=`${t}|${Sn(a)}|${Sn(n)}|${[...i].sort().join(",")}${o}`;return`wall-${Nn(Fn(r)).slice(0,20)}`};let En=0;const On=t=>{for(let e=0;e<1e3;e++){const e=globalThis.crypto?.randomUUID?.(),s=`wall-${e||Nn(Fn(`${Date.now()}|${En++}|${Math.random()}`)).slice(0,26)}`;if(!t.has(s))return s}throw new kn("duplicate-id","id factory exhausted")},Bn=t=>{const e=new Map;for(const s of Array.isArray(t?.wall_segments)?t.wall_segments:[])if(s&&"string"==typeof s.id&&Mn(s.a)&&Mn(s.b)){if(e.has(s.id))throw new kn("duplicate-id",s.id);e.set(s.id,s)}return e},Hn=(t,e,s)=>{const i=(s,i)=>{const o=t[0]-s[0],a=t[1]-s[1];return Math.abs(e[0]-i[0]-o)<=$n&&Math.abs(e[1]-i[1]-a)<=$n?[o,a]:null};return i(s.a,s.b)||i(s.b,s.a)},Wn=(t,e)=>{const s=Array.isArray(t.rooms)?t.rooms:[],i=et(t.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]),o=i.length?i:st(s,null,1,.04*E,!0),a=[];for(const t of s){const s=B(t),i=Array.isArray(t?.wall_ids)?t.wall_ids:[];if(s&&i.length===s.length)for(let t=0;t<i.length;t++){const o="string"==typeof i[t]?e.get(i[t]):null;0===Number(o?.cm)&&a.push([s[t][0],s[t][1],s[(t+1)%s.length][0],s[(t+1)%s.length][1]])}}const n=[...a,...o],r=o.length?(Array.isArray(t.openings)?t.openings:[]).filter(t=>"partition"!==t.host?.kind&&[Number(t.x),Number(t.y)].every(Number.isFinite)&&Number.isFinite(Number(t.angle))&&Number(t.length)>0&&o.some(e=>Rn([Number(t.x),Number(t.y)],[e[0],e[1]],[e[2],e[3]])<=.04*E)):[],l=r.map(t=>{const e=Number(t.angle)*Math.PI/180,s=[Math.cos(e),Math.sin(e)],i=Number(t.length)/2,o=[Number(t.x),Number(t.y)];return{a:[o[0]-s[0]*i,o[1]-s[1]*i],b:[o[0]+s[0]*i,o[1]+s[1]*i]}}),h=(t,e)=>r.some(s=>{const i=[Number(s.x),Number(s.y)];if(!at(t,e,Number(s.angle)))return!1;if(Rn(i,t,e)>.02*E)return!1;const o=Dn(t,e),a=Tn(i,t,e)*o,n=Number(s.length)/2;return a+n>=-1e-9&&a-n<=o+$n}),c=new Map,d=[];for(const i of s){const r=String(i?.id||""),p=B(i);if(!r||!p||p.length<3)throw new kn("invalid-room",r);const u=it(s,r,n,E,1,[...t.walls||[],...l]);if(!u||u.poly.length<3)throw new kn("invalid-room",r);const _=Array.isArray(i.wall_ids)?i.wall_ids:[],m=_.length===p.length;let g=null,f=m;if(f)for(let t=0;t<p.length;t++){const s=e.get(_[t]),i=s?Hn(p[t],p[(t+1)%p.length],s):null;if(!i||g&&(Math.abs(i[0]-g[0])>$n||Math.abs(i[1]-g[1])>$n)){f=!1;break}g=i}const b=[];for(let t=0;t<u.poly.length;t++){const s=u.poly[t],i=u.poly[(t+1)%u.poly.length];if(Dn(s,i)<=$n)throw new kn("zero-length",r);const n=Pn(s,i);let l=c.get(n);if(!l){const[t,e]=In(s,i);l={key:n,a:t,b:e,owners:new Set,preferredIds:new Set,positionalIds:new Set,preferredCarriers:new Map,parentKeys:new Set,zeroWall:!1},c.set(n,l)}if(l.owners.add(r),l.owners.size>2)throw new kn("third-owner",n);const d=m?_[u.parent[t]]:void 0;if("string"==typeof d&&d){const o=e.get(d);f||!o||zn(s,i,o.a,o.b)>$n?l.preferredIds.add(d):l.positionalIds.add(d),l.preferredCarriers.set(d,{a:Cn(p[u.parent[t]]),b:Cn(p[(u.parent[t]+1)%p.length])})}const g=u.parent[t];l.parentKeys.add(tt(p[g],p[(g+1)%p.length],E));const v=[(s[0]+i[0])/2,(s[1]+i[1])/2],y=t=>t.some(t=>Rn(v,[t[0],t[1]],[t[2],t[3]])<=.04*E);l.zeroWall||=y(a)||y(o)&&!h(s,i),b.push(n)}const v={...i};delete v.wall_ids,d.push({...v,poly:u.poly.map(t=>[t[0],t[1]]),wall_ids:b})}return{atoms:[...c.values()].sort((t,e)=>t.key.localeCompare(e.key)),rooms:d}},jn=(t,e,s,i,o)=>{const a=new Map([...s.values()].map(t=>[Pn(t.a,t.b),t])),n=(t=>{const e=new Map;for(const s of t)"wall"===s.host?.kind&&e.set(s.host.id,(e.get(s.host.id)||0)+1);return e})(t.openings||[]),r=new Map;for(const t of e){const e=o?.get(t.key);if(e){const i=s.get(e);if(!i)throw new kn("duplicate-id",e);r.set(t,i);continue}if(t.preferredIds.size>1)throw new kn("duplicate-id",[...t.preferredIds].sort().join(","));const i=[...t.preferredIds][0],l=i?s.get(i):void 0;if(l){r.set(t,l);continue}const h=i?t.preferredCarriers.get(i):void 0;if(i&&h){r.set(t,{id:i,a:h.a,b:h.b,cm:0});continue}const c=a.get(t.key);if(c){r.set(t,c);continue}const d=[...s.values()].filter(e=>zn(t.a,t.b,e.a,e.b)>$n),p=[...new Map(d.map(t=>[t.id,t])).values()];if(p.sort((t,e)=>(n.get(e.id)||0)-(n.get(t.id)||0)||Dn(e.a,e.b)-Dn(t.a,t.b)||t.id.localeCompare(e.id)),p[0])r.set(t,p[0]);else if(1===t.positionalIds.size){const e=s.get([...t.positionalIds][0]);e&&r.set(t,e)}}const l=new Map;for(const[t,e]of r){const s=l.get(e.id)||[];s.push(t),l.set(e.id,s)}for(const[t,e]of l){const i=s.get(t)||r.get(e[0]);if(!i)throw new kn("duplicate-id",t);const o=[(i.a[0]+i.b[0])/2,(i.a[1]+i.b[1])/2];e.sort((t,e)=>{const s=Rn(o,t.a,t.b)<=$n?0:1,a=Rn(o,e.a,e.b)<=$n?0:1;if(s!==a)return s-a;return(Rn(i.a,t.a,t.b)<=$n?0:1)-(Rn(i.a,e.a,e.b)<=$n?0:1)||t.key.localeCompare(e.key)}),e[0].id=t}const h=(t=>{const e=new Set;for(const s of[t.rooms,t.openings,t.decor,t.room_drafts,t.partitions,t.wall_columns])for(const t of Array.isArray(s)?s:[])"string"==typeof t?.id&&t.id&&e.add(t.id);for(const s of Array.isArray(t.room_drafts)?t.room_drafts:[])for(const t of Array.isArray(s?.segments)?s.segments:[])"string"==typeof t?.id&&t.id&&e.add(t.id);return e})(t);for(const t of e)if(t.id){if(h.has(t.id))throw new kn("duplicate-id",t.id);h.add(t.id)}const c=e.filter(t=>!t.id);if(i){const e=c.map(e=>{const[s,i]=In(e.a,e.b),o=`${String(t.id||"")}|${Sn(s)}|${Sn(i)}|${[...e.owners].sort().join(",")}`,a=Nn(Fn(o));return{atom:e,seed:o,digest:a,base:`wall-${a.slice(0,20)}`}}).sort((t,e)=>t.digest.localeCompare(e.digest)||t.atom.key.localeCompare(e.atom.key)),s=new Map;for(const t of e){const e=s.get(t.digest);if(e&&e!==t.seed)throw new kn("duplicate-id",t.digest);s.set(t.digest,t.seed);let i=1,o=t.base;for(;h.has(o);)o=`${t.base}-${++i}`;t.atom.id=o,h.add(o)}}else for(const t of c)t.id=On(h),h.add(t.id)},Gn=(t,e)=>{if("partition"===t.host?.kind)return null;const s=[Number(t.x),Number(t.y)];if(!s.every(Number.isFinite))return null;const i=e=>{if(!(Number(e.cm)>0))return!1;const i=Tn(s,e.a,e.b),o=Dn(e.a,e.b),a=Number(t.length)/2;return i>=-1e-9&&i<=1+$n&&Rn(s,e.a,e.b)<=.02*E&&at(e.a,e.b,Number(t.angle))&&Number.isFinite(a)&&a>=0&&i*o-a>=-1e-9&&i*o+a<=o+$n},o="wall"===t.host?.kind?e.find(e=>e.id===t.host.id):null,a=o&&i(o)?[o]:e.filter(i);if(1!==a.length)return null;const n=a[0];return{kind:"wall",id:n.id,t:Math.max(0,Math.min(1,Tn(s,n.a,n.b)))}},qn=(t,e)=>{const s=[Number(t.x),Number(t.y)];if(!s.every(Number.isFinite))return null;const i=Number(t.length)/2,o=e.filter(e=>{if(!(Number(e.cm)>0))return!1;const o=Tn(s,e.a,e.b),a=Dn(e.a,e.b);return o>=-1e-9&&o<=1+$n&&Rn(s,e.a,e.b)<=.02*E&&at(e.a,e.b,Number(t.angle))&&Number.isFinite(i)&&i>=0&&o*a-i>=-1e-9&&o*a+i<=a+$n}),a=(e=>{if(!e.length)return null;const i="wall"===t.host?.kind?e.find(e=>e.id===t.host.id):null;return i||[...e].sort((t,e)=>Rn(s,t.a,t.b)-Rn(s,e.a,e.b)||Number(e.cm)-Number(t.cm)||(t.id<e.id?-1:t.id>e.id?1:0))[0]})(o);return a?{kind:"wall",id:a.id,t:Math.max(0,Math.min(1,Tn(s,a.a,a.b)))}:null},Un=/^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/,Kn=t=>{if("number"!=typeof t&&"string"!=typeof t)return null;if("string"==typeof t&&!Un.test(t.trim()))return null;const e=Number(t);return Number.isFinite(e)?e:null},Vn=t=>{if(!Array.isArray(t)||t.length<2)return null;const e=Kn(t[0]),s=Kn(t[1]);return null==e||null==s?null:[e,s]},Jn=t=>"string"==typeof t?t:"",Zn=t=>{if(!Object.prototype.hasOwnProperty.call(t,"room_drafts"))return{drafts:0,segments:0};const e=Array.isArray(t.room_drafts)?t.room_drafts:[];if(!e.length)return delete t.room_drafts,{drafts:0,segments:0};const s=new Set;for(const e of[t.rooms,t.openings,t.decor,t.partitions,t.wall_columns,t.wall_segments])for(const t of Array.isArray(e)?e:[])"string"==typeof t?.id&&t.id&&s.add(t.id);for(const t of e)"string"==typeof t?.id&&t.id&&s.add(t.id);const i=Array.isArray(t.partitions)?[...t.partitions]:[];let o=0;for(const a of e){const e=Jn(a?.id),n=Array.isArray(a?.points)?a.points:[],r=Array.isArray(a?.segments)?a.segments:[];if(n.length<2||r.length!==n.length-1)throw new kn("zero-length",e);for(let a=0;a+1<n.length;a++){const l=Vn(n[a]),h=Vn(n[a+1]),c=r[a];if(!l||!h||nt(l,h,.001))throw new kn("zero-length",e);const d=Kn(c?.cm);if(null==d||d<0||d>100)throw new kn("thickness-conflict",e);let p="string"==typeof c?.id&&c.id?c.id:"";if(!p||s.has(p)){const i=An(Jn(t.id),l,h,[`draft:${e}:${a}`]);p=i;for(let t=2;s.has(p);t++)p=`${i}-${t}`}s.add(p),i.push({id:p,a:Cn(l),b:Cn(h),cm:d}),o++}}return i.length?t.partitions=i:delete t.partitions,delete t.room_drafts,{drafts:e.length,segments:o}},Yn=t=>Zn(t),Xn=(t,e,s)=>{const i=Zn(t),o=Bn(t),{atoms:a,rooms:n}=Wn(t,o);jn(t,a,o,e,s);const r=a.map(e=>{const s=e.id?o.get(e.id):void 0,i=((t,e,s)=>{if(e.zeroWall)return 0;const i=Array.isArray(t.walls)?t.walls:[],o=tt(e.a,e.b,E),a=i.filter(t=>Number(t.cm)>0&&(!(t.key!==o&&!e.parentKeys.has(t.key))||!(!Mn(t.a)||!Mn(t.b))&&zn(e.a,e.b,t.a,t.b)>=Dn(e.a,e.b)-$n)).map(t=>Math.max(1,Math.min(100,Number(t.cm))));if(new Set(a.map(t=>t.toFixed(9))).size>1)throw new kn("thickness-conflict",e.key);if(a.length)return a[0];const n=rt(i,e.a,e.b,E,1);return n>0?n:Number(s?.cm)>0?Number(s.cm):0})(t,e,s);return{...s||{},id:e.id,a:[...e.a],b:[...e.b],cm:i}}),l=new Map(a.map(t=>[t.key,t.id]));for(const t of n)t.wall_ids=t.wall_ids.map(t=>l.get(t));t.rooms=n,t.wall_segments=r,t.walls=r.filter(t=>t.cm>0).map(t=>({key:tt(t.a,t.b,E),cm:t.cm,a:[...t.a],b:[...t.b]})),t.walls.length||delete t.walls,delete t.open_spans;for(const e of t.rooms)delete e.open_to;return((t,e,s)=>{const i=Array.isArray(t.openings)?t.openings:[];for(const t of i){if("partition"===t.host?.kind)continue;if(!t.host&&!s){const s=Gn(t,e);s&&(t.host=s);continue}const i=Gn(t,e)??(s?qn(t,e):null);if(i)t.host=i;else{if(!s)throw new kn("opening-host",t.id);delete t.host}}})(t,r,e),{wallSegments:r.reduce((t,e)=>t+(o.has(e.id)?0:1),0),drafts:i.drafts,draftSegments:i.segments}};function Qn(t,e={}){const s=JSON.stringify(t),i=xn(t);Q(i);let o=0,a=0,n=0;const r=Number(i?.model_version||0)<10;for(const t of Array.isArray(i?.spaces)?i.spaces:[]){const s=e.lineageSpaceId===String(t?.id||"")?e.lineageHints:void 0,i=Xn(t,r,s);o+=i.wallSegments,a+=i.drafts,n+=i.draftSegments}return i.model_version=10,Q(i),{config:i,changed:s!==JSON.stringify(i),migratedSegments:o,migratedDrafts:a,migratedDraftSegments:n}}const tr=t=>!!t&&"object"==typeof t&&!Array.isArray(t);function er(t,e){const s=(t,e)=>{if(Array.isArray(t)&&Array.isArray(e)){const i=new Map;for(const e of t)tr(e)&&"string"==typeof e.id&&e.id&&i.set(e.id,e);const o=e.map((e,o)=>{if(tr(e)&&"string"==typeof e.id&&e.id){const t=i.get(e.id);return t?s(t,e):xn(e)}return o<t.length?s(t[o],e):xn(e)});return t.splice(0,t.length,...o),t}if(tr(t)&&tr(e)){const i=Object.entries(e).map(([e,i])=>[e,e in t?s(t[e],i):xn(i)]);for(const e of Object.keys(t))delete t[e];for(const[e,s]of i)t[e]=s;return t}return xn(e)};return s(t,e)}const sr=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),ir=(t,e,s)=>Math.min(s,Math.max(e,t)),or=t=>$t({spaces:[t]})[0],ar=(t,e,s)=>{const i=s>0?s:1,o=t=>`${(t[0]/i).toFixed(12)},${(t[1]/i).toFixed(12)}`,a=o(t),n=o(e);return a<n?`${a}|${n}`:`${n}|${a}`};function nr(t,e,s,i,o,a,n=1){if(!e?.length)return[];const r=n>0?n:1,l=Math.max(i*r*.02,1e-9),h=[];for(const e of t||[])for(const t of B(e)||[])h.push([t[0],t[1]]);const c=[];for(const t of s||[])Array.isArray(t)&&t.length>=4&&t.slice(0,4).every(Number.isFinite)&&c.push([t[0],t[1]],[t[2],t[3]]);const d=(t,e)=>e.some(e=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l),p=new Map;for(const n of t||[]){if(!n?.id)continue;const u=kt(t,n.id,e,s,i,o,a,r);if(u)for(let t=0;t<u.orig.length;t++){const e=[];for(let s=0;s<u.parent.length;s++)u.parent[s]===t&&e.push(s);for(let t=1;t+1<e.length;t++){const s=e[t-1],i=e[t],o=e[t+1];if(null===u.kinds[s]||null===u.kinds[i]||null===u.kinds[o])continue;const n=u.cms[s],_=u.cms[i],m=u.cms[o];if(!(n>0&&_>0&&n===m&&_!==n))continue;const g=u.poly[i],f=u.poly[(i+1)%u.poly.length],b=Math.hypot(f[0]-g[0],f[1]-g[1]);if(!(b>l&&b<.5*a-1e-9*a))continue;if(d(g,c)||d(f,c))continue;if(d(g,h)&&d(f,h))continue;const v=ar(g,f,r),y=p.get(v);y?y.targets.add(n):p.set(v,{a:[g[0],g[1]],b:[f[0],f[1]],targets:new Set([n])})}}}let u=e.slice();const _=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l,m=(t,e)=>{if(!Array.isArray(t.a)||!Array.isArray(t.b)||t.a.length<2||t.b.length<2)return!1;const s=[Number(t.a[0])*r,Number(t.a[1])*r],i=[Number(t.b[0])*r,Number(t.b[1])*r];return!![...s,...i].every(Number.isFinite)&&(_(s,e.a)&&_(i,e.b)||_(s,e.b)&&_(i,e.a))};for(const t of[...p.values()].filter(t=>1===t.targets.size).sort((t,e)=>ar(t.a,t.b,r).localeCompare(ar(e.a,e.b,r)))){const e=[...t.targets][0],s=u.filter(e=>m(e,t));if(new Set(s.map(t=>t.cm)).size>1)continue;let o=!1;u=u.map(s=>m(s,t)?(o=!0,s.cm===e?s:{...s,cm:e}):s),o||(u=K(u,t.a,t.b,e,i,r))}return u}const rr=t=>{const e=[];for(const s of t||[]){const t=B(s);if(t?.length)for(let s=0;s<t.length;s++)e.push([[t[s][0],t[s][1]],[t[(s+1)%t.length][0],t[(s+1)%t.length][1]]])}return e};function lr(t,e,s={},i={}){const o=i.reconcileCoincidentPartitions??gn,a=function(t,e,s={}){const i=fn(t||{spaces:[],markers:[],settings:{}}),o=fn(e||{}),a=JSON.stringify(i),n=JSON.stringify(o),r=Array.isArray(i.spaces)?i.spaces:[],l=Array.isArray(i.markers)?i.markers:[],h=r.map(t=>"string"==typeof t?.id?t.id:"").filter(Boolean),c=new Set(h),d=new Map;for(const t of h){const e=yn("space",t);e.layers>0&&vn("space",e.root)&&wn(d,e.root,t)}const p=new Map,u=new Map,_=new Map,m=new Map;for(const t of r){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const s=new Map;for(const i of Array.isArray(t.rooms)?t.rooms:[]){const t="string"==typeof i?.id?i.id:"";if(!t)continue;const o=yn("room",t);o.layers>0&&vn("room",o.root)&&wn(s,o.root,t),u.has(t)||u.set(t,e),_.has(t)||_.set(t,String(i.name||""));const a="string"==typeof i.area?i.area:"";if(a){const s=m.get(a)||[];s.push({spaceId:e,roomId:t}),m.set(a,s)}}p.set(e,s)}const g=new Set(u.keys()),f=new Map,b=new Map;for(const t of l)"string"==typeof t?.id&&t.id&&(!0===t.removed?b.set(t.id,t):f.set(t.id,t));const v={spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0,positionsUnresolved:0,nestedRefsUnresolved:0,deadSpaceIds:[],orphanRoomLabelsRemoved:0,orphanDevicePositionsRemoved:0,orphanGroupPositionsRemoved:0,liveMissingPositionsRemoved:0,removedPositions:[],liveMissingPositions:[],unverifiedPositions:[]},y=new Set,w=t=>c.has(t)?null:(()=>{const e=yn("space",t).root;if(!vn("space",e))return null;const s=d.get(e)||[];return 1===s.length?s[0]:null})(),$=(t,e)=>{const s=yn("room",t).root;if(!vn("room",s))return null;const i=p.get(e)?.get(s)||[];return 1===i.length?i[0]:null},k=t=>{const e=s.effectiveAreaByMarker?.[t]||"",i=e&&m.get(e)||[];return 1===i.length?i[0]:null},x=(t,e,s)=>{if("string"==typeof t.room_id&&t.room_id&&!g.has(t.room_id)){const i=e?$(t.room_id,e):null;i?(t.room_id=i,v.roomRefsRemapped++):s?(t.room_id=s.roomId,v.roomRefsRemapped++):!0!==t.removed&&delete t.room_id}const i=t.vacuum?.segment_map;if(i&&"object"==typeof i&&!Array.isArray(i))for(const t of Object.keys(i)){const s=i[t];if("string"!=typeof s||!s||g.has(s))continue;const o=e?$(s,e):null;o?(i[t]=o,v.roomRefsRemapped++):v.nestedRefsUnresolved++}};for(const t of l){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const s="string"==typeof t.space?t.space:"",i=s&&!c.has(s),a=o[e],n="string"==typeof a?.s?a.s:"",r=n&&!c.has(n),l=!0===t.removed;let h=s&&c.has(s)?s:null,d=null,p=!1;if(i){const i=w(s);i?(t.space=i,h=i,p=!0,v.spaceRefsRemapped++):l||"virtual"===t.binding?l||(delete t.space,h=null,v.markersDetached++):(d=k(e),d?(t.space=d.spaceId,h=d.spaceId,v.spaceRefsRemapped++):(delete t.space,h=null,v.markersDetached++))}l&&!p||x(t,h,d),r&&p&&n===s&&h&&(o[e]={...a,s:h},v.positionsRemapped++,y.add(e))}for(const t of Object.keys(o)){if(y.has(t))continue;const e=o[t],s="string"==typeof e?.s?e.s:"";if(!s||c.has(s))continue;const i=w(s);if(i){if(t.startsWith("rl_")){const s=t.slice(3),a=$(s,i);if(a){const s=`rl_${a}`;bn(o,s)||(o[s]={...e,s:i}),delete o[t],v.roomRefsRemapped++,v.positionsRemapped++;continue}}o[t]={...e,s:i},v.positionsRemapped++}}const M=s.ownerRoster,C=!0===M?.authoritative,S=new Set(M?.deviceIds||[]),P=new Set(M?.entityIds||[]),I=new Set(Array.isArray(i.settings?.known_devices)?i.settings.known_devices.filter(t=>"string"==typeof t):[]),D=(t,e="")=>{const s=String(M?.names?.[t]||e||"").trim();return s&&s!==t?s:""},L=(t,e,s,i="",o)=>({id:t,spaceId:e,kind:s,name:D(t,i),...o?{reason:o}:{}}),T=t=>{"room_label"===t?v.orphanRoomLabelsRemoved++:"group"===t?v.orphanGroupPositionsRemoved++:v.orphanDevicePositionsRemoved++},R=new Set;for(const[t,e]of Object.entries(o)){const i="string"==typeof e?.s?e.s:"";if(!i||c.has(i))continue;let a,n;const r=f.get(t),l=b.get(t);if(r)a=L(t,i,"device",String(r.name||"")),n="live";else if(l)a=L(t,i,"device",String(l.name||"")),n="absent";else if(t.startsWith("rl_")){const e=t.slice(3);a=L(t,i,"room_label",_.get(e)||""),n=g.has(e)?"live":"absent"}else if(t.startsWith("lg_")){const e=t.slice(3);a=L(t,i,"group"),n=P.has(e)?"live":C?"absent":"unverified","unverified"===n&&(a.reason="registry_unavailable")}else S.has(t)?(a=L(t,i,"device"),n="live"):I.has(t)?(a=L(t,i,"device"),n=C?"absent":"unverified","unverified"===n&&(a.reason="registry_unavailable")):(a=L(t,i,"unknown","","unknown_owner"),n="unverified");if("absent"!==n){if("live"===n){if(v.liveMissingPositions.push(a),!0===s.removeLiveMissingPositions){delete o[t],v.liveMissingPositionsRemoved++,T(a.kind),v.removedPositions.push(a);continue}}else v.unverifiedPositions.push(a);v.positionsUnresolved++,R.add(i)}else delete o[t],T(a.kind),v.removedPositions.push(a)}return v.deadSpaceIds=[...R].sort((t,e)=>t.localeCompare(e)),{config:i,layout:o,report:v,changed:JSON.stringify(i)!==a||JSON.stringify(o)!==n}}(t,e,s),n=a.config,r=lt(n,a.layout);Q(n),ht(a.layout);const l=JSON.stringify(t||{}),h=JSON.stringify(e||{}),c=Number.isInteger(Number(n.model_version))?Number(n.model_version):0,d=(t=>{let e=0,s=0,i=0;for(const s of t.markers||[]){if("ripple"===s.display&&(s.display="icon_ripple",e++),Array.isArray(s.controls)){const t="string"==typeof s.binding&&s.binding.startsWith("entity:")?s.binding.slice(7):"",i=t?s.controls.filter(e=>e!==t):s.controls;JSON.stringify(i)!==JSON.stringify(s.controls)&&(s.controls=i.length?i:null,e++)}const t=s.vacuum;t&&sr(t,"trail")&&(["never","cleaning","always"].includes(t.trail_mode)||(t.trail_mode=!1===t.trail?"never":"cleaning"),delete t.trail,e++)}for(const o of t.spaces||[]){const t=o.settings;"glow"===t?.fill_mode&&("boolean"!=typeof t.glow_enabled&&(t.glow_enabled=!0),t.fill_mode="none",e++,s++);for(const t of o.rooms||[]){const s=t.settings;"glow"===s?.fill_mode&&("boolean"!=typeof s.glow&&(s.glow=!0),delete s.fill_mode,e++,i++)}if(sr(o,"segments")&&(delete o.segments,e++),sr(o,"plan_scale")){const t=Number(o.plan_scale);Number.isFinite(t)&&t>=gt&&t<=ft&&(sr(o,"plan_scale_x")||(o.plan_scale_x=t),sr(o,"plan_scale_y")||(o.plan_scale_y=t),delete o.plan_scale,e++)}const a=Number(o.cell_cm);sr(o,"cell_cm")&&(!Number.isFinite(a)||a<.1||a>1e3)&&(o.cell_cm=Number.isFinite(a)&&a>0?ir(a,.1,1e3):5,e++);const n=Number(o.cell_cm),r=Number.isFinite(n)&&n>0?n:5;for(const t of o.wall_columns||[])if("circle"===t.shape)sr(t,"angle")&&(delete t.angle,e++);else if("square"===t.shape&&sr(t,"angle")){const s=((Number(t.angle)||0)%90+90)%90;t.angle!==s&&(t.angle=s,e++)}for(const t of o.decor||[]){if(sr(t,"width")){const s=Number(t.width);(sr(t,"width_cm")||Number.isFinite(s))&&(sr(t,"width_cm")||(t.width_cm=Number(ir(s/_t*r,.1,100).toFixed(6))),delete t.width,e++)}if("rect"!==t?.kind&&"ellipse"!==t?.kind||!0!==t.fill||(sr(t,"fill_color")||(t.fill_color=t.color||"#607d8b",e++),sr(t,"fill_opacity")||(t.fill_opacity=.25,e++)),"text"!==t?.kind)continue;void 0===t.size_cm?(t.size_cm=Number(ir(bt*vt(t)/_t*r,.1,2e3).toFixed(6)),delete t.scale,delete t.size,e++):(sr(t,"scale")||sr(t,"size"))&&(delete t.scale,delete t.size,e++);let s=String(t.text??"");const i=[...s.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!yt(t[1]));if(!(sr(t,"entity")||sr(t,"attr")||sr(t,"unit")))continue;const o=String(t.unit??"").trim(),a="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,n=i||o?"":wt(t.entity,a);if(i||n){if(n){const e=s.indexOf("{}");s=e>=0?s.slice(0,e)+n+s.slice(e+2):`${s}${s?" ":""}${n}`,t.text=s}delete t.entity,delete t.attr,delete t.unit,e++}}}return{total:e,glowSpaces:s,glowRooms:i}})(n);let p=d.total,u=0,_=0,m=0;if(c<10)for(const t of Array.isArray(n.spaces)?n.spaces:[]){const e=Yn(t);_+=e.drafts,m+=e.segments}const g=(f=n.spaces||[],JSON.parse(JSON.stringify(f)));var f;const b=Ua(n.spaces||[],a.layout);let v=0,y=0,w=0,$="";const k=b.spaces.map(t=>{const e=ct(t);v+=e.report.wallsStraightened,y+=e.report.wallsStraightenSkipped;const s=Number(t?.cell_cm)>0?Number(t.cell_cm):5,i=e.report.maxStraightenShift/E*s;return i>w&&(w=i,$=String(t?.id||"")),e.space}),x=v?Ua(k,b.layout):{...b,spaces:k};n.spaces=x.spaces;const M=v?{...b.report,moved:b.report.moved+x.report.moved,coordsCanonicalized:b.report.coordsCanonicalized+x.report.coordsCanonicalized,maxShift:Math.max(b.report.maxShift,x.report.maxShift),maxShiftCm:Math.max(b.report.maxShiftCm,x.report.maxShiftCm),maxSpace:x.report.maxShiftCm>b.report.maxShiftCm?x.report.maxSpace:b.report.maxSpace,rotated:b.report.rotated+x.report.rotated}:{...b.report};let C=0,S=0,P=0,I=0,D=0,L=0,T=0;for(let t=0;t<n.spaces.length;t++){const e=g[t],s=n.spaces[t],i=JSON.stringify({zero:(e.wall_segments||[]).filter(t=>0===Number(t.cm)),walls:e.walls||[]}),a=or(e),r=or(s);if(!a||!r)continue;const l=rr(a.rooms),h=rr(r.rooms),c=.02*_t,d=(e.wall_segments||[]).filter(t=>0===Number(t.cm)).map(t=>({...t,key:tt(t.a,t.b,E),cm:0})),p=new Set(d.map(t=>t.key)),u=dt(e,a.rooms,pt,c);S+=u.length;for(const t of u){const e=[t[0]/pt,t[1]/pt],s=[t[2]/pt,t[3]/pt],i=tt(e,s,E);p.has(i)||(p.add(i),d.push({key:i,a:e,b:s,cm:0}))}const _=d.length,m=ut(d,l,h,E,pt),f=(t,e,s)=>{const i=s[0]-e[0],o=s[1]-e[1],a=i*i+o*o;if(!(a>0))return Math.hypot(t[0]-e[0],t[1]-e[1]);const n=Math.max(0,Math.min(1,((t[0]-e[0])*i+(t[1]-e[1])*o)/a));return Math.hypot(t[0]-(e[0]+i*n),t[1]-(e[1]+o*n))},b=m.filter(t=>{if(!Array.isArray(t.a)||!Array.isArray(t.b))return!1;const e=t.a.map(t=>t*pt),s=t.b.map(t=>t*pt);return h.some(([t,i])=>f(e,t,i)<=4*c&&f(s,t,i)<=4*c)});P+=Math.max(0,_-b.length);const v=(s.wall_segments||[]).filter(t=>Number(t.cm)>0);s.wall_segments=[...v,...b.map(({key:t,...e})=>e)];const y=b.map(t=>[t.a[0]*pt,t.a[1]*pt,t.b[0]*pt,t.b[1]*pt]),w=Array.isArray(e.walls)?e.walls.length:0;let $=ut(e.walls,l,h,E,pt);$=nr(r.rooms,$,y,E,Number(s.cell_cm)>0?Number(s.cell_cm):5,_t,pt),$=V(r.rooms,$,y,E,Number(s.cell_cm)>0?Number(s.cell_cm):5,_t,pt),$=mt($,s.rooms||[],E,1,y.map(t=>[t[0]/pt,t[1]/pt,t[2]/pt,t[3]/pt])),C+=Math.max(0,w-$.length),$.length?s.walls=$:delete s.walls;const k=Qa(s.partitions||[],{pitch:E,geometry:en(s)});k.merged&&(I+=k.merged,s.partitions=k.partitions,tn(s.openings,s.partitions,k.openingMoves,{coordScale:pt,cellCm:Number(s.cell_cm)>0?Number(s.cell_cm):5,gridPitch:_t}));const x=or(s);if(x){const t=o(s,x,s.walls||[],y,{pitch:E,cellCm:Number(s.cell_cm)>0?Number(s.cell_cm):5,gridPitch:_t,coordScale:pt});t.partitionsReconciled&&(D+=t.partitionsReconciled,L+=t.openingsRehosted,t.partitions.length?s.partitions=t.partitions:delete s.partitions,t.openings.length?s.openings=t.openings:delete s.openings,t.walls.length?s.walls=t.walls:delete s.walls)}JSON.stringify({zero:(s.wall_segments||[]).filter(t=>0===Number(t.cm)),walls:s.walls||[]})!==i&&T++}if(c<=10){const t=function(t){const e=Qn(t);return er(t,e.config),{...e,config:t}}(n);u+=t.migratedSegments,_+=t.migratedDrafts,m+=t.migratedDraftSegments}const R=Q(n),z=ht(x.layout),F=JSON.stringify(R)!==l||JSON.stringify(z)!==h;c<10&&F&&(R.model_version=10);const N=JSON.stringify(R)!==l||JSON.stringify(z)!==h,A=Number.isInteger(Number(R.model_version))?Number(R.model_version):c,O=N?M:{...M,moved:0,coordsCanonicalized:0,maxShift:0,maxShiftCm:0,maxSpace:"",rotated:0},B=N?a.report:{...a.report,spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0,orphanRoomLabelsRemoved:0,orphanDevicePositionsRemoved:0,orphanGroupPositionsRemoved:0,liveMissingPositionsRemoved:0};return{config:R,layout:z,report:{...O,modelFrom:c,modelTo:A,migrated:N?p:0,glowSpacesMigrated:N?d.glowSpaces:0,glowRoomsMigrated:N?d.glowRooms:0,canonicalized:N?T:0,wallSegmentsMigrated:N?u:0,roomDraftsMigrated:N?_:0,roomDraftSegmentsMigrated:N?m:0,legacyZeroWallsMigrated:N?S:0,wallsMerged:N?C:0,spansMerged:N?P:0,partitionsMerged:N?I:0,partitionsReconciled:N?D:0,openingsRehosted:N?L:0,wallsStraightened:N?v:0,wallsStraightenSkipped:y,maxStraightenShiftCm:N?w:0,maxStraightenSpace:N?$:"",latticeCoordinatesCanonicalized:N?r.canonicalized:0,latticeCoordinatesFar:N?r.far:0,latticeMaxShift:N?r.maxShift:0,latticeMaxShiftCm:N?r.maxShiftCm:0,latticeSpaces:N?r.spaces:[],...B},changed:N}}async function hr(t,e,s){t._saveConfigDebounced.pending()&&t._saveConfigDebounced.flush(),await t._writeChain;const i=await t.hass.callWS({type:"houseplan/plan/optimize",config:e,layout:s,expected_config_rev:t._cfgRev,expected_layout_rev:t._layoutRev});t._adoption.acceptPairWrite(e,s,i),t._geometryHistory.clear(),t._cancelDeviceDrag(),t._devicePositionHistory.clear(),t._canOptimizeUndo=!0===i.can_undo,t._undoKind=!0===i.can_undo?"optimize":null,t._dirtyPos.clear(),t._sentPos.clear(),t._cfgEpoch++,t._modelCache=null,t._frame=null,t._regSignature="",t._maybeRebuildDevices(),t._cacheSnapshot(),t.requestUpdate()}const cr=Object.freeze({spaces:50,partitions:2e3,openings:500,decor:1e3,columns:500});class dr extends Error{constructor(t){super(t),this.code=t,this.name="SpaceCopyError"}}const pr=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),ur=t=>void 0===t?t:JSON.parse(JSON.stringify(t)),_r=t=>null===t||"object"!=typeof t||Array.isArray(t)?null:t;function mr(t,e=!1){if(void 0===t&&!e)return[];if(!Array.isArray(t))throw new dr("source_invalid");return t.map(t=>{const e=_r(t);if(!e||"string"!=typeof e.id||!e.id)throw new dr("source_invalid");return e})}const gr=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(t));function fr(t,e,s){const i=String(t??"").trim()||s,o=new Set(e.map(t=>{const e=_r(t);return String(e?.title??"").trim()}));let a=2;for(;o.has(`${i} (${a})`);)a++;return`${i} (${a})`}const br=["settings","zero_wall_style","cell_cm","view_box","plan_url","plan_aspect","plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"];const vr={source_missing:"space.copy_error_source_missing",source_invalid:"space.copy_error_source_invalid",spaces_limit:"space.copy_error_spaces_limit",partitions_limit:"space.copy_error_partitions_limit",openings_limit:"space.copy_error_openings_limit",decor_limit:"space.copy_error_decor_limit",columns_limit:"space.copy_error_columns_limit",opening_host_missing:"space.copy_error_opening_host",opening_host_unknown:"space.copy_error_opening_host",geometry_unsafe:"space.copy_error_geometry"};let yr=0;function wr(t,e,s){const i=t._spaceDialog;return!(!i?.copy||i.copy.token!==e)&&(t._spaceDialog={...i,busy:s,copy:{...i.copy,busy:s}},!0)}function $r(t){t._cfgEpoch++,t._modelCache=null,t._frame=null,t._regSignature="",t._maybeRebuildDevices(),t.requestUpdate()}async function kr(t,e){const s=t._spaceDialog;if(!s?.copy||"edit"!==s.mode||s.busy||s.copy.busy||!s.copy.title.trim()||!s.spaceId||!t._serverCfg)return;const i=++yr,o=s.spaceId,a=s.copy.title.trim();t._spaceDialog={...s,busy:!0,copy:{...s.copy,title:a,busy:!0,token:i}};let n=!1;try{if(t._saveConfigDebounced.pending()&&t._saveConfigDebounced.flush(),await t._writeChain,!wr(t,i,!0)||!t._serverCfg)return;const s=t._cfgRev,r=t._layoutRev,l=xt(t._serverCfg),h=xt(t._layout);let c;try{c=(e.optimize??lr)(t._serverCfg,t._layout,e.optimizeReferenceContext())}catch(s){return wr(t,i,!1),void e.showWallModelMigrationBlocked(s)}if(c.changed){const d=t._checkOptimizeGeometry(c.config);if(e.reportPreflightFailure(d,c.config),!d.ok)return wr(t,i,!1),void t._showToast(t._t("space.copy_error_optimize_geometry"));const p=await t._confirmDanger({key:`copy-space:${o}`,kind:"warning",title:t._t("space.copy_optimize_title"),message:t._t("space.copy_optimize_body",{name:a}),objectName:a,confirmLabel:t._t("space.copy_optimize_confirm"),cancelLabel:t._t("btn.cancel"),icon:"mdi:broom"});if(!wr(t,i,p))return;if(!p)return;if(t._cfgRev!==s||t._layoutRev!==r||!t._serverCfg||xt(t._serverCfg)!==l||xt(t._layout)!==h)return wr(t,i,!1),void t._showToast(t._t("space.copy_error_changed"));e.clearGeometryGesture(),await hr(t,c.config,c.layout),n=!0}if(!wr(t,i,!0)||!t._serverCfg)return;const d=t._serverCfg,p=function(t,e,s,i){const o=t.spaces;if(!s.trim())throw new dr("source_invalid");if(o.length>=cr.spaces)throw new dr("spaces_limit");const a=o.findIndex(t=>t.id===e);if(a<0)throw new dr("source_missing");const n=o[a];if(!Array.isArray(n.view_box))throw new dr("source_invalid");const r=mr(n.wall_segments,!0),l=mr(n.partitions),h=mr(n.openings),c=mr(n.decor),d=mr(n.wall_columns);if(r.length+l.length>cr.partitions)throw new dr("partitions_limit");if(h.length>cr.openings)throw new dr("openings_limit");if(c.length>cr.decor)throw new dr("decor_limit");if(d.length>cr.columns)throw new dr("columns_limit");let p=0;const u=t=>`${t}${i}${(p++).toString(36)}`,_=new Map,m=new Map,g=[];for(const t of r){if(_.has(t.id)||!gr(t.a)||!gr(t.b)||"number"!=typeof t.cm||!Number.isFinite(t.cm))throw new dr("source_invalid");const e=u("cw");_.set(t.id,e),g.push({id:e,a:ur(t.a),b:ur(t.b),cm:t.cm})}for(const t of l){if(m.has(t.id)||!gr(t.a)||!gr(t.b)||"number"!=typeof t.cm||!Number.isFinite(t.cm))throw new dr("source_invalid");const e=u("cp");m.set(t.id,e),g.push({id:e,a:ur(t.a),b:ur(t.b),cm:t.cm})}const f=h.map(t=>{const e=_r(t.host);if(!e||"string"!=typeof e.id||"string"!=typeof e.kind)throw new dr("opening_host_missing");const s="wall"===e.kind?_.get(e.id):"partition"===e.kind?m.get(e.id):void 0;if(!s)throw new dr("opening_host_unknown");const i={...ur(t),id:u("co"),host:{...ur(e),kind:"partition",id:s}};return delete i.contact,delete i.lock,i}),b=c.map(t=>({...ur(t),id:u("cd")})),v=d.map(t=>({...ur(t),id:u("cc")})),y=`s${i}`;if(o.some(t=>t.id===y))throw new dr("source_invalid");const w={id:y,title:s.trim(),rooms:[],wall_segments:[],view_box:ur(n.view_box)};for(const t of br)"view_box"!==t&&pr(n,t)&&(w[t]=ur(n[t]));g.length&&(w.partitions=g),f.length&&(w.openings=f),b.length&&(w.decor=b),v.length&&(w.wall_columns=v);const $=ur(t);return $.spaces.splice(a+1,0,w),{config:$,space:w,sourceIndex:a}}(d,o,a,e.newSeed?.()??function(t=Date.now(),e=Math.random()){const s=Math.floor(16777216*Math.max(0,Math.min(.999999999,e))).toString(36).padStart(5,"0");return`${Math.max(0,Math.floor(t)).toString(36)}${s}`}());let u=!1;try{u=t._checkSpacePhysicalGeometry(p.config,p.space.id).ok}catch{u=!1}if(!u||t._junctionLimitViolations(p.config,p.space.id).length)throw new dr("geometry_unsafe");const _=t._adoption.beginOptimistic(d,p.config);t._adoption.stageLocalConfig(p.config),$r(t);try{await e.saveConfigNow(_)}catch(e){throw t._rollbackOptimistic(_)&&$r(t),"conflict"!==e?.code&&await t._reloadConfigOnly(!0),e}t._canOptimizeUndo=!1,t._undoKind=null,e.clearGeometryGesture(),t._selId=null,t._physicalSel=null,t._spaceDialog=null,t._commitSpace(p.space.id,!0),e.setMode("plan"),t._tool="draw",t._path=[],t._cursorPt=null,t._activeWallChainId=null,t._activeWallChainPartitionIds=[],t._primeDrawWallField(),t._saveNav(),t.requestUpdate(),t._showToast(t._t("toast.space_copied",{name:a}))}catch(e){"conflict"===e?.code&&await Promise.all([t._reloadConfigOnly(!0),t._reloadLayoutOnly()]),wr(t,i,!1),function(t,e){if(e instanceof dr)return void t._showToast(t._t(vr[e.code]));const s=e?.code;"wall_model_client_outdated"!==s?t._showToast(t._t("toast.error",{err:t._errText(e)})):t._showToast(t._t("toast.wall_model_client_outdated"))}(t,e),n&&t.requestUpdate()}}function xr(){if(this.host._spaceDialog.copy)return function(t,e){const s=t._spaceDialog.copy,i=()=>function(t){const e=t._spaceDialog;!e?.copy||e.busy||e.copy.busy||(t._spaceDialog={...e,copy:void 0})}(t);return p`<hp-dialog .hass=${t.hass} data-kind="space"
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
.title=${t._t("space.copy_title")}
|
||
icon="mdi:content-copy" @hp-close=${s}>
|
||
<div class="body">
|
||
<label for="space-copy-name">${t._t("space.copy_name")}</label>
|
||
<input id="space-copy-name" class="namein" type="text" autofocus
|
||
.value=${i.title}
|
||
@focus=${t=>t.currentTarget.select()}
|
||
@input=${e=>{const i=t._spaceDialog;i?.copy&&!i.busy&&(t._spaceDialog={...i,copy:{...i.copy,title:e.target.value}})}}
|
||
@keydown=${t=>{"Enter"===t.key&&i.title.trim()&&!i.busy&&(t.preventDefault(),e())}} />
|
||
</div>
|
||
<div class="row dialog-action-footer" slot="footer">
|
||
<span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel"
|
||
@click=${s} ?disabled=${i.busy}>
|
||
${t._t("btn.cancel")}
|
||
</button>
|
||
<button class="btn on" data-hp="dialog-confirm"
|
||
@click=${e} ?disabled=${!i.title.trim()||i.busy}>
|
||
<ha-icon icon="mdi:content-copy"></ha-icon>${i.busy?"…":t._t("space.copy_create")}
|
||
</button>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}(this.host,()=>{this._saveSpaceCopy()});const t=Ao({host:this.host,idPrefix:"space",help:this._help.bind(this),rangeInput:(t,e,i,s,o,a,n)=>this._rangeInput(t,e,i,s,o,a,n),pickPlanFile:t=>this._pickPlanFile(t),toggleServerPlans:()=>this._toggleServerPlans(),renderServerPlans:t=>this._renderServerPlans(t),save:()=>this._saveSpaceDialog(),skipImport:()=>this._skipImport(),deleteSpace:()=>this._deleteSpace(),copySpace:()=>function(t){const e=t._spaceDialog;if(!e||"edit"!==e.mode||e.busy||!t._serverCfg)return;const i=t._serverCfg.spaces.find(t=>t?.id===e.spaceId);i&&(t._spaceDialog={...e,copy:{title:yr(i.title,t._serverCfg.spaces,t._t("space.copy_fallback")),busy:!1,token:0}})}(this.host)});return p`<hp-dialog .hass=${this.host.hass} data-kind="space" form-shell wide
|
||
.title=${t.title} .badge=${t.badge} icon="mdi:floor-plan" @hp-close=${t.requestClose}>
|
||
${t.body}${t.footer}
|
||
</hp-dialog>`}const Pr=new Set(["busy","glowRadiusInput","northDegInput"]);function Ir(t){return m(t,Pr)}function Dr(t){const e=[],i=Mt(t.glowRadiusInput);null!==i&&i>0||e.push({field:"gs-glow-radius",message:"gs.error_glow_radius"});const s=t.northDegInput.trim(),o=""===s?null:Mt(s);return""===s||null!==o&&Number.isInteger(o)&&o>=0&&o<=359||e.push({field:"gs-north",message:"gs.error_north"}),e}function Lr(){wo(this.host);const t=this.host,e=t._settingsDialog,i=t._t.bind(t),s=l(t.hass,t._config?.language),o=(t,e)=>Ho(s,t,e),a=e=>{t._settingsDialog={...t._settingsDialog,...e}},n=Dr(e),r=t=>n.find(e=>e.field===t),h=function(t,e){return g(t,"settings",Ir(e))}(t,e),c=h&&0===n.length&&!e.busy,u=()=>{!function(t){_(t,"settings")}(t),t._settingsDialog=null},m=async i=>{if(!h||e.busy)return void u();const s=i.currentTarget;await t._confirmDanger({key:"discard-settings-dialog",kind:"warning",title:o("dialog.discard_title"),message:o("dialog.discard_message"),confirmLabel:o("dialog.discard_confirm"),cancelLabel:o("dialog.discard_keep"),icon:"mdi:content-save-off-outline",confirmIcon:"mdi:content-save-off-outline"})?u():s?.rejectClose?.()},f=(s,a)=>{const n=e.colors[s],r=i(a);return Wo({label:r,hex:n.c,opacity:n.a,opacityLabel:o("gs.opacity_of",{name:r}),onOpacity:t=>this._setFillColor(s,{c:n.c,a:t}),picker:p`<hp-color-opacity .label=${r} hide-label flat-swatch cover-swatch
|
||
.opacityLabel=${i("space.opacity")}
|
||
.pickerLabels=${t._colorPickerLabels}
|
||
.color=${n.c} .opacity=${n.a} .showOpacity=${!0}
|
||
@hp-color-opacity-change=${t=>{this._setFillColor(s,{c:t.detail.color,a:t.detail.opacity})}}></hp-color-opacity>`})},b=r("gs-glow-radius"),v=r("gs-north"),y=ia(s,"help")&&ia(s,"help_aria")?p`<hp-help data-help-key="topology.help" .text=${sa(s,"help")} .ariaLabel=${sa(s,"help_aria")}></hp-help>`:d;return p`<hp-dialog .hass=${t.hass} data-kind="settings" form-shell wide
|
||
.title=${i("gs.title")} icon="mdi:cog-outline" @hp-close=${m}>
|
||
<div class="body hpf-form">
|
||
${Co({id:"display",title:i("gs.card_display"),body:p`
|
||
${Io({id:"gs-room-tooltip",icon:"mdi:tooltip-text-outline",title:_a(s,"gs.show_room_tooltip"),caption:o("gs.show_room_tooltip_hint"),checked:e.showRoomTooltip,onChange:t=>a({showRoomTooltip:t})})}
|
||
${Io({id:"gs-radar-live",icon:"mdi:radar",title:i("gs.radar_show_live"),caption:o("gs.radar_show_live_hint"),checked:e.radarShowLive,onChange:t=>a({radarShowLive:t})})}`})}
|
||
${Co({id:"zigbee",title:i("gs.card_zigbee"),help:y,body:p`<hp-zigbee-topology-settings embedded .hass=${t.hass} .value=${e.zigbeeTopology}
|
||
========
|
||
</hp-dialog>`}(this.host,()=>{this._saveSpaceCopy()});const t=No({host:this.host,idPrefix:"space",help:this._help.bind(this),rangeInput:(t,e,s,i,o,a,n)=>this._rangeInput(t,e,s,i,o,a,n),pickPlanFile:t=>this._pickPlanFile(t),toggleServerPlans:()=>this._toggleServerPlans(),renderServerPlans:t=>this._renderServerPlans(t),save:()=>this._saveSpaceDialog(),skipImport:()=>this._skipImport(),deleteSpace:()=>this._deleteSpace(),copySpace:()=>function(t){const e=t._spaceDialog;if(!e||"edit"!==e.mode||e.busy||!t._serverCfg)return;const s=t._serverCfg.spaces.find(t=>t?.id===e.spaceId);s&&(t._spaceDialog={...e,copy:{title:fr(s.title,t._serverCfg.spaces,t._t("space.copy_fallback")),busy:!1,token:0}})}(this.host)});return p`<hp-dialog .hass=${this.host.hass} data-kind="space" form-shell wide
|
||
.title=${t.title} .badge=${t.badge} icon="mdi:floor-plan" @hp-close=${t.requestClose}>
|
||
${t.body}${t.footer}
|
||
</hp-dialog>`}const Mr=new Set(["busy","glowRadiusInput","northDegInput"]);function Cr(t){return m(t,Mr)}function Sr(t){const e=[],s=Mt(t.glowRadiusInput);null!==s&&s>0||e.push({field:"gs-glow-radius",message:"gs.error_glow_radius"});const i=t.northDegInput.trim(),o=""===i?null:Mt(i);return""===i||null!==o&&Number.isInteger(o)&&o>=0&&o<=359||e.push({field:"gs-north",message:"gs.error_north"}),e}function Pr(){vo(this.host);const t=this.host,e=t._settingsDialog,s=t._t.bind(t),i=l(t.hass,t._config?.language),o=(t,e)=>Oo(i,t,e),a=e=>{t._settingsDialog={...t._settingsDialog,...e}},n=Sr(e),r=t=>n.find(e=>e.field===t),h=function(t,e){return g(t,"settings",Cr(e))}(t,e),c=h&&0===n.length&&!e.busy,u=()=>{!function(t){_(t,"settings")}(t),t._settingsDialog=null},m=async s=>{if(!h||e.busy)return void u();const i=s.currentTarget;await t._confirmDanger({key:"discard-settings-dialog",kind:"warning",title:o("dialog.discard_title"),message:o("dialog.discard_message"),confirmLabel:o("dialog.discard_confirm"),cancelLabel:o("dialog.discard_keep"),icon:"mdi:content-save-off-outline",confirmIcon:"mdi:content-save-off-outline"})?u():i?.rejectClose?.()},f=(i,a)=>{const n=e.colors[i],r=s(a);return Bo({label:r,hex:n.c,opacity:n.a,opacityLabel:o("gs.opacity_of",{name:r}),onOpacity:t=>this._setFillColor(i,{c:n.c,a:t}),picker:p`<hp-color-opacity .label=${r} hide-label flat-swatch cover-swatch
|
||
.opacityLabel=${s("space.opacity")}
|
||
.pickerLabels=${t._colorPickerLabels}
|
||
.color=${n.c} .opacity=${n.a} .showOpacity=${!0}
|
||
@hp-color-opacity-change=${t=>{this._setFillColor(i,{c:t.detail.color,a:t.detail.opacity})}}></hp-color-opacity>`})},b=r("gs-glow-radius"),v=r("gs-north"),y=ea(i,"help")&&ea(i,"help_aria")?p`<hp-help data-help-key="topology.help" .text=${sa(i,"help")} .ariaLabel=${sa(i,"help_aria")}></hp-help>`:d;return p`<hp-dialog .hass=${t.hass} data-kind="settings" form-shell wide
|
||
.title=${s("gs.title")} icon="mdi:cog-outline" @hp-close=${m}>
|
||
<div class="body hpf-form">
|
||
${xo({id:"display",title:s("gs.card_display"),body:p`
|
||
${So({id:"gs-room-tooltip",icon:"mdi:tooltip-text-outline",title:da(i,"gs.show_room_tooltip"),caption:o("gs.show_room_tooltip_hint"),checked:e.showRoomTooltip,onChange:t=>a({showRoomTooltip:t})})}
|
||
${So({id:"gs-radar-live",icon:"mdi:radar",title:s("gs.radar_show_live"),caption:o("gs.radar_show_live_hint"),checked:e.radarShowLive,onChange:t=>a({radarShowLive:t})})}`})}
|
||
${xo({id:"zigbee",title:s("gs.card_zigbee"),help:y,body:p`<hp-zigbee-topology-settings embedded .hass=${t.hass} .value=${e.zigbeeTopology}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
.savedEnabled=${Ct(t._settings).enabled} .devices=${t._devices} .registry=${t._haRegistry}
|
||
@hp-topology-settings-change=${t=>a({zigbeeTopology:t.detail})}></hp-zigbee-topology-settings>`})}
|
||
${Co({id:"fills",title:i("gs.card_fills"),help:this._help("gs.card_fills.help"),body:p`
|
||
${To({title:i("gs.light_group")})}
|
||
${Oo([f("light_on","gs.light_on"),f("light_off","gs.light_off"),f("light_none","gs.light_none")])}
|
||
${To({title:i("gs.temp_group")})}
|
||
${Oo([f("temp_cold","gs.temp_cold"),f("temp_ok","gs.temp_ok"),f("temp_hot","gs.temp_hot")])}
|
||
${To({title:i("gs.lqi_group")})}
|
||
${Oo([f("lqi_low","gs.lqi_low"),f("lqi_high","gs.lqi_high")])}`})}
|
||
${Co({id:"glow",title:i("gs.glow_group"),body:p`
|
||
${Oo([f("glow_base","gs.glow_base"),f("glow_light","gs.glow_light")])}
|
||
${So({label:i("gs.glow_radius"),htmlFor:"gs-glow-radius",help:this._help("gs.glow_radius.help"),error:b?o(b.message):void 0,control:Ro({id:"gs-glow-radius",value:e.glowRadiusInput,min:.5,step:.5,invalid:!!b,unit:t._imperial?i("gs.unit_ft"):i("gs.unit_m"),onInput:t=>{const e=Mt(t);a({glowRadiusInput:t,...null!=e&&e>0?{glowRadius:e}:{}})}})})}`})}
|
||
${Co({id:"plan",title:i("gs.card_plan"),body:p`
|
||
${Bo({label:i("gs.wall_fill"),picker:Do({hex:e.colors.wall_fill.c,opacity:e.colors.wall_fill.a,opacityLabel:i("space.opacity"),onOpacity:t=>this._setFillColor("wall_fill",{c:e.colors.wall_fill.c,a:t}),resetLabel:i("btn.reset"),onReset:()=>this._setFillColor("wall_fill",{...Pt.wall_fill}),picker:p`<hp-color-opacity .label=${i("gs.wall_fill")} hide-label flat-swatch
|
||
.opacityLabel=${i("space.opacity")} .pickerLabels=${t._colorPickerLabels}
|
||
.color=${e.colors.wall_fill.c} .opacity=${e.colors.wall_fill.a} .showOpacity=${!0}
|
||
@hp-color-opacity-change=${t=>{this._setFillColor("wall_fill",{c:t.detail.color,a:t.detail.opacity})}}></hp-color-opacity>`})})}
|
||
${So({label:i("gs.bg_mode"),help:this._help("gs.bg_mode.help"),control:Po({name:"gs-bg-mode",value:"daynight"===e.bgMode?"daynight":"static",ariaLabel:i("gs.bg_mode"),options:[{value:"static",label:i("gs.bg_static")},{value:"daynight",label:i("gs.bg_daynight")}],onChange:t=>a({bgMode:"daynight"===t?"daynight":"static"})})})}
|
||
${"static"===e.bgMode?So({label:i("gs.bg_color"),hint:o(e.bgColor?"gs.bg_custom_hint":"gs.bg_theme_hint"),control:Do({hex:e.bgColor||t._stageBgHex(),resetLabel:e.bgColor?i("gs.bg_default"):void 0,onReset:()=>a({bgColor:null}),picker:p`<hp-color-opacity .label=${i("gs.bg_color")} hide-label flat-swatch
|
||
.pickerLabels=${t._colorPickerLabels}
|
||
.color=${e.bgColor||t._stageBgHex()} .opacity=${1} .showOpacity=${!1}
|
||
@hp-color-opacity-change=${t=>a({bgColor:t.detail.color})}></hp-color-opacity>`})}):d}`})}
|
||
${Co({id:"sun",title:i("gs.sun_group"),body:p`
|
||
${St(t.hass)?d:ko({kind:"warning",role:"status",text:i("gs.sun_missing")})}
|
||
<div class="hpf-north">
|
||
<span class="hpf-labelrow"><label for="gs-north">${i("gs.north")}</label>${this._help("gs.north.help")}</span>
|
||
<div class="hpf-inline hpf-wrap">
|
||
${Ro({id:"gs-north",value:e.northDegInput,unit:"°",min:0,max:359,step:1,placeholder:i("gs.north_ph"),invalid:!!v,onInput:t=>{const e=t.trim(),i=""===e?null:Mt(e);a({northDegInput:t,...""===e?{northDeg:null}:null!==i&&Number.isInteger(i)&&i>=0&&i<=359?{northDeg:i}:{}})}})}
|
||
${null!==e.northDeg||e.northDegInput.trim()?xo(i("gs.north_clear"),()=>a({northDeg:null,northDegInput:""})):d}
|
||
</div>
|
||
<span class="hpf-north-n" aria-hidden="true">${i("gs.north_letter")}</span>
|
||
${t._renderCompass()}
|
||
</div>
|
||
${v?p`<p class="hpf-error" role="alert">${o(v.message)}</p>`:d}
|
||
${Io({id:"gs-sun-rays",icon:"mdi:weather-sunny",title:i("gs.sun_rays"),caption:o("gs.sun_rays_hint"),checked:e.sunRays,onChange:t=>a({sunRays:t})})}
|
||
${w=e.sunRayOrigin,$=t=>i(t),k=t=>a({sunRayOrigin:t}),So({label:$("gs.sun_ray_origin"),control:Po({name:"gs-sun-ray-origin",value:w,ariaLabel:$("gs.sun_ray_origin"),options:[{value:"inner",label:$("gs.sun_ray_origin.inner")},{value:"outer",label:$("gs.sun_ray_origin.outer")}],onChange:t=>k("outer"===t?"outer":"inner")})})}`})}
|
||
${Co({id:"data",title:i("gs.card_data"),body:p`
|
||
${t._canEdit?p`
|
||
${To({title:i("gs.backup_group"),help:this._help("gs.backup_group.help")})}
|
||
<div class="hpf-actions">
|
||
<button class="btn" @click=${()=>this._openBackupExport()}>
|
||
<ha-icon icon="mdi:download"></ha-icon>${i("backup.export_open")}
|
||
</button>
|
||
<span class="backupupload">
|
||
<button class="btn" type="button" @click=${t=>t.currentTarget.nextElementSibling?.click()}>
|
||
<ha-icon icon="mdi:upload"></ha-icon>${i("backup.import_open")}
|
||
</button>
|
||
<input type="file" accept="application/json,.json" @change=${t=>this._pickBackupImport(t)} />
|
||
</span>
|
||
${t._canOptimizeUndo&&"import"===t._undoKind?p`
|
||
<button class="btn" @click=${()=>this._undoPlanOptimization()} ?disabled=${t._optimizeUndoBusy}>
|
||
<ha-icon icon="mdi:undo-variant"></ha-icon>${i("backup.undo_import")}
|
||
</button>`:d}
|
||
</div>`:d}
|
||
${To({title:i("gs.grid_group"),help:this._help("gs.grid_group.help")})}
|
||
<div class="hpf-actions">
|
||
<button class="btn" @click=${()=>this.optimizePlans.open()}>
|
||
<ha-icon icon="mdi:broom"></ha-icon>${i("gs.align_all")}
|
||
</button>
|
||
${t._canOptimizeUndo&&"import"!==t._undoKind?p`
|
||
<button class="btn" @click=${()=>this._undoPlanOptimization()} ?disabled=${t._optimizeUndoBusy}>
|
||
<ha-icon icon="mdi:undo-variant"></ha-icon>${i("gs.optimize_undo")}
|
||
</button>`:d}
|
||
</div>`})}
|
||
</div>
|
||
<div class="row dialog-action-footer hpf-footer" slot="footer">
|
||
<div class="dialog-action-group">
|
||
<button class="btn ghost" @click=${()=>a({colors:JSON.parse(JSON.stringify(Pt)),glowRadius:t._imperial?9.8:3,glowRadiusInput:String(t._imperial?9.8:3),bgColor:null,northDeg:null,northDegInput:"",bgMode:"daynight",sunRays:!1,sunRayOrigin:"inner",showRoomTooltip:!0,radarShowLive:!0,zigbeeTopology:{enabled:!1,z2mBaseTopics:[]}})}>${i("gs.reset")}</button>
|
||
</div>
|
||
${Eo(n.length?{action:xo(o("dialog.review_fields",{n:String(n.length)}),()=>{const e=n[0];if(!e)return;const i=t.renderRoot.querySelector(`#${e.field}`);i?.scrollIntoView({block:"center"}),i?.focus()})}:{})}
|
||
<div class="dialog-action-group dialog-action-commit">
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${m}>${i("btn.cancel")}</button>
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>this._saveSettingsDialog()} ?disabled=${!c}
|
||
title=${n[0]?o(n[0].message):""}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${e.busy?"…":i("btn.save")}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`;var w,$,k}function Tr(t){return m({name:t._nameSel,area:t._areaSel,fill:t._roomFill,customFill:t._roomCustomFill,tempMin:t._roomTempMin,tempMax:t._roomTempMax,tempSrc:t._roomTempSrc,humSrc:t._roomHumSrc,nameScale:t._roomNameScale,labelScale:t._roomLabelScale})}function Rr(t){_(t,"room")}function Fr(t,e){const i=t.host,s="temp"===e?i._roomTempSrc:i._roomHumSrc,o=t=>{"temp"===e?i._roomTempSrc=t:i._roomHumSrc=t,i.requestUpdate()},a=i._roomSrcOpen===e,n=i._t("temp"===e?"room.temp_src_label":"room.hum_src_label");return p`${To({title:n})}
|
||
${Po({name:`rsrc-${e}`,value:s?"pick":"avg",ariaLabel:n,options:[{value:"avg",label:i._t("room.src_average")},{value:"pick",label:i._t("room.src_pick")}],onChange:t=>{if("avg"===t)return o(""),void(i._roomSrcOpen=null);i._roomSrcOpen=e,i._roomSrcFilter="",i.requestUpdate()}})}
|
||
${s||a?Mo({id:`room-${e}-source`,open:a,current:s?{label:t._roomSrcLabel(s),sub:s}:null,placeholder:i._t("room.src_ph"),ariaLabel:n,filter:i._roomSrcFilter,filterPlaceholder:i._t("marker.search_ph"),candidates:a?t._roomSrcCandidates():[],selected:s,emptyText:i._t("marker.nothing_found"),onToggle:()=>{i._roomSrcOpen=a?null:e,i._roomSrcFilter="",i.requestUpdate()},onFilter:t=>{i._roomSrcFilter=t,i.requestUpdate()},onPick:t=>{o(t),i._roomSrcOpen=null}}):d}`}function zr(){wo(this.host);const t=this.host,e=t._t.bind(t),i=l(t.hass,t._config?.language),s=(t,e)=>Ho(i,t,e),o=!!t._roomEditId,a=o?null:t._wallFaceBatch,n=a&&a.candidates.length>1?e("room.queue_progress",{current:a.index+1,total:a.candidates.length}):"",r=b(t._curSpaceCfg),h=""===t._roomFill,c=t._roomFill||r.fill,u=t._roomCustomFill||r.customFill,_=It(t._roomTempMin,t._roomTempMax).valid,m=function(t){const e=[];return!t._roomEditId&&t._areaSel||t._nameSel.trim()||e.push({field:"room-name",message:"room.error_name"}),It(t._roomTempMin,t._roomTempMax).valid||e.push({field:"room-temp-min",message:"room.error_temp_range"}),e}(t),f=t=>m.find(e=>e.field===t),v=function(t){return g(t,"room",Tr(t))}(t),y=0===m.length&&_&&(!o||v),w=[...t._freeAreas];if(o&&t._areaSel&&!w.some(e=>e.area_id===t._areaSel)){const e=t.hass.areas[t._areaSel];e&&w.unshift(e)}const $=()=>{Rr(t),this._roomDialogCancel()},k=async e=>{if(!o||!v)return void $();const i=e.currentTarget;await t._confirmDanger({key:"discard-room-dialog",kind:"warning",title:s("dialog.discard_title"),message:s("dialog.discard_message"),objectName:t._nameSel.trim()||void 0,confirmLabel:s("dialog.discard_confirm"),cancelLabel:s("dialog.discard_keep"),icon:"mdi:content-save-off-outline",confirmIcon:"mdi:content-save-off-outline"})?$():i?.rejectClose?.()},x=f("room-name"),M=f("room-temp-min"),C=e=>{t._roomFill=e,"custom"!==e&&(t._roomCustomFill=null),t.requestUpdate()},S=t=>Math.round(100*t),P=t._roomCustomFill?e("room.custom_fill_own"):e("room.custom_fill_space"),I=[["name","room.name_scale",t._roomNameScale,e=>{t._roomNameScale=e}],["label","room.label_scale",t._roomLabelScale,e=>{t._roomLabelScale=e}]];return p`<hp-dialog class="roomdialog" .hass=${t.hass} data-kind="room" form-shell wide
|
||
========
|
||
</hp-dialog>`;var w,$,k}function Ir(t){return m({name:t._nameSel,area:t._areaSel,fill:t._roomFill,customFill:t._roomCustomFill,tempMin:t._roomTempMin,tempMax:t._roomTempMax,tempSrc:t._roomTempSrc,humSrc:t._roomHumSrc,nameScale:t._roomNameScale,labelScale:t._roomLabelScale})}function Dr(t){_(t,"room")}function Lr(t,e){const s=t.host,i="temp"===e?s._roomTempSrc:s._roomHumSrc,o=t=>{"temp"===e?s._roomTempSrc=t:s._roomHumSrc=t,s.requestUpdate()},a=s._roomSrcOpen===e,n=s._t("temp"===e?"room.temp_src_label":"room.hum_src_label");return p`${Do({title:n})}
|
||
${Co({name:`rsrc-${e}`,value:i?"pick":"avg",ariaLabel:n,options:[{value:"avg",label:s._t("room.src_average")},{value:"pick",label:s._t("room.src_pick")}],onChange:t=>{if("avg"===t)return o(""),void(s._roomSrcOpen=null);s._roomSrcOpen=e,s._roomSrcFilter="",s.requestUpdate()}})}
|
||
${i||a?ko({id:`room-${e}-source`,open:a,current:i?{label:t._roomSrcLabel(i),sub:i}:null,placeholder:s._t("room.src_ph"),ariaLabel:n,filter:s._roomSrcFilter,filterPlaceholder:s._t("marker.search_ph"),candidates:a?t._roomSrcCandidates():[],selected:i,emptyText:s._t("marker.nothing_found"),onToggle:()=>{s._roomSrcOpen=a?null:e,s._roomSrcFilter="",s.requestUpdate()},onFilter:t=>{s._roomSrcFilter=t,s.requestUpdate()},onPick:t=>{o(t),s._roomSrcOpen=null}}):d}`}function Tr(){vo(this.host);const t=this.host,e=t._t.bind(t),s=l(t.hass,t._config?.language),i=(t,e)=>Oo(s,t,e),o=!!t._roomEditId,a=o?null:t._wallFaceBatch,n=a&&a.candidates.length>1?e("room.queue_progress",{current:a.index+1,total:a.candidates.length}):"",r=b(t._curSpaceCfg),h=""===t._roomFill,c=t._roomFill||r.fill,u=t._roomCustomFill||r.customFill,_=It(t._roomTempMin,t._roomTempMax).valid,m=function(t){const e=[];return!t._roomEditId&&t._areaSel||t._nameSel.trim()||e.push({field:"room-name",message:"room.error_name"}),It(t._roomTempMin,t._roomTempMax).valid||e.push({field:"room-temp-min",message:"room.error_temp_range"}),e}(t),f=t=>m.find(e=>e.field===t),v=function(t){return g(t,"room",Ir(t))}(t),y=0===m.length&&_&&(!o||v),w=[...t._freeAreas];if(o&&t._areaSel&&!w.some(e=>e.area_id===t._areaSel)){const e=t.hass.areas[t._areaSel];e&&w.unshift(e)}const $=()=>{Dr(t),this._roomDialogCancel()},k=async e=>{if(!o||!v)return void $();const s=e.currentTarget;await t._confirmDanger({key:"discard-room-dialog",kind:"warning",title:i("dialog.discard_title"),message:i("dialog.discard_message"),objectName:t._nameSel.trim()||void 0,confirmLabel:i("dialog.discard_confirm"),cancelLabel:i("dialog.discard_keep"),icon:"mdi:content-save-off-outline",confirmIcon:"mdi:content-save-off-outline"})?$():s?.rejectClose?.()},x=f("room-name"),M=f("room-temp-min"),C=e=>{t._roomFill=e,"custom"!==e&&(t._roomCustomFill=null),t.requestUpdate()},S=t=>Math.round(100*t),P=t._roomCustomFill?e("room.custom_fill_own"):e("room.custom_fill_space"),I=[["name","room.name_scale",t._roomNameScale,e=>{t._roomNameScale=e}],["label","room.label_scale",t._roomLabelScale,e=>{t._roomLabelScale=e}]];return p`<hp-dialog class="roomdialog" .hass=${t.hass} data-kind="room" form-shell wide
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
.title=${o?e("room.settings_title"):n||e("room.new")}
|
||
.badge=${t._spaceModel()?.title??""}
|
||
icon=${o?"mdi:cog-outline":"mdi:floor-plan"} @hp-close=${k}>
|
||
<div class="body hpf-form">
|
||
${n?p`<p class="hpf-hint" role="status" aria-live="polite">${n}</p>`:d}
|
||
${Co({id:"basics",body:zo([So({label:e("room.name_label"),htmlFor:"room-name",error:x?s(x.message):void 0,control:p`<input id="room-name" class="hpf-input" type="text" placeholder=${e("room.name_ph")}
|
||
.value=${t._nameSel} aria-invalid=${x?"true":d}
|
||
@input=${e=>{t._nameSel=e.target.value,t.requestUpdate()}} />`}),So({label:e("room.area_label"),htmlFor:"room-area",help:this._help("room.group_basics.help"),control:p`<select id="room-area" class="hpf-select"
|
||
@change=${e=>{t._areaSel=e.target.value,!t._nameSel&&t._areaSel&&(t._nameSel=t.hass.areas[t._areaSel]?.name||""),t.requestUpdate()}}>
|
||
<option value="">${e("room.no_area_option")}</option>
|
||
${w.map(e=>p`<option value=${e.area_id} ?selected=${e.area_id===t._areaSel}>${e.name}</option>`)}
|
||
</select>`})])})}
|
||
${Co({id:"fill",title:e("room.group_fill"),help:this._help("room.group_fill.help"),body:p`
|
||
${Io({id:"room-fill-inherit",icon:"mdi:layers-outline",title:e("fill.inherit"),caption:s("room.fill_inherit_hint"),checked:h,onChange:t=>C(t?"":Dt.includes(r.fill)?r.fill:"custom")})}
|
||
${h?p`<p class="hpf-hint">${s("room.fill_following",{mode:e(`fill.${r.fill}`)})}</p>`:So({label:s("room.fill_mode_label"),control:Po({name:"rfill",value:t._roomFill,ariaLabel:e("room.fill_label"),options:Dt.map(t=>({value:t,label:s(`fill.seg_${t}`)})),onChange:t=>C(t)})})}
|
||
${"custom"===t._roomFill?Bo({label:P,picker:Do({hex:u.c,opacity:u.a,opacityLabel:e("space.opacity"),onOpacity:e=>{t._roomCustomFill={c:u.c,a:e},t.requestUpdate()},resetLabel:t._roomCustomFill?e("btn.reset"):void 0,onReset:()=>{t._roomCustomFill=null,t.requestUpdate()},picker:p`<hp-color-opacity .label=${P} hide-label flat-swatch
|
||
.opacityLabel=${e("space.opacity")}
|
||
.pickerLabels=${t._colorPickerLabels}
|
||
.color=${u.c}
|
||
.opacity=${u.a}
|
||
@hp-color-opacity-change=${e=>{t._roomCustomFill={c:e.detail.color,a:e.detail.opacity}}}></hp-color-opacity>`})}):d}
|
||
${"temp"===c?p`<div class="hpf-field hpf-temprange">
|
||
<span class="hpf-label hpf-labelrow">${e("room.temp_range_label")}${this._help("room.temp_range.help")}</span>
|
||
${zo([So({label:s("room.temp_min_label"),htmlFor:"room-temp-min",control:Ro({id:"room-temp-min",wide:!0,unit:"°C",step:.5,value:t._roomTempMin,placeholder:String(r.tempMin),ariaLabel:e("room.temp_range_min"),invalid:""!==t._roomTempMin.trim()&&null===Mt(t._roomTempMin),onInput:e=>{t._roomTempMin=e,t.requestUpdate()}})}),So({label:s("room.temp_max_label"),htmlFor:"room-temp-max",control:Ro({id:"room-temp-max",wide:!0,unit:"°C",step:.5,value:t._roomTempMax,placeholder:String(r.tempMax),ariaLabel:e("room.temp_range_max"),invalid:""!==t._roomTempMax.trim()&&null===Mt(t._roomTempMax),onInput:e=>{t._roomTempMax=e,t.requestUpdate()}})})])}
|
||
${M?p`<p class="hpf-error" role="alert">${s(M.message)}</p>`:d}
|
||
<div class="hpf-templegend" aria-hidden="true">
|
||
<span>${e("gs.temp_cold")}</span><span>${e("gs.temp_ok")}</span><span>${e("gs.temp_hot")}</span>
|
||
</div>
|
||
${t._roomTempMin.trim()||t._roomTempMax.trim()?xo(e("room.temp_range_reset"),()=>{t._roomTempMin="",t._roomTempMax="",t.requestUpdate()}):d}
|
||
</div>`:d}`})}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${Co({id:"sources",title:e("room.group_sources"),help:this._help("room.group_sources.help"),body:p`${Fr(this,"temp")}${Fr(this,"hum")}`})}
|
||
${Co({id:"sizes",title:e("room.sizes_section"),help:this._help("room.sizes_section.help"),body:p`
|
||
${I.map(([i,o,a,n])=>p`<div class="hpf-field">
|
||
========
|
||
${xo({id:"sources",title:e("room.group_sources"),help:this._help("room.group_sources.help"),body:p`${Lr(this,"temp")}${Lr(this,"hum")}`})}
|
||
${xo({id:"sizes",title:e("room.sizes_section"),help:this._help("room.sizes_section.help"),body:p`
|
||
${I.map(([s,o,a,n])=>p`<div class="hpf-field">
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="hpf-headline">
|
||
<span class="hpf-label hpf-labelrow"><label for=${`room-${i}-scale`}>${e(o)}</label></span>
|
||
${xo(s("btn.reset_100"),()=>{n(1),t.requestUpdate()},{disabled:100===S(a)})}
|
||
</div>
|
||
${Lo({id:`room-${i}-scale`,min:50,max:300,step:5,value:S(a),unit:"%",ariaLabel:e(o),slider:this._rangeInput(50,300,5,S(a),e=>{n(e/100),t.requestUpdate()},!1,e(o)),onInput:e=>{n(e/100),t.requestUpdate()}})}
|
||
${No("50%","300%")}
|
||
</div>`)}
|
||
<p class="hpf-hint">${s("room.sizes_hint",{v:String(S(r.cardFontScale))})}</p>
|
||
<div class="hpf-tint hpf-preview">${t._renderCardPreview(r.cardFontScale,t._roomNameScale,t._roomLabelScale)}</div>`})}
|
||
</div>
|
||
<div class="row dialog-action-footer hpf-footer" slot="footer">
|
||
${o||t._pendingSplit?d:p`<div class="dialog-action-group">
|
||
<button class="btn ghost" data-hp="dialog-confirm" @click=${()=>this._keepClosedAsPartitions()}>
|
||
<ha-icon icon="mdi:wall"></ha-icon>${e("btn.keep_as_walls")}
|
||
</button>
|
||
</div>`}
|
||
${Eo(m.length?{action:xo(s("dialog.review_fields",{n:String(m.length)}),()=>{const e=m[0];if(!e)return;const i=t.renderRoot.querySelector(`#${e.field}`);i?.scrollIntoView({block:"center"}),i?.focus()})}:{})}
|
||
<div class="dialog-action-group dialog-action-commit">
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${k}>${e("btn.cancel")}</button>
|
||
${o?p`<button class="btn on" data-hp="dialog-confirm" ?disabled=${!y}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
title=${m[0]?s(m[0].message):d}
|
||
@click=${()=>{Rr(t),this._saveRoomEdit()}}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${e("btn.save")}
|
||
</button>`:p`<button class="btn on room-save" data-hp="dialog-confirm" ?disabled=${!y}
|
||
title=${m[0]?s(m[0].message):d}
|
||
@click=${()=>{Rr(t),this._saveRoom()}}>
|
||
========
|
||
title=${m[0]?i(m[0].message):d}
|
||
@click=${()=>{Dr(t),this._saveRoomEdit()}}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${e("btn.save")}
|
||
</button>`:p`<button class="btn on room-save" data-hp="dialog-confirm" ?disabled=${!y}
|
||
title=${m[0]?i(m[0].message):d}
|
||
@click=${()=>{Dr(t),this._saveRoom()}}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<ha-icon icon="mdi:check"></ha-icon>${e("btn.save")}
|
||
</button>`}
|
||
</div>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}const Nr=new WeakMap;function Er(t,e,i){let s=Nr.get(t);s||(s=new Map,Nr.set(t,s));const o=s.get(e);if(o)return void(o.run=i);const a={run:i};s.set(e,a),queueMicrotask(()=>{s.get(e)===a&&(s.delete(e),a.run())})}function Ar(t,e){const i=Nr.get(t),s=i?.get(e);s&&(i.delete(e),s.run())}function Or(t,e){const i=Nr.get(t);if(!i)return;const s=e?[...i].filter(([t])=>t===e):[...i];for(const[t]of s)i.delete(t);i.size||Nr.delete(t)}const Br=new WeakMap,Hr=new Set(["_cursorPt","_opMeasure","_physicalDrag","_physicalRotate","_decorDraft","_dtBox","_dtDrag","_bdDrag","_furnPreviewInput","_layout"]),Wr=new Set(["_cursorPt","_opMeasure","_furnPreviewInput"]),Gr=new Set(["_physicalDrag","_physicalRotate","_decorDraft","_dtDrag","_bdDrag"]),jr=t=>{let e=Br.get(t);return e||(e={raf:0,requestedRevision:0,paintedRevision:0,waiters:[],hidden:[],transparent:[],dimmed:[]},Br.set(t,e)),e},Ur=(t,e)=>{t.paintedRevision=Math.max(t.paintedRevision,e);const i=t.waiters.filter(e=>e.revision<=t.paintedRevision);t.waiters=t.waiters.filter(e=>e.revision>t.paintedRevision);for(const t of i)t.resolve()},qr=t=>!!("view"!==t._mode&&(t._deviceDrag||t._physicalDrag||t._physicalRotate||t._decorDraft||t._decorMove||t._dtDrag||t._bdDrag||t._opDrag||t._resize?.dragging));function Kr(t,e,i){const s=t;if(!s?.isConnected||"view"===s._mode)return!1;const o=void 0!==e&&Hr.has(e);if("_layout"===e&&!s._deviceDrag)return!1;if("_dtBox"===e&&!s._dtDrag)return!1;if(void 0!==e&&Gr.has(e)&&null==i&&null!=s[e]&&qr(s))return!1;if(void 0!==e&&Gr.has(e)&&null==s[e])return!1;if(void 0!==e&&Wr.has(e)&&null==s[e])return!1;return!!(o&&(Wr.has(e)||qr(s))||void 0===e&&qr(s))&&(function(t){const e=jr(t);if(e.requestedRevision++,e.raf||"function"!=typeof requestAnimationFrame)return;e.raf=requestAnimationFrame(()=>{e.raf=0;const i=e.requestedRevision;!function(t){const e=t,i=e.renderRoot;if(!i)return;const s=jr(e);Yr(s),Qr(e,i);const o=i.querySelector("[data-hp-live-editor]");if(!o)return;if(Jr(s,i,".hp-editor-only-layer:not(.hp-plan-snap-layer)"),"plan"===e._mode)e._opDrag&&Vr(s,i,".wallbodies"),e._resize?.dragging&&(il(s,i,".wallbodies"),Jr(s,i,".resize-layer"),el(s,i,e._resize.plan?.movingOpeningIds||[])),e._opDrag&&Jr(s,i,".openinglayer");else if("decor"===e._mode){const t=e._dtDrag?.id||e._decorMove?.id;t&&tl(s,i,t),Jr(s,i,".dtframe, .backdropframe")}Lt(Xr(e),o);const a=i.querySelector("[data-hp-live-editor-html]");if(a){const t=e._viewOr(e._baseVb());Lt(e._renderLiveEditorMeasurements(t),a)}e._liveEditorPaintCount=(e._liveEditorPaintCount||0)+1}(t),Ur(e,i)})}(s),!0)}const Vr=(t,e,i)=>{for(const s of e.querySelectorAll(i))s.closest("[data-hp-live-editor]")||"hidden"!==s.style.visibility&&(s.style.visibility="hidden",t.hidden.push(s))},Jr=(t,e,i)=>{for(const s of e.querySelectorAll(i))s.closest("[data-hp-live-editor]")||"0"!==s.style.opacity&&(s.style.opacity="0",t.transparent.push(s))},Yr=t=>{for(const e of t.hidden)e.style.removeProperty("visibility");t.hidden.length=0;for(const e of t.transparent)e.style.removeProperty("opacity");t.transparent.length=0;for(const e of t.dimmed)e.style.removeProperty("opacity");t.dimmed.length=0},Zr=(t,e,i=[])=>{if("iso"===t._renderProjection)return Tt``;const s=t._spaceModel();if(!s)return Tt``;const o=new Set(i),a=(s.rooms||[]).filter(t=>!!t.id&&o.has(t.id)).flatMap(t=>{const e=t.poly||[];return e.map((t,i)=>[t,e[(i+1)%e.length]])}),n=(t,e)=>{const[i,s]=e,o=s[0]-i[0],a=s[1]-i[1],n=o*o+a*a;if(!(n>0))return!1;const r=((t[0]-i[0])*o+(t[1]-i[1])*a)/n,l=Math.max(0,Math.min(1,r));return Math.hypot(t[0]-i[0]-o*l,t[1]-i[1]-a*l)<1e-4},r=[...t._spaceWalls.filter(t=>{const e=(t.a||[]).map(t=>t*pt),i=(t.b||[]).map(t=>t*pt);return a.some(t=>n(e,t)&&n(i,t))}).map((e,i)=>((e,i,s,o)=>{const a=Math.hypot(i[0]-e[0],i[1]-e[1]);if(!(a>1e-9&&s>0))return null;const n=X(s,t._cellCm,t._gridPitch)/2,r=-(i[1]-e[1])/a*n,l=(i[0]-e[0])/a*n;return{key:o,kind:"outer",cm:s,a:e,b:i,depthUnits:2*n,quad:[[e[0]+r,e[1]+l],[i[0]+r,i[1]+l],[i[0]-r,i[1]-l],[e[0]-r,e[1]-l]]}})((e.a||[]).map(t=>t*pt),(e.b||[]).map(t=>t*pt),e.cm,e.key||`wall-${i}`))].filter(t=>!!t),l=t._openingsR.map(t=>({x:t.rx,y:t.ry,angle:t.angle,length:t.rlen})),h=r.map(t=>Rt(t,l)).filter(Boolean);if(!h.length)return Tt``;const c=Math.max(...r.map(t=>t.depthUnits),0),d=t._viewOr(t._baseVb()),p=t._stageEl?.clientWidth&&d.w?t._stageEl.clientWidth/d.w:1,u=Ft(c,p)||zt(Nt(t._cellCm),p),_=e?.color||"#607d8b",m=t._fillColors.wall_fill,g=h.join(" ");return Tt`<g class="wallbodies hp-resize-preview-walls"
|
||
========
|
||
</hp-dialog>`}const Rr=new WeakMap;function zr(t,e,s){let i=Rr.get(t);i||(i=new Map,Rr.set(t,i));const o=i.get(e);if(o)return void(o.run=s);const a={run:s};i.set(e,a),queueMicrotask(()=>{i.get(e)===a&&(i.delete(e),a.run())})}function Fr(t,e){const s=Rr.get(t),i=s?.get(e);i&&(s.delete(e),i.run())}function Nr(t,e){const s=Rr.get(t);if(!s)return;const i=e?[...s].filter(([t])=>t===e):[...s];for(const[t]of i)s.delete(t);s.size||Rr.delete(t)}const Ar=new WeakMap,Er=new Set(["_cursorPt","_opMeasure","_physicalDrag","_physicalRotate","_decorDraft","_dtBox","_dtDrag","_bdDrag","_furnPreviewInput","_layout"]),Or=new Set(["_cursorPt","_opMeasure","_furnPreviewInput"]),Br=new Set(["_physicalDrag","_physicalRotate","_decorDraft","_dtDrag","_bdDrag"]),Hr=t=>{let e=Ar.get(t);return e||(e={raf:0,requestedRevision:0,paintedRevision:0,waiters:[],hidden:[],transparent:[],dimmed:[]},Ar.set(t,e)),e},Wr=(t,e)=>{t.paintedRevision=Math.max(t.paintedRevision,e);const s=t.waiters.filter(e=>e.revision<=t.paintedRevision);t.waiters=t.waiters.filter(e=>e.revision>t.paintedRevision);for(const t of s)t.resolve()},jr=t=>!!("view"!==t._mode&&(t._deviceDrag||t._physicalDrag||t._physicalRotate||t._decorDraft||t._decorMove||t._dtDrag||t._bdDrag||t._opDrag||t._resize?.dragging));function Gr(t,e,s){const i=t;if(!i?.isConnected||"view"===i._mode)return!1;const o=void 0!==e&&Er.has(e);if("_layout"===e&&!i._deviceDrag)return!1;if("_dtBox"===e&&!i._dtDrag)return!1;if(void 0!==e&&Br.has(e)&&null==s&&null!=i[e]&&jr(i))return!1;if(void 0!==e&&Br.has(e)&&null==i[e])return!1;if(void 0!==e&&Or.has(e)&&null==i[e])return!1;return!!(o&&(Or.has(e)||jr(i))||void 0===e&&jr(i))&&(function(t){const e=Hr(t);if(e.requestedRevision++,e.raf||"function"!=typeof requestAnimationFrame)return;e.raf=requestAnimationFrame(()=>{e.raf=0;const s=e.requestedRevision;!function(t){const e=t,s=e.renderRoot;if(!s)return;const i=Hr(e);Kr(i),Zr(e,s);const o=s.querySelector("[data-hp-live-editor]");if(!o)return;if(Ur(i,s,".hp-editor-only-layer:not(.hp-plan-snap-layer)"),"plan"===e._mode)e._opDrag&&qr(i,s,".wallbodies"),e._resize?.dragging&&(Qr(i,s,".wallbodies"),Ur(i,s,".resize-layer"),Xr(i,s,e._resize.plan?.movingOpeningIds||[])),e._opDrag&&Ur(i,s,".openinglayer");else if("decor"===e._mode){const t=e._dtDrag?.id||e._decorMove?.id;t&&Yr(i,s,t),Ur(i,s,".dtframe, .backdropframe")}Lt(Jr(e),o);const a=s.querySelector("[data-hp-live-editor-html]");if(a){const t=e._viewOr(e._baseVb());Lt(e._renderLiveEditorMeasurements(t),a)}e._liveEditorPaintCount=(e._liveEditorPaintCount||0)+1}(t),Wr(e,s)})}(i),!0)}const qr=(t,e,s)=>{for(const i of e.querySelectorAll(s))i.closest("[data-hp-live-editor]")||"hidden"!==i.style.visibility&&(i.style.visibility="hidden",t.hidden.push(i))},Ur=(t,e,s)=>{for(const i of e.querySelectorAll(s))i.closest("[data-hp-live-editor]")||"0"!==i.style.opacity&&(i.style.opacity="0",t.transparent.push(i))},Kr=t=>{for(const e of t.hidden)e.style.removeProperty("visibility");t.hidden.length=0;for(const e of t.transparent)e.style.removeProperty("opacity");t.transparent.length=0;for(const e of t.dimmed)e.style.removeProperty("opacity");t.dimmed.length=0},Vr=(t,e,s=[])=>{if("iso"===t._renderProjection)return Tt``;const i=t._spaceModel();if(!i)return Tt``;const o=new Set(s),a=(i.rooms||[]).filter(t=>!!t.id&&o.has(t.id)).flatMap(t=>{const e=t.poly||[];return e.map((t,s)=>[t,e[(s+1)%e.length]])}),n=(t,e)=>{const[s,i]=e,o=i[0]-s[0],a=i[1]-s[1],n=o*o+a*a;if(!(n>0))return!1;const r=((t[0]-s[0])*o+(t[1]-s[1])*a)/n,l=Math.max(0,Math.min(1,r));return Math.hypot(t[0]-s[0]-o*l,t[1]-s[1]-a*l)<1e-4},r=[...t._spaceWalls.filter(t=>{const e=(t.a||[]).map(t=>t*pt),s=(t.b||[]).map(t=>t*pt);return a.some(t=>n(e,t)&&n(s,t))}).map((e,s)=>((e,s,i,o)=>{const a=Math.hypot(s[0]-e[0],s[1]-e[1]);if(!(a>1e-9&&i>0))return null;const n=X(i,t._cellCm,t._gridPitch)/2,r=-(s[1]-e[1])/a*n,l=(s[0]-e[0])/a*n;return{key:o,kind:"outer",cm:i,a:e,b:s,depthUnits:2*n,quad:[[e[0]+r,e[1]+l],[s[0]+r,s[1]+l],[s[0]-r,s[1]-l],[e[0]-r,e[1]-l]]}})((e.a||[]).map(t=>t*pt),(e.b||[]).map(t=>t*pt),e.cm,e.key||`wall-${s}`))].filter(t=>!!t),l=t._openingsR.map(t=>({x:t.rx,y:t.ry,angle:t.angle,length:t.rlen})),h=r.map(t=>Rt(t,l)).filter(Boolean);if(!h.length)return Tt``;const c=Math.max(...r.map(t=>t.depthUnits),0),d=t._viewOr(t._baseVb()),p=t._stageEl?.clientWidth&&d.w?t._stageEl.clientWidth/d.w:1,u=zt(c,p)||Ft(Nt(t._cellCm),p),_=e?.color||"#607d8b",m=t._fillColors.wall_fill,g=h.join(" ");return Tt`<g class="wallbodies hp-resize-preview-walls"
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
style="--room-stroke:${_};--wall-fill:${m.c};--wall-fill-op:${m.a}">
|
||
<path class="wallbody-fill" data-component="preview" d=${g}
|
||
fill=${m.c} fill-opacity=${m.a} fill-rule="nonzero" stroke="none"></path>
|
||
<path class="wallbody ${u?"solid":""}" data-hp="wall"
|
||
data-id="preview" data-kind="preview" d=${g}
|
||
fill=${u?"none":"url(#hp-wall-hatch)"} fill-rule="nonzero"
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
stroke=${_} stroke-width=${Et(.6,t._cellCm)}></path>
|
||
</g>`},Xr=t=>{if("plan"===t._mode)return(t=>{const e=t._baseVb(),i=t._viewOr(e),s=t._opMeasureView;if(t._resize?.dragging){const e=t._spaceDisplayForRender(),s=t._resize.plan;return Tt`<g class="hp-live-resize" aria-hidden="true" pointer-events="none">
|
||
${Zr(t,e,s?.roomIds)}
|
||
========
|
||
stroke=${_} stroke-width=${At(.6,t._cellCm)}></path>
|
||
</g>`},Jr=t=>{if("plan"===t._mode)return(t=>{const e=t._baseVb(),s=t._viewOr(e),i=t._opMeasureView;if(t._resize?.dragging){const e=t._spaceDisplayForRender(),i=t._resize.plan;return Tt`<g class="hp-live-resize" aria-hidden="true" pointer-events="none">
|
||
${Vr(t,e,i?.roomIds)}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
${t._renderResizeMeasurements()}
|
||
${t._renderOpenings(e,s?.movingOpeningIds)}
|
||
${t._renderResizeLayer(i,s?.roomIds)}
|
||
</g>`}const o=t._spaceDisplayForRender();return Tt`<g class="hp-live-plan" aria-hidden="true" pointer-events="none">
|
||
${t._opDrag?t._renderWallBodies(o):d}
|
||
${t._renderMarkupLayer(e)}
|
||
${t._renderHiddenWallDiagnosticOverlay()}
|
||
${t._renderOpeningPlacementPreview()}
|
||
${s?t._renderOpeningDimensionGuides(s):d}
|
||
${s?.guide?t._renderOpeningCenterTick(s.guide):d}
|
||
${t._renderActiveChainInk()}
|
||
${""}
|
||
${t._renderAlignGuides()}
|
||
${"draw"===t._tool?d:t._renderPlanSnapOverlay()}
|
||
${t._renderWallThickUi()}
|
||
${t._opDrag?t._renderOpenings(o):d}
|
||
</g>`})(t);if("decor"===t._mode){const e=t._viewOr(t._baseVb()),i=t._dtDrag?.id||t._decorMove?.id||null;return Tt`<g class="hp-live-decor" aria-hidden="true" pointer-events="none">
|
||
${t._renderDecorLayer(i)}
|
||
${t._renderAlignGuides()}
|
||
${t._renderBackdropFrame(e)}
|
||
${t._renderTextFrame(e)}
|
||
</g>`}return Tt`<g class="hp-live-devices" aria-hidden="true" pointer-events="none">
|
||
${t._renderAlignGuides()}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</g>`},Qr=(t,e)=>{const i=t._deviceDrag;if(!i)return;const s=t._devices.find(t=>t.id===i.id),o=[...e.querySelectorAll('[data-hp="device"]')].find(t=>t.dataset.id===i.id);if(!s||!o)return;const a=t._livePos(s),n=t._scenePoint([a.x,a.y]),r=t._viewOr(t._baseVb());o.style.left=(n[0]-r.x)/r.w*100+"%",o.style.top=(n[1]-r.y)/r.h*100+"%"},tl=(t,e,i)=>{for(const s of e.querySelectorAll('.decorlayer [data-hp="decor"]'))s.closest("[data-hp-live-editor]")||s.dataset.id!==i||"0"!==s.style.opacity&&(s.style.opacity="0",t.transparent.push(s))},el=(t,e,i)=>{const s=new Set(i);for(const i of e.querySelectorAll('.openinglayer [data-hp="opening"]'))!i.closest("[data-hp-live-editor]")&&s.has(i.dataset.id||"")&&(i.style.opacity="0",t.transparent.push(i))},il=(t,e,i)=>{for(const s of e.querySelectorAll(i))s.closest("[data-hp-live-editor]")||(s.style.opacity="0.35",t.dimmed.push(s))};const sl=(t,e,i)=>Math.min(i,Math.max(e,Number.isFinite(t)?t:e));function ol(t){return Number.isFinite(t)?(t%360+360)%360:0}function al(t){if("string"!=typeof t)return null;const e=t.trim().replace(/^#/,""),i=/^[0-9a-fA-F]{3}$/.test(e)?e.split("").map(t=>`${t}${t}`).join(""):e;return/^[0-9a-fA-F]{6}$/.test(i)?`#${i.toLowerCase()}`:null}function nl(t){const e=al(t);return e?{r:Number.parseInt(e.slice(1,3),16),g:Number.parseInt(e.slice(3,5),16),b:Number.parseInt(e.slice(5,7),16)}:null}function rl(t){const e=sl(t.r,0,255)/255,i=sl(t.g,0,255)/255,s=sl(t.b,0,255)/255,o=Math.max(e,i,s),a=o-Math.min(e,i,s);let n=0;return a>0&&(n=o===e?(i-s)/a%6*60:o===i?60*((s-e)/a+2):60*((e-i)/a+4)),{h:ol(n),s:0===o?0:a/o*100,v:100*o}}function ll(t){return function(t){const e=t=>Math.round(sl(t,0,255)).toString(16).padStart(2,"0");return`#${e(t.r)}${e(t.g)}${e(t.b)}`}(function(t){const e=ol(t.h),i=sl(t.s,0,100)/100,s=sl(t.v,0,100)/100,o=s*i,a=o*(1-Math.abs(e/60%2-1)),n=s-o;let r;return r=e<60?[o,a,0]:e<120?[a,o,0]:e<180?[0,o,a]:e<240?[0,a,o]:e<300?[a,0,o]:[o,0,a],{r:Math.round(255*(r[0]+n)),g:Math.round(255*(r[1]+n)),b:Math.round(255*(r[2]+n))}}(t))}const hl={title:"Color picker",hue:"Hue",saturation:"Saturation",value:"Brightness",hex:"Hex color",invalidHex:"Enter a 3- or 6-digit hex color",confirm:"OK"};class cl extends Ot{constructor(){super(...arguments),this.label="",this.opacityLabel="Opacity",this.color="#607d8b",this.opacity=1,this.disabled=!1,this.showOpacity=!0,this.hideLabel=!1,this.flatSwatch=!1,this.coverSwatch=!1,this.pickerLabels=hl,this._open=!1,this._pickerRaf=0,this._emitRaf=0,this._forceFallback=!1,this._overlayDispose=null,this._hue=0,this._saturation=0,this._value=0,this._hexDraft="#607d8b",this._hexInvalid=!1,this._hexNeedsValidInput=!1,this._lastValidColor="#607d8b",this._activePointerId=null,this._outsidePointerDown=t=>{if(!this._open)return;const e=t.composedPath();this._floating.containsPath(e)||this._closePicker(!1,"outside")},this._keyDown=t=>{this._open&&"Escape"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),this._closePicker(this._floating.ownsActiveElement(),"escape"))},this._floating=new Go(this,"color-opacity",this._keyDown),this._queuePickerPosition=()=>{if(!this._open)return;this._pickerRaf&&cancelAnimationFrame(this._pickerRaf);const t=this._window();t&&(this._pickerRaf=t.requestAnimationFrame(()=>{this._pickerRaf=0,this._positionPicker()||this._closePicker()}))}}connectedCallback(){super.connectedCallback(),this._syncFromColor(this.color,!1),this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.addEventListener("resize",this._queuePickerPosition),t?.addEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.addEventListener("resize",this._queuePickerPosition),t?.visualViewport?.addEventListener("scroll",this._queuePickerPosition),this.addEventListener("keydown",this._keyDown,!0)}disconnectedCallback(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.removeEventListener("resize",this._queuePickerPosition),t?.removeEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.removeEventListener("resize",this._queuePickerPosition),t?.visualViewport?.removeEventListener("scroll",this._queuePickerPosition),this.removeEventListener("keydown",this._keyDown,!0),this._pickerRaf&&cancelAnimationFrame(this._pickerRaf),this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._pickerRaf=0,this._emitRaf=0,this._closePicker(!1,"disconnect"),super.disconnectedCallback()}updated(t){if(t.has("color")){const t=al(this.color);t&&t!==this._lastValidColor&&this._syncFromColor(t,this._open)}this.disabled&&this._open?this._closePicker():this._open&&(this._supportsPopover()||this._renderFallback(),(t.has("color")||t.has("opacity")||t.has("showOpacity")||t.has("label")||t.has("opacityLabel")||t.has("pickerLabels"))&&this._queuePickerPosition())}_window(){return this._floating.window()}_supportsPopover(){return this._floating.usesPopover(this._forceFallback)}_dialog(){return this._floating.dialog()}async _toggle(){this.disabled||(this._open?this._closePicker():(this._forceFallback=!1,this._syncFromColor(this.color,!1),this._hexInvalid=!1,this._hexNeedsValidInput=!1,this._activePointerId=null,this._open=!0,await this.updateComplete,this._open&&(this._supportsPopover()||this._renderFallback(),this._positionPicker()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:t=>this._closePicker("escape"===t&&this._floating.ownsActiveElement(),t)})||null:this._closePicker())))}_closePicker(t=!1,e="exclusive"){if(!this._open&&!this._floating.hasFallback)return;const i=this._overlayDispose;this._overlayDispose=null,i?.();const s=this.renderRoot.querySelector(".picker");if(s?.hidePopover)try{s.matches(":popover-open")&&s.hidePopover()}catch{}this._open=!1,this._cancelQueuedEmit(),this._activePointerId=null,this._floating.destroy(),t&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_surface(){return this._floating.surface(".picker",this._supportsPopover())}_renderFallback(){const t=cl.styles.cssText;this._floating.renderFallback(this._pickerTemplate(!1),t)}_positionPicker(){if(!this._open)return!1;const t=this._window(),e=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!t||!e?.isConnected||!i?.isConnected)return!1;const s=jo(t);if(i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden",this._supportsPopover()&&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.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden"}const o=e.getBoundingClientRect(),a=i.getBoundingClientRect();if(!(o.width&&o.height&&a.width&&a.height))return!1;const n=Uo(o,a,s);return i.style.left=`${n.left}px`,i.style.top=`${n.top}px`,i.dataset.side=n.side,i.style.visibility="",!0}_labels(){const t=this.pickerLabels||hl;return{title:t.title||hl.title,hue:t.hue||hl.hue,saturation:t.saturation||hl.saturation,value:t.value||hl.value,hex:t.hex||hl.hex,invalidHex:t.invalidHex||hl.invalidHex,confirm:t.confirm||hl.confirm}}_syncFromColor(t,e){const i=al(Bt(t,"#607d8b"))||"#607d8b",s=nl(i);if(!s)return;const o=rl(s);(!e||o.s>1e-4)&&(this._hue=o.h),this._saturation=o.s,this._value=o.v,this._hexDraft=i,this._hexInvalid=!1,this._hexNeedsValidInput=!1,this._lastValidColor=i}_cancelQueuedEmit(t=!1){this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._emitRaf=0,t&&this._syncFromColor(this._lastValidColor,!0)}_queueHsvEmit(){if(this._emitRaf)return;const t=this._window();t?this._emitRaf=t.requestAnimationFrame(()=>{this._emitRaf=0,this._emitHsv()}):this._emitHsv()}_emitHsv(){this._emit(ll({h:this._hue,s:this._saturation,v:this._value}),this.opacity)}_setHue(t){this._hue=Math.min(359,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setSaturation(t){this._saturation=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setValue(t){this._value=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setOpacity(t){this._emit(this._lastValidColor,t)}_shiftRangeKey(t,e,i,s,o){if(!t.shiftKey)return;const a="ArrowRight"===t.key||"ArrowUp"===t.key?10:"ArrowLeft"===t.key||"ArrowDown"===t.key?-10:0;a&&(t.preventDefault(),t.stopPropagation(),o(Math.min(s,Math.max(i,e+a))))}_setSvFromPointer(t,e){const i=t.currentTarget.getBoundingClientRect();i.width&&i.height&&(this._saturation=Math.min(100,Math.max(0,(t.clientX-i.left)/i.width*100)),this._value=Math.min(100,Math.max(0,100*(1-(t.clientY-i.top)/i.height))),e?(this._cancelQueuedEmit(),this._emitHsv()):this._queueHsvEmit())}_svPointerDown(t){if(t.preventDefault(),t.stopPropagation(),null===this._activePointerId){this._activePointerId=t.pointerId;try{t.currentTarget.setPointerCapture(t.pointerId)}catch{}this._setSvFromPointer(t,!0)}}_svPointerMove(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!1))}_svPointerUp(t){if(t.pointerId===this._activePointerId){t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!0),this._activePointerId=null;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}}}_svPointerCancel(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._activePointerId=null,this._cancelQueuedEmit(!0))}_svLostPointerCapture(t){t.pointerId===this._activePointerId&&(this._activePointerId=null,this._cancelQueuedEmit(!0))}_hexInput(t){const e=t.target.value;this._hexDraft=e;const i=al(e),s=i?nl(i):null;if(!i||!s)return void(this._hexInvalid=this._hexNeedsValidInput);this._hexNeedsValidInput=!1,this._hexInvalid=!1;const o=rl(s);o.s>1e-4&&(this._hue=o.h),this._saturation=o.s,this._value=o.v,this._emit(i,this.opacity,!0)}_commitHex(){const t=al(this._hexDraft);if(!t)return this._hexDraft=this._lastValidColor,this._hexInvalid=!0,void(this._hexNeedsValidInput=!0);this._hexDraft=t,this._hexNeedsValidInput?this._hexInvalid=!0:(this._hexInvalid=!1,t!==this._lastValidColor&&this._emit(t,this.opacity))}_confirm(t){t.preventDefault(),t.stopPropagation(),this._commitHex(),this._hexInvalid||this._hexNeedsValidInput?this.updateComplete.then(()=>{this._surface()?.querySelector('input[type="text"]')?.focus()}):this._closePicker(!0)}_hexKeyDown(t){"Enter"===t.key&&(t.preventDefault(),t.stopPropagation(),this._commitHex())}_emit(t,e,i=!1){const s=al(t)||this._lastValidColor,o=Number.isFinite(e)?e:Number(this.opacity)||0,a=Math.min(1,Math.max(0,o));this.color=s,this.opacity=a,this._lastValidColor=s,i||(this._hexDraft=s),this._hexInvalid=this._hexNeedsValidInput,this.dispatchEvent(new CustomEvent("hp-color-opacity-change",{detail:{color:s,opacity:a},bubbles:!0,composed:!0}))}_pickerTemplate(t){const e=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),i=ll({h:this._hue,s:this._saturation,v:this._value}),s=ll({h:this._hue,s:100,v:100}),o=this._labels(),a=Math.round(this._hue),n=Math.round(this._saturation),r=Math.round(this._value);return p`
|
||
========
|
||
</g>`},Zr=(t,e)=>{const s=t._deviceDrag;if(!s)return;const i=t._devices.find(t=>t.id===s.id),o=[...e.querySelectorAll('[data-hp="device"]')].find(t=>t.dataset.id===s.id);if(!i||!o)return;const a=t._livePos(i),n=t._scenePoint([a.x,a.y]),r=t._viewOr(t._baseVb());o.style.left=(n[0]-r.x)/r.w*100+"%",o.style.top=(n[1]-r.y)/r.h*100+"%"},Yr=(t,e,s)=>{for(const i of e.querySelectorAll('.decorlayer [data-hp="decor"]'))i.closest("[data-hp-live-editor]")||i.dataset.id!==s||"0"!==i.style.opacity&&(i.style.opacity="0",t.transparent.push(i))},Xr=(t,e,s)=>{const i=new Set(s);for(const s of e.querySelectorAll('.openinglayer [data-hp="opening"]'))!s.closest("[data-hp-live-editor]")&&i.has(s.dataset.id||"")&&(s.style.opacity="0",t.transparent.push(s))},Qr=(t,e,s)=>{for(const i of e.querySelectorAll(s))i.closest("[data-hp-live-editor]")||(i.style.opacity="0.35",t.dimmed.push(i))};const tl=(t,e,s)=>Math.min(s,Math.max(e,Number.isFinite(t)?t:e));function el(t){return Number.isFinite(t)?(t%360+360)%360:0}function sl(t){if("string"!=typeof t)return null;const e=t.trim().replace(/^#/,""),s=/^[0-9a-fA-F]{3}$/.test(e)?e.split("").map(t=>`${t}${t}`).join(""):e;return/^[0-9a-fA-F]{6}$/.test(s)?`#${s.toLowerCase()}`:null}function il(t){const e=sl(t);return e?{r:Number.parseInt(e.slice(1,3),16),g:Number.parseInt(e.slice(3,5),16),b:Number.parseInt(e.slice(5,7),16)}:null}function ol(t){const e=tl(t.r,0,255)/255,s=tl(t.g,0,255)/255,i=tl(t.b,0,255)/255,o=Math.max(e,s,i),a=o-Math.min(e,s,i);let n=0;return a>0&&(n=o===e?(s-i)/a%6*60:o===s?60*((i-e)/a+2):60*((e-s)/a+4)),{h:el(n),s:0===o?0:a/o*100,v:100*o}}function al(t){return function(t){const e=t=>Math.round(tl(t,0,255)).toString(16).padStart(2,"0");return`#${e(t.r)}${e(t.g)}${e(t.b)}`}(function(t){const e=el(t.h),s=tl(t.s,0,100)/100,i=tl(t.v,0,100)/100,o=i*s,a=o*(1-Math.abs(e/60%2-1)),n=i-o;let r;return r=e<60?[o,a,0]:e<120?[a,o,0]:e<180?[0,o,a]:e<240?[0,a,o]:e<300?[a,0,o]:[o,0,a],{r:Math.round(255*(r[0]+n)),g:Math.round(255*(r[1]+n)),b:Math.round(255*(r[2]+n))}}(t))}const nl={title:"Color picker",hue:"Hue",saturation:"Saturation",value:"Brightness",hex:"Hex color",invalidHex:"Enter a 3- or 6-digit hex color",confirm:"OK"};class rl extends Ot{constructor(){super(...arguments),this.label="",this.opacityLabel="Opacity",this.color="#607d8b",this.opacity=1,this.disabled=!1,this.showOpacity=!0,this.hideLabel=!1,this.flatSwatch=!1,this.coverSwatch=!1,this.pickerLabels=nl,this._open=!1,this._pickerRaf=0,this._emitRaf=0,this._forceFallback=!1,this._overlayDispose=null,this._hue=0,this._saturation=0,this._value=0,this._hexDraft="#607d8b",this._hexInvalid=!1,this._hexNeedsValidInput=!1,this._lastValidColor="#607d8b",this._activePointerId=null,this._outsidePointerDown=t=>{if(!this._open)return;const e=t.composedPath();this._floating.containsPath(e)||this._closePicker(!1,"outside")},this._keyDown=t=>{this._open&&"Escape"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),this._closePicker(this._floating.ownsActiveElement(),"escape"))},this._floating=new Ho(this,"color-opacity",this._keyDown),this._queuePickerPosition=()=>{if(!this._open)return;this._pickerRaf&&cancelAnimationFrame(this._pickerRaf);const t=this._window();t&&(this._pickerRaf=t.requestAnimationFrame(()=>{this._pickerRaf=0,this._positionPicker()||this._closePicker()}))}}connectedCallback(){super.connectedCallback(),this._syncFromColor(this.color,!1),this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.addEventListener("resize",this._queuePickerPosition),t?.addEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.addEventListener("resize",this._queuePickerPosition),t?.visualViewport?.addEventListener("scroll",this._queuePickerPosition),this.addEventListener("keydown",this._keyDown,!0)}disconnectedCallback(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.removeEventListener("resize",this._queuePickerPosition),t?.removeEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.removeEventListener("resize",this._queuePickerPosition),t?.visualViewport?.removeEventListener("scroll",this._queuePickerPosition),this.removeEventListener("keydown",this._keyDown,!0),this._pickerRaf&&cancelAnimationFrame(this._pickerRaf),this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._pickerRaf=0,this._emitRaf=0,this._closePicker(!1,"disconnect"),super.disconnectedCallback()}updated(t){if(t.has("color")){const t=sl(this.color);t&&t!==this._lastValidColor&&this._syncFromColor(t,this._open)}this.disabled&&this._open?this._closePicker():this._open&&(this._supportsPopover()||this._renderFallback(),(t.has("color")||t.has("opacity")||t.has("showOpacity")||t.has("label")||t.has("opacityLabel")||t.has("pickerLabels"))&&this._queuePickerPosition())}_window(){return this._floating.window()}_supportsPopover(){return this._floating.usesPopover(this._forceFallback)}_dialog(){return this._floating.dialog()}async _toggle(){this.disabled||(this._open?this._closePicker():(this._forceFallback=!1,this._syncFromColor(this.color,!1),this._hexInvalid=!1,this._hexNeedsValidInput=!1,this._activePointerId=null,this._open=!0,await this.updateComplete,this._open&&(this._supportsPopover()||this._renderFallback(),this._positionPicker()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:t=>this._closePicker("escape"===t&&this._floating.ownsActiveElement(),t)})||null:this._closePicker())))}_closePicker(t=!1,e="exclusive"){if(!this._open&&!this._floating.hasFallback)return;const s=this._overlayDispose;this._overlayDispose=null,s?.();const i=this.renderRoot.querySelector(".picker");if(i?.hidePopover)try{i.matches(":popover-open")&&i.hidePopover()}catch{}this._open=!1,this._cancelQueuedEmit(),this._activePointerId=null,this._floating.destroy(),t&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_surface(){return this._floating.surface(".picker",this._supportsPopover())}_renderFallback(){const t=rl.styles.cssText;this._floating.renderFallback(this._pickerTemplate(!1),t)}_positionPicker(){if(!this._open)return!1;const t=this._window(),e=this.renderRoot.querySelector(".trigger");let s=this._surface();if(!t||!e?.isConnected||!s?.isConnected)return!1;const i=Wo(t);if(s.style.maxWidth=`${Math.max(0,i.width-16)}px`,s.style.maxHeight=`${Math.max(0,i.height-16)}px`,s.style.visibility="hidden",this._supportsPopover()&&s.showPopover)try{s.matches(":popover-open")||s.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),s=this._surface(),!s?.isConnected)return!1;s.style.maxWidth=`${Math.max(0,i.width-16)}px`,s.style.maxHeight=`${Math.max(0,i.height-16)}px`,s.style.visibility="hidden"}const o=e.getBoundingClientRect(),a=s.getBoundingClientRect();if(!(o.width&&o.height&&a.width&&a.height))return!1;const n=jo(o,a,i);return s.style.left=`${n.left}px`,s.style.top=`${n.top}px`,s.dataset.side=n.side,s.style.visibility="",!0}_labels(){const t=this.pickerLabels||nl;return{title:t.title||nl.title,hue:t.hue||nl.hue,saturation:t.saturation||nl.saturation,value:t.value||nl.value,hex:t.hex||nl.hex,invalidHex:t.invalidHex||nl.invalidHex,confirm:t.confirm||nl.confirm}}_syncFromColor(t,e){const s=sl(Bt(t,"#607d8b"))||"#607d8b",i=il(s);if(!i)return;const o=ol(i);(!e||o.s>1e-4)&&(this._hue=o.h),this._saturation=o.s,this._value=o.v,this._hexDraft=s,this._hexInvalid=!1,this._hexNeedsValidInput=!1,this._lastValidColor=s}_cancelQueuedEmit(t=!1){this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._emitRaf=0,t&&this._syncFromColor(this._lastValidColor,!0)}_queueHsvEmit(){if(this._emitRaf)return;const t=this._window();t?this._emitRaf=t.requestAnimationFrame(()=>{this._emitRaf=0,this._emitHsv()}):this._emitHsv()}_emitHsv(){this._emit(al({h:this._hue,s:this._saturation,v:this._value}),this.opacity)}_setHue(t){this._hue=Math.min(359,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setSaturation(t){this._saturation=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setValue(t){this._value=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setOpacity(t){this._emit(this._lastValidColor,t)}_shiftRangeKey(t,e,s,i,o){if(!t.shiftKey)return;const a="ArrowRight"===t.key||"ArrowUp"===t.key?10:"ArrowLeft"===t.key||"ArrowDown"===t.key?-10:0;a&&(t.preventDefault(),t.stopPropagation(),o(Math.min(i,Math.max(s,e+a))))}_setSvFromPointer(t,e){const s=t.currentTarget.getBoundingClientRect();s.width&&s.height&&(this._saturation=Math.min(100,Math.max(0,(t.clientX-s.left)/s.width*100)),this._value=Math.min(100,Math.max(0,100*(1-(t.clientY-s.top)/s.height))),e?(this._cancelQueuedEmit(),this._emitHsv()):this._queueHsvEmit())}_svPointerDown(t){if(t.preventDefault(),t.stopPropagation(),null===this._activePointerId){this._activePointerId=t.pointerId;try{t.currentTarget.setPointerCapture(t.pointerId)}catch{}this._setSvFromPointer(t,!0)}}_svPointerMove(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!1))}_svPointerUp(t){if(t.pointerId===this._activePointerId){t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!0),this._activePointerId=null;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}}}_svPointerCancel(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._activePointerId=null,this._cancelQueuedEmit(!0))}_svLostPointerCapture(t){t.pointerId===this._activePointerId&&(this._activePointerId=null,this._cancelQueuedEmit(!0))}_hexInput(t){const e=t.target.value;this._hexDraft=e;const s=sl(e),i=s?il(s):null;if(!s||!i)return void(this._hexInvalid=this._hexNeedsValidInput);this._hexNeedsValidInput=!1,this._hexInvalid=!1;const o=ol(i);o.s>1e-4&&(this._hue=o.h),this._saturation=o.s,this._value=o.v,this._emit(s,this.opacity,!0)}_commitHex(){const t=sl(this._hexDraft);if(!t)return this._hexDraft=this._lastValidColor,this._hexInvalid=!0,void(this._hexNeedsValidInput=!0);this._hexDraft=t,this._hexNeedsValidInput?this._hexInvalid=!0:(this._hexInvalid=!1,t!==this._lastValidColor&&this._emit(t,this.opacity))}_confirm(t){t.preventDefault(),t.stopPropagation(),this._commitHex(),this._hexInvalid||this._hexNeedsValidInput?this.updateComplete.then(()=>{this._surface()?.querySelector('input[type="text"]')?.focus()}):this._closePicker(!0)}_hexKeyDown(t){"Enter"===t.key&&(t.preventDefault(),t.stopPropagation(),this._commitHex())}_emit(t,e,s=!1){const i=sl(t)||this._lastValidColor,o=Number.isFinite(e)?e:Number(this.opacity)||0,a=Math.min(1,Math.max(0,o));this.color=i,this.opacity=a,this._lastValidColor=i,s||(this._hexDraft=i),this._hexInvalid=this._hexNeedsValidInput,this.dispatchEvent(new CustomEvent("hp-color-opacity-change",{detail:{color:i,opacity:a},bubbles:!0,composed:!0}))}_pickerTemplate(t){const e=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),s=al({h:this._hue,s:this._saturation,v:this._value}),i=al({h:this._hue,s:100,v:100}),o=this._labels(),a=Math.round(this._hue),n=Math.round(this._saturation),r=Math.round(this._value);return p`
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="picker" popover=${t?"manual":d} role="dialog" aria-label=${o.title}>
|
||
<div class="picker-head">
|
||
<span class="caption">${this.label||o.title}</span>
|
||
<span class="preview" aria-hidden="true"><span style=${`background:${i};opacity:${e/100}`}></span></span>
|
||
</div>
|
||
<div class="sv-field" aria-hidden="true"
|
||
style=${`--hp-picker-hue:${s};--hp-picker-saturation:${this._saturation}%;--hp-picker-value:${100-this._value}%`}
|
||
@pointerdown=${t=>this._svPointerDown(t)}
|
||
@pointermove=${t=>this._svPointerMove(t)}
|
||
@pointerup=${t=>this._svPointerUp(t)}
|
||
@pointercancel=${t=>this._svPointerCancel(t)}
|
||
@lostpointercapture=${t=>this._svLostPointerCapture(t)}>
|
||
<span class="sv-thumb"></span>
|
||
</div>
|
||
<label class="control">
|
||
<span class="control-head"><span class="caption">${o.hue}</span><span class="control-value">${a}°</span></span>
|
||
<input class="hue-range" type="range" min="0" max="359" step="1" .value=${String(a)}
|
||
aria-label=${o.hue} aria-valuetext=${`${a}°`} style=${`--hp-picker-hue:${s}`}
|
||
@input=${t=>this._setHue(Number(t.target.value))}
|
||
@keydown=${t=>this._shiftRangeKey(t,a,0,359,t=>this._setHue(t))} />
|
||
</label>
|
||
<label class="control">
|
||
<span class="control-head"><span class="caption">${o.saturation}</span><span class="control-value">${n}%</span></span>
|
||
<input type="range" min="0" max="100" step="1" .value=${String(n)}
|
||
aria-label=${o.saturation} aria-valuetext=${`${n}%`}
|
||
@input=${t=>this._setSaturation(Number(t.target.value))}
|
||
@keydown=${t=>this._shiftRangeKey(t,n,0,100,t=>this._setSaturation(t))} />
|
||
</label>
|
||
<label class="control">
|
||
<span class="control-head"><span class="caption">${o.value}</span><span class="control-value">${r}%</span></span>
|
||
<input type="range" min="0" max="100" step="1" .value=${String(r)}
|
||
aria-label=${o.value} aria-valuetext=${`${r}%`}
|
||
@input=${t=>this._setValue(Number(t.target.value))}
|
||
@keydown=${t=>this._shiftRangeKey(t,r,0,100,t=>this._setValue(t))} />
|
||
</label>
|
||
<label class="control">
|
||
<span class="caption">${o.hex}</span>
|
||
<input type="text" inputmode="text" autocomplete="off" spellcheck="false"
|
||
.value=${this._hexDraft} aria-label=${o.hex}
|
||
aria-invalid=${this._hexInvalid?"true":"false"}
|
||
aria-describedby=${this._hexInvalid?"hex-error":d}
|
||
@input=${t=>this._hexInput(t)}
|
||
@blur=${()=>this._commitHex()}
|
||
@keydown=${t=>this._hexKeyDown(t)} />
|
||
${this._hexInvalid?p`<span id="hex-error" class="error">${o.invalidHex}</span>`:d}
|
||
</label>
|
||
${this.showOpacity?p`<div class="row">
|
||
<span class="caption">${this.opacityLabel}</span>
|
||
<input type="range" min="0" max="100" step="1" .value=${String(e)}
|
||
aria-label=${this.opacityLabel} aria-valuetext=${`${e}%`}
|
||
@input=${t=>this._setOpacity(Number(t.target.value)/100)}
|
||
@keydown=${t=>this._shiftRangeKey(t,e,0,100,t=>this._setOpacity(t/100))} />
|
||
<input type="number" min="0" max="100" step="1" .value=${String(e)}
|
||
aria-label=${`${this.opacityLabel}, %`}
|
||
@change=${t=>this._setOpacity(Number(t.target.value)/100)} />
|
||
<span class="pct">%</span>
|
||
</div>`:d}
|
||
<button class="confirm" type="button" @click=${t=>this._confirm(t)}>${o.confirm}</button>
|
||
</div>`}render(){const t=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),e=Bt(this.color,"#607d8b"),i=this.showOpacity?`${this.label||"Color"}: ${e}, ${t}%`:`${this.label||"Color"}: ${e}`;return p`
|
||
${this.label&&!this.hideLabel?p`<span class="label">${this.label}</span>`:d}
|
||
<button class="trigger" type="button" .disabled=${this.disabled}
|
||
aria-label=${i} aria-haspopup="dialog" aria-expanded=${this._open?"true":"false"}
|
||
title=${i} @click=${this._toggle}>
|
||
<span class="swatch" style=${`background:${e};opacity:${this.flatSwatch?1:this.showOpacity?t/100:1}`}></span>
|
||
</button>
|
||
${this._open&&!this.disabled&&this._supportsPopover()?this._pickerTemplate(!0):d}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
`}}cl.properties={label:{type:String},opacityLabel:{type:String,attribute:"opacity-label"},color:{type:String},opacity:{type:Number},disabled:{type:Boolean,reflect:!0},showOpacity:{type:Boolean,attribute:"show-opacity"},hideLabel:{type:Boolean,attribute:"hide-label"},flatSwatch:{type:Boolean,attribute:"flat-swatch"},coverSwatch:{type:Boolean,attribute:"cover-swatch"},pickerLabels:{attribute:!1},_open:{state:!0},_hue:{state:!0},_saturation:{state:!0},_value:{state:!0},_hexDraft:{state:!0},_hexInvalid:{state:!0}},cl.styles=At`:host{position:relative;display:inline-flex;align-items:center;gap:6px;min-width:0;}.label{font-size:12px;color:var(--secondary-text-color,#9aa4ad);white-space:nowrap;}.trigger{width:40px;height:40px;flex:none;box-sizing:border-box;padding:3px;border:1px solid var(--divider-color,#666);border-radius:7px;background:linear-gradient(45deg,#b8b8b8 25%,transparent 25%) 0 0 / 10px 10px,linear-gradient(45deg,transparent 75%,#b8b8b8 75%) 0 0 / 10px 10px,linear-gradient(45deg,transparent 75%,#b8b8b8 75%) 5px -5px / 10px 10px,linear-gradient(45deg,#b8b8b8 25%,#eee 25%) 5px 5px / 10px 10px;cursor:pointer;}:host([flat-swatch]) .trigger{background:none;}:host([cover-swatch]){display:block;width:100%;height:100%;}:host([cover-swatch]) .trigger{width:100%;height:100%;padding:0;border:0;border-radius:6px;}:host([cover-swatch]) .swatch{border-radius:6px;box-shadow:none;}:host([cover-swatch]) .trigger:focus-visible{outline-offset:-2px;}:host([data-pointer-hover]) .trigger:hover{border-color:var(--primary-color,#03a9f4);}.trigger[aria-expanded='true']{border-color:var(--primary-color,#03a9f4);outline:none;box-shadow:0 0 0 1px var(--primary-color,#03a9f4);}.trigger:focus-visible{border-color:var(--primary-color,#03a9f4);outline:2px solid var(--primary-color,#03a9f4);outline-offset:2px;}.swatch{display:block;width:100%;height:100%;border-radius:3px;box-shadow:inset 0 0 0 1px rgb(0 0 0 / 0.18);pointer-events:none;}.picker{position:fixed;z-index:2147483647;inset:auto;top:0;left:0;width:min(292px,calc(100vw - 16px));max-height:calc(100vh - 16px);margin:0;box-sizing:border-box;display:grid;gap:10px;padding:12px;overflow:auto;color:var(--primary-text-color,#fff);background:var(--card-background-color,#202126);border:1px solid var(--primary-color,#03a9f4);border-radius:10px;box-shadow:0 10px 28px rgb(0 0 0 / 0.34);}.picker[popover]:not(:popover-open){display:none;}.picker-head,.row,.control-head{display:flex;align-items:center;gap:8px;min-width:0;}.picker-head{justify-content:space-between;}.caption{flex:1;min-width:0;overflow:hidden;color:var(--secondary-text-color,#9aa4ad);font-size:12px;text-overflow:ellipsis;white-space:nowrap;}.preview{width:52px;height:30px;flex:none;box-sizing:border-box;padding:3px;border:1px solid var(--divider-color,#666);border-radius:7px;background:linear-gradient(45deg,#b8b8b8 25%,transparent 25%) 0 0 / 10px 10px,linear-gradient(45deg,transparent 75%,#b8b8b8 75%) 0 0 / 10px 10px,linear-gradient(45deg,transparent 75%,#b8b8b8 75%) 5px -5px / 10px 10px,linear-gradient(45deg,#b8b8b8 25%,#eee 25%) 5px 5px / 10px 10px;}.preview>span{display:block;width:100%;height:100%;border-radius:3px;}.sv-field{position:relative;width:100%;height:132px;overflow:hidden;box-sizing:border-box;border:1px solid var(--divider-color,#666);border-radius:8px;background:linear-gradient(to top,#000,transparent),linear-gradient(to right,#fff,var(--hp-picker-hue,#f00));cursor:crosshair;touch-action:none;user-select:none;}.sv-thumb{position:absolute;left:var(--hp-picker-saturation,0%);top:var(--hp-picker-value,100%);width:14px;height:14px;box-sizing:border-box;border:2px solid #fff;border-radius:50%;box-shadow:0 0 0 1px rgb(0 0 0 / .65),0 1px 3px rgb(0 0 0 / .5);transform:translate(-50%,-50%);pointer-events:none;}.control{display:grid;gap:2px;min-width:0;}.control-value{flex:none;color:var(--secondary-text-color,#9aa4ad);font-size:12px;}input[type='range']{width:auto;height:40px;min-width:0;flex:1;margin:-5px 0;accent-color:var(--primary-color,#03a9f4);touch-action:none;}.hue-range{accent-color:var(--hp-picker-hue,#f00);--hp-picker-hue-track:linear-gradient(to right,#f00 0%,#ff0 16.667%,#0f0 33.333%,#0ff 50%,#00f 66.667%,#f0f 83.333%,#f00 100%);--hp-picker-hue-thumb-shadow:0 0 0 2px var(--card-background-color,#202126),0 0 0 3px var(--primary-text-color,#fff);}.hue-range::-webkit-slider-runnable-track{height:10px;box-sizing:border-box;border:1px solid var(--divider-color,#666);border-radius:999px;background:var(--hp-picker-hue-track);}.hue-range::-moz-range-track{height:10px;box-sizing:border-box;border:1px solid var(--divider-color,#666);border-radius:999px;background:var(--hp-picker-hue-track);}.hue-range::-moz-range-progress{height:10px;border:0;border-radius:999px;background:transparent;}.hue-range::-webkit-slider-thumb{border-radius:50%;box-shadow:var(--hp-picker-hue-thumb-shadow);}.hue-range::-moz-range-thumb{border-radius:50%;box-shadow:var(--hp-picker-hue-thumb-shadow);}input[type='text'],input[type='number']{min-height:40px;box-sizing:border-box;border:1px solid var(--divider-color,#666);border-radius:6px;padding:6px 8px;color:var(--primary-text-color,#fff);background:var(--input-fill-color,transparent);font:inherit;}input[type='text']{width:100%;}input[type='number']{width:50px;flex:none;}input:focus-visible,.sv-field:focus-visible{outline:2px solid var(--primary-color,#03a9f4);outline-offset:1px;}input[aria-invalid='true']{border-color:var(--error-color,#db4437);}.error{color:var(--error-color,#db4437);font-size:11px;line-height:1.25;}.pct{color:var(--secondary-text-color,#9aa4ad);font-size:12px;}.confirm{width:100%;min-height:40px;box-sizing:border-box;border:1px solid var(--primary-color,#03a9f4);border-radius:6px;padding:8px 12px;color:var(--text-primary-color,#fff);background:var(--primary-color,#03a9f4);cursor:pointer;font:inherit;font-weight:600;}.confirm:focus-visible{outline:2px solid var(--primary-text-color,#fff);outline-offset:-4px;}:host([disabled]){opacity:.5;pointer-events:none;}@media (prefers-reduced-motion:reduce){.picker{transition:none !important;}}@media (forced-colors:active){.hue-range::-webkit-slider-runnable-track{border-color:ButtonText;background:Canvas;}.hue-range::-moz-range-track{border-color:ButtonText;background:Canvas;}.hue-range::-webkit-slider-thumb{box-shadow:none;}.hue-range::-moz-range-thumb{box-shadow:none;}.confirm{border-color:ButtonText;color:HighlightText;background:Highlight;forced-color-adjust:none;}}`,customElements.get("hp-color-opacity")||customElements.define("hp-color-opacity",cl);const dl=new WeakMap;function pl(t){const e=function(t){const e=t?.connection||t;return!e||"object"!=typeof e&&"function"!=typeof e?null:e}(t);if(!e)return null;let i=dl.get(e);return i||(i={revision:0,loaded:!1,configEntries:{},manifests:{},listeners:new Set,refs:0},dl.set(e,i)),i}function ul(t){t.revision++;for(const e of[...t.listeners])try{e()}catch{}}function _l(t,e){const i=pl(t);if(!i)return()=>{};i.refs++,i.listeners.add(e),async function(t,e){e.loading||"function"!=typeof t?.callWS?e.loading:e.loaded&&e.loadedAt&&Date.now()-e.loadedAt<3e5||(e.loading=(async()=>{const[i,s]=await Promise.allSettled([t.callWS({type:"config_entries/get"}),t.callWS({type:"manifest/list"})]);"fulfilled"===i.status&&Array.isArray(i.value)&&(e.configEntries=Object.fromEntries(i.value.filter(t=>"string"==typeof t?.entry_id).map(t=>[t.entry_id,t]))),"fulfilled"===s.status&&Array.isArray(s.value)&&(e.manifests=Object.fromEntries(s.value.filter(t=>"string"==typeof t?.domain).map(t=>[t.domain,t]))),e.loaded=!0,e.loadedAt=Date.now(),e.loading=void 0,ul(e)})().catch(()=>{e.loaded=!0,e.loadedAt=Date.now(),e.loading=void 0,ul(e)}),e.loading)}(t,i),async function(t,e){if(e.unsubscribe||e.subscribing)return e.subscribing;const i=t?.connection?.subscribeMessage;"function"==typeof i&&(e.subscribing=(async()=>{try{e.unsubscribe=await i.call(t.connection,t=>{const i=Array.isArray(t)?t:Array.isArray(t?.entries)?t.entries:t?[t]:[];let s=!1;const o={...e.configEntries};for(const t of i){const e=t?.entry||t?.data?.entry||("string"==typeof t?.entry_id?t:null),i=e?.entry_id;if("string"!=typeof i)continue;const a=t?.type||t?.action||t?.data?.action;"removed"===a||"remove"===a?delete o[i]:o[i]=e,s=!0}s&&(e.configEntries=o,ul(e))},{type:"config_entries/subscribe"})}catch{}finally{0===e.refs&&(e.unsubscribe?.(),e.unsubscribe=void 0),e.subscribing=void 0}})(),e.subscribing)}(t,i);let s=!1;return()=>{s||(s=!0,i.listeners.delete(e),i.refs=Math.max(0,i.refs-1),i.refs||(i.unsubscribe?.(),i.unsubscribe=void 0))}}function ml(t){const e=pl(t);return e?{revision:e.revision,loaded:e.loaded,configEntries:e.configEntries,manifests:e.manifests}:{revision:0,loaded:!1,configEntries:{},manifests:{}}}function gl(t,e,i=ml(t),s){const o=i.manifests[e];return function(t,e){if("function"!=typeof t?.localize)return"";try{const i=`component.${e}.title`,s=t.localize(i);return"string"==typeof s&&s!==i?s:""}catch{return""}}(t,e)||String(o?.name||"")||String(s||"")||e.replace(/_/g," ")}function fl(t,e,i,s,o){const a=String(e||"").trim();if(!a)return null;const n=o?s.configEntries[o]:null;return{domain:a,label:gl(t,a,s,n?.title),configEntryId:o,configEntryTitle:n?.title,confidence:i}}function bl(t){const e={"registry-owner":0,"entity-platform":1,"identifier-fallback":2},i=new Set;return t.filter(t=>!!t).sort((t,i)=>e[t.confidence]-e[i.confidence]||t.label.localeCompare(i.label)||t.domain.localeCompare(i.domain)).filter(t=>{const e=`${t.domain}\n${t.configEntryId||""}`;return!i.has(e)&&(i.add(e),!0)})}function vl(t,e,i,s=ml(t)){const o=i.entities?.[e]||t?.entities?.[e];if(!o)return null;const a=o.config_entry_id||void 0,n=a?s.configEntries[a]?.domain:"";return fl(t,o.platform||n,"entity-platform",s,a)}class yl extends Ot{constructor(){super(...arguments),this.deviceName="",this._metadataConnection=null,this._demoUntil=0,this._demoTimer=0,this._demoGeneration=1,this._demoKind=null,this._reducedMotion=!1,this._onMotionChange=t=>{this._reducedMotion=t.matches,this.requestUpdate()},this._startShortDemo=()=>{const t=this.presentation;t&&"icon_ripple"===t.display&&"none"===t.pulse.kind&&(this._demoGeneration++,this._demoKind="short",this._demoUntil=Date.now()+3300,window.clearTimeout(this._demoTimer),this._demoTimer=window.setTimeout(()=>{this._demoUntil=0,this._demoTimer=0,this._demoKind=null,this.requestUpdate()},3330),this.requestUpdate())},this._toggleContinuousDemo=()=>{const t=this.presentation;t&&"icon_ripple"===t.display&&"none"===t.pulse.kind&&("continuous"===this._demoKind?this._clearDemo():(this._clearDemo(),this._demoGeneration++,this._demoKind="continuous",this._demoUntil=Number.POSITIVE_INFINITY),this.requestUpdate())}}connectedCallback(){super.connectedCallback(),this._motionMedia=window.matchMedia?.("(prefers-reduced-motion: reduce)"),this._reducedMotion=!!this._motionMedia?.matches,this._motionMedia?.addEventListener?.("change",this._onMotionChange),this._ensureMetadata()}disconnectedCallback(){this._metadataRelease?.(),this._metadataRelease=void 0,this._metadataConnection=null,this._clearDemo(),this._motionMedia?.removeEventListener?.("change",this._onMotionChange),this._motionMedia=void 0,super.disconnectedCallback()}willUpdate(t){t.has("hass")&&this._ensureMetadata();const e=this.presentation,i=t.get("presentation");t.has("presentation")&&i?.binding!==e?.binding&&this._clearDemo(),e&&this._demoKind&&("icon_ripple"!==e.display||"none"!==e.pulse.kind)&&this._clearDemo()}_ensureMetadata(){const t=this.hass?.connection||null;t&&t!==this._metadataConnection&&(this._metadataRelease?.(),this._metadataConnection=t,this._metadataRelease=_l(this.hass,()=>this.requestUpdate()))}_clearDemo(){window.clearTimeout(this._demoTimer),this._demoTimer=0,this._demoUntil=0,this._demoKind=null}get _lang(){return l(this.hass)}_t(t,e){return Wt(this._lang,t,e)}_providerText(t){return"houseplan"===t.domain?this._t("marker.preview.virtual_provider"):t.label.toLowerCase()===t.domain.toLowerCase()?t.domain:`${t.label} (${t.domain})`}_providers(){return this.presentation&&this.registry?function(t,e,i,s=ml(t)){if("virtual"===e)return[{domain:"houseplan",label:"House Plan",confidence:"registry-owner"}];const o=e.indexOf(":");if(o<1)return[];const a=e.slice(0,o),n=e.slice(o+1);if("entity"===a){const e=vl(t,n,i,s);return e?[e]:[]}if("device"!==a)return[];const r=i.devices?.[n]||t?.devices?.[n];if(!r)return[];const l=[r.config_entry_id,...Array.isArray(r.config_entries)?r.config_entries:[]].filter(t=>"string"==typeof t&&!!t).map(e=>{const i=s.configEntries[e];return fl(t,i?.domain,"registry-owner",s,e)});if(l.some(Boolean))return bl(l);const h=[];for(const[e,o]of Object.entries(i.entities||{}))o?.device_id===n&&null==o?.disabled_by&&h.push(vl(t,e,i,s));return h.some(Boolean)?bl(h):bl((Array.isArray(r.identifiers)?r.identifiers:[]).map(e=>{const i=Array.isArray(e)?e[0]:null;return fl(t,i,"identifier-fallback",s)}))}(this.hass,this.presentation.binding,this.registry,ml(this.hass)):[]}_providerSummary(t){if(!t.length)return this._t("marker.preview.unknown_provider");const e=t.slice(0,2).map(t=>this._providerText(t)),i=t.length-e.length;return e.join(", ")+(i>0?` · ${this._t("marker.preview.more_sources",{n:i})}`:"")}_sourceSummary(t){const e=t.visualSources;return e.length?1===e.length?`${e[0].name} · ${e[0].eid} · ${this._sourceProvider(e[0].eid)}`:2===e.length?e.map(t=>t.name).join(" · "):this._t("marker.preview.multiple_sources",{n:e.length}):this._t("marker.preview.no_source")}_stateSummary(t){if(!t.visualSources.length)return this._t("marker.preview.no_state");if(1===t.visualSources.length)return t.visualSources[0].stateText||this._t("marker.preview.no_state");const e=[...new Set(t.visualSources.map(t=>t.stateText).filter(Boolean))];return 1===e.length?e[0]:this._t("marker.preview.mixed_states")}_reason(t){return this._t(`marker.preview.reason.${t}`)}_sourceProvider(t){if(!this.registry)return this._t("marker.preview.unknown_provider");const e=vl(this.hass,t,this.registry,ml(this.hass));return e?this._providerText(e):this._t("marker.preview.unknown_provider")}render(){const t=this.presentation;if(!t)return d;const e=!!this._demoKind&&this._demoUntil>Date.now()&&"icon_ripple"===t.display&&"none"===t.pulse.kind,i=e?(()=>{const e=Gt(t.pulse,this._demoKind,this._demoGeneration,this._reducedMotion,"short"===this._demoKind?this._demoUntil:null);return{...t,pulse:e,classes:[...t.classes.filter(t=>!t.startsWith("pulse-")),`pulse-${e.kind}`,...e.generation%2==0?["pulse-gen2"]:[]]}})():t,s=this._providers(),o="none"!==t.pulse.kind,a=i.scale*(i.pulse.animated?i.pulse.diameterScale:1);let n=-a/2,r=a/2,l=-a/2,h=a/2;if(i.valueBadge){const t=i.scale*Math.min(4,Math.max(.9,.29*i.valueBadge.text.length+.28)),e=.7*i.scale,s=.6*i.scale;"right"===i.valueBadge.position&&(r=Math.max(r,s+t)),"left"===i.valueBadge.position&&(n=Math.min(n,-s-t)),"top"===i.valueBadge.position&&(l=Math.min(l,-s-e)),"bottom"===i.valueBadge.position&&(h=Math.max(h,s+e))}if(null!=i.lqiText){const t=i.scale*("bottom"===i.valueBadge?.position?1.55:.95);h=Math.max(h,t)}const c=Math.min(1,2.35/Math.max(1,r-n),2.35/Math.max(1,h-l)),u=Math.round(100*c),_=[`left:calc(50% - ${54*((n+r)/2)*c}px)`,`top:calc(50% - ${54*((l+h)/2)*c}px)`,c<1?`transform:scale(${c})`:""].filter(Boolean).join(";"),m=["dev",jt(this.hass),...i.classes,"virtual"===i.binding?"virtual":"",i.haDisabled?"ghost ha-disabled":"",null!=i.valueText?"valonly":""].filter(Boolean).join(" "),g=Ut(i).join(";"),f=e?this._t("continuous"===this._demoKind?"marker.preview.demo_continuous_notice":"marker.preview.demo_short_notice"):this._reason(t.explanation.reason),b=[this.deviceName,this._providerSummary(s),this._stateSummary(t),f,t.valueFullText||"",qt(t.valueBadge),null!=t.lqiText&&t.lqiBand?this._t(`marker.lqi_a11y_${t.lqiBand}`,{value:t.lqiText}):""].filter(Boolean).join(". ");return p`<section class="devicepreview">
|
||
========
|
||
`}}rl.properties={label:{type:String},opacityLabel:{type:String,attribute:"opacity-label"},color:{type:String},opacity:{type:Number},disabled:{type:Boolean,reflect:!0},showOpacity:{type:Boolean,attribute:"show-opacity"},hideLabel:{type:Boolean,attribute:"hide-label"},flatSwatch:{type:Boolean,attribute:"flat-swatch"},coverSwatch:{type:Boolean,attribute:"cover-swatch"},pickerLabels:{attribute:!1},_open:{state:!0},_hue:{state:!0},_saturation:{state:!0},_value:{state:!0},_hexDraft:{state:!0},_hexInvalid:{state:!0}},rl.styles=Et`:host{position:relative;display:inline-flex;align-items:center;gap:6px;min-width:0;}.label{font-size:12px;color:var(--secondary-text-color,#9aa4ad);white-space:nowrap;}.trigger{width:40px;height:40px;flex:none;box-sizing:border-box;padding:3px;border:1px solid var(--divider-color,#666);border-radius:7px;background:linear-gradient(45deg,#b8b8b8 25%,transparent 25%) 0 0 / 10px 10px,linear-gradient(45deg,transparent 75%,#b8b8b8 75%) 0 0 / 10px 10px,linear-gradient(45deg,transparent 75%,#b8b8b8 75%) 5px -5px / 10px 10px,linear-gradient(45deg,#b8b8b8 25%,#eee 25%) 5px 5px / 10px 10px;cursor:pointer;}:host([flat-swatch]) .trigger{background:none;}:host([cover-swatch]){display:block;width:100%;height:100%;}:host([cover-swatch]) .trigger{width:100%;height:100%;padding:0;border:0;border-radius:6px;}:host([cover-swatch]) .swatch{border-radius:6px;box-shadow:none;}:host([cover-swatch]) .trigger:focus-visible{outline-offset:-2px;}:host([data-pointer-hover]) .trigger:hover{border-color:var(--primary-color,#03a9f4);}.trigger[aria-expanded='true']{border-color:var(--primary-color,#03a9f4);outline:none;box-shadow:0 0 0 1px var(--primary-color,#03a9f4);}.trigger:focus-visible{border-color:var(--primary-color,#03a9f4);outline:2px solid var(--primary-color,#03a9f4);outline-offset:2px;}.swatch{display:block;width:100%;height:100%;border-radius:3px;box-shadow:inset 0 0 0 1px rgb(0 0 0 / 0.18);pointer-events:none;}.picker{position:fixed;z-index:2147483647;inset:auto;top:0;left:0;width:min(292px,calc(100vw - 16px));max-height:calc(100vh - 16px);margin:0;box-sizing:border-box;display:grid;gap:10px;padding:12px;overflow:auto;color:var(--primary-text-color,#fff);background:var(--card-background-color,#202126);border:1px solid var(--primary-color,#03a9f4);border-radius:10px;box-shadow:0 10px 28px rgb(0 0 0 / 0.34);}.picker[popover]:not(:popover-open){display:none;}.picker-head,.row,.control-head{display:flex;align-items:center;gap:8px;min-width:0;}.picker-head{justify-content:space-between;}.caption{flex:1;min-width:0;overflow:hidden;color:var(--secondary-text-color,#9aa4ad);font-size:12px;text-overflow:ellipsis;white-space:nowrap;}.preview{width:52px;height:30px;flex:none;box-sizing:border-box;padding:3px;border:1px solid var(--divider-color,#666);border-radius:7px;background:linear-gradient(45deg,#b8b8b8 25%,transparent 25%) 0 0 / 10px 10px,linear-gradient(45deg,transparent 75%,#b8b8b8 75%) 0 0 / 10px 10px,linear-gradient(45deg,transparent 75%,#b8b8b8 75%) 5px -5px / 10px 10px,linear-gradient(45deg,#b8b8b8 25%,#eee 25%) 5px 5px / 10px 10px;}.preview>span{display:block;width:100%;height:100%;border-radius:3px;}.sv-field{position:relative;width:100%;height:132px;overflow:hidden;box-sizing:border-box;border:1px solid var(--divider-color,#666);border-radius:8px;background:linear-gradient(to top,#000,transparent),linear-gradient(to right,#fff,var(--hp-picker-hue,#f00));cursor:crosshair;touch-action:none;user-select:none;}.sv-thumb{position:absolute;left:var(--hp-picker-saturation,0%);top:var(--hp-picker-value,100%);width:14px;height:14px;box-sizing:border-box;border:2px solid #fff;border-radius:50%;box-shadow:0 0 0 1px rgb(0 0 0 / .65),0 1px 3px rgb(0 0 0 / .5);transform:translate(-50%,-50%);pointer-events:none;}.control{display:grid;gap:2px;min-width:0;}.control-value{flex:none;color:var(--secondary-text-color,#9aa4ad);font-size:12px;}input[type='range']{width:auto;height:40px;min-width:0;flex:1;margin:-5px 0;accent-color:var(--primary-color,#03a9f4);touch-action:none;}.hue-range{accent-color:var(--hp-picker-hue,#f00);--hp-picker-hue-track:linear-gradient(to right,#f00 0%,#ff0 16.667%,#0f0 33.333%,#0ff 50%,#00f 66.667%,#f0f 83.333%,#f00 100%);--hp-picker-hue-thumb-shadow:0 0 0 2px var(--card-background-color,#202126),0 0 0 3px var(--primary-text-color,#fff);}.hue-range::-webkit-slider-runnable-track{height:10px;box-sizing:border-box;border:1px solid var(--divider-color,#666);border-radius:999px;background:var(--hp-picker-hue-track);}.hue-range::-moz-range-track{height:10px;box-sizing:border-box;border:1px solid var(--divider-color,#666);border-radius:999px;background:var(--hp-picker-hue-track);}.hue-range::-moz-range-progress{height:10px;border:0;border-radius:999px;background:transparent;}.hue-range::-webkit-slider-thumb{border-radius:50%;box-shadow:var(--hp-picker-hue-thumb-shadow);}.hue-range::-moz-range-thumb{border-radius:50%;box-shadow:var(--hp-picker-hue-thumb-shadow);}input[type='text'],input[type='number']{min-height:40px;box-sizing:border-box;border:1px solid var(--divider-color,#666);border-radius:6px;padding:6px 8px;color:var(--primary-text-color,#fff);background:var(--input-fill-color,transparent);font:inherit;}input[type='text']{width:100%;}input[type='number']{width:50px;flex:none;}input:focus-visible,.sv-field:focus-visible{outline:2px solid var(--primary-color,#03a9f4);outline-offset:1px;}input[aria-invalid='true']{border-color:var(--error-color,#db4437);}.error{color:var(--error-color,#db4437);font-size:11px;line-height:1.25;}.pct{color:var(--secondary-text-color,#9aa4ad);font-size:12px;}.confirm{width:100%;min-height:40px;box-sizing:border-box;border:1px solid var(--primary-color,#03a9f4);border-radius:6px;padding:8px 12px;color:var(--text-primary-color,#fff);background:var(--primary-color,#03a9f4);cursor:pointer;font:inherit;font-weight:600;}.confirm:focus-visible{outline:2px solid var(--primary-text-color,#fff);outline-offset:-4px;}:host([disabled]){opacity:.5;pointer-events:none;}@media (prefers-reduced-motion:reduce){.picker{transition:none !important;}}@media (forced-colors:active){.hue-range::-webkit-slider-runnable-track{border-color:ButtonText;background:Canvas;}.hue-range::-moz-range-track{border-color:ButtonText;background:Canvas;}.hue-range::-webkit-slider-thumb{box-shadow:none;}.hue-range::-moz-range-thumb{box-shadow:none;}.confirm{border-color:ButtonText;color:HighlightText;background:Highlight;forced-color-adjust:none;}}`,customElements.get("hp-color-opacity")||customElements.define("hp-color-opacity",rl);const ll=new WeakMap;function hl(t){const e=function(t){const e=t?.connection||t;return!e||"object"!=typeof e&&"function"!=typeof e?null:e}(t);if(!e)return null;let s=ll.get(e);return s||(s={revision:0,loaded:!1,configEntries:{},manifests:{},listeners:new Set,refs:0},ll.set(e,s)),s}function cl(t){t.revision++;for(const e of[...t.listeners])try{e()}catch{}}function dl(t,e){const s=hl(t);if(!s)return()=>{};s.refs++,s.listeners.add(e),async function(t,e){e.loading||"function"!=typeof t?.callWS?e.loading:e.loaded&&e.loadedAt&&Date.now()-e.loadedAt<3e5||(e.loading=(async()=>{const[s,i]=await Promise.allSettled([t.callWS({type:"config_entries/get"}),t.callWS({type:"manifest/list"})]);"fulfilled"===s.status&&Array.isArray(s.value)&&(e.configEntries=Object.fromEntries(s.value.filter(t=>"string"==typeof t?.entry_id).map(t=>[t.entry_id,t]))),"fulfilled"===i.status&&Array.isArray(i.value)&&(e.manifests=Object.fromEntries(i.value.filter(t=>"string"==typeof t?.domain).map(t=>[t.domain,t]))),e.loaded=!0,e.loadedAt=Date.now(),e.loading=void 0,cl(e)})().catch(()=>{e.loaded=!0,e.loadedAt=Date.now(),e.loading=void 0,cl(e)}),e.loading)}(t,s),async function(t,e){if(e.unsubscribe||e.subscribing)return e.subscribing;const s=t?.connection?.subscribeMessage;"function"==typeof s&&(e.subscribing=(async()=>{try{e.unsubscribe=await s.call(t.connection,t=>{const s=Array.isArray(t)?t:Array.isArray(t?.entries)?t.entries:t?[t]:[];let i=!1;const o={...e.configEntries};for(const t of s){const e=t?.entry||t?.data?.entry||("string"==typeof t?.entry_id?t:null),s=e?.entry_id;if("string"!=typeof s)continue;const a=t?.type||t?.action||t?.data?.action;"removed"===a||"remove"===a?delete o[s]:o[s]=e,i=!0}i&&(e.configEntries=o,cl(e))},{type:"config_entries/subscribe"})}catch{}finally{0===e.refs&&(e.unsubscribe?.(),e.unsubscribe=void 0),e.subscribing=void 0}})(),e.subscribing)}(t,s);let i=!1;return()=>{i||(i=!0,s.listeners.delete(e),s.refs=Math.max(0,s.refs-1),s.refs||(s.unsubscribe?.(),s.unsubscribe=void 0))}}function pl(t){const e=hl(t);return e?{revision:e.revision,loaded:e.loaded,configEntries:e.configEntries,manifests:e.manifests}:{revision:0,loaded:!1,configEntries:{},manifests:{}}}function ul(t,e,s=pl(t),i){const o=s.manifests[e];return function(t,e){if("function"!=typeof t?.localize)return"";try{const s=`component.${e}.title`,i=t.localize(s);return"string"==typeof i&&i!==s?i:""}catch{return""}}(t,e)||String(o?.name||"")||String(i||"")||e.replace(/_/g," ")}function _l(t,e,s,i,o){const a=String(e||"").trim();if(!a)return null;const n=o?i.configEntries[o]:null;return{domain:a,label:ul(t,a,i,n?.title),configEntryId:o,configEntryTitle:n?.title,confidence:s}}function ml(t){const e={"registry-owner":0,"entity-platform":1,"identifier-fallback":2},s=new Set;return t.filter(t=>!!t).sort((t,s)=>e[t.confidence]-e[s.confidence]||t.label.localeCompare(s.label)||t.domain.localeCompare(s.domain)).filter(t=>{const e=`${t.domain}\n${t.configEntryId||""}`;return!s.has(e)&&(s.add(e),!0)})}function gl(t,e,s,i=pl(t)){const o=s.entities?.[e]||t?.entities?.[e];if(!o)return null;const a=o.config_entry_id||void 0,n=a?i.configEntries[a]?.domain:"";return _l(t,o.platform||n,"entity-platform",i,a)}class fl extends Ot{constructor(){super(...arguments),this.deviceName="",this._metadataConnection=null,this._demoUntil=0,this._demoTimer=0,this._demoGeneration=1,this._demoKind=null,this._reducedMotion=!1,this._onMotionChange=t=>{this._reducedMotion=t.matches,this.requestUpdate()},this._startShortDemo=()=>{const t=this.presentation;t&&"icon_ripple"===t.display&&"none"===t.pulse.kind&&(this._demoGeneration++,this._demoKind="short",this._demoUntil=Date.now()+3300,window.clearTimeout(this._demoTimer),this._demoTimer=window.setTimeout(()=>{this._demoUntil=0,this._demoTimer=0,this._demoKind=null,this.requestUpdate()},3330),this.requestUpdate())},this._toggleContinuousDemo=()=>{const t=this.presentation;t&&"icon_ripple"===t.display&&"none"===t.pulse.kind&&("continuous"===this._demoKind?this._clearDemo():(this._clearDemo(),this._demoGeneration++,this._demoKind="continuous",this._demoUntil=Number.POSITIVE_INFINITY),this.requestUpdate())}}connectedCallback(){super.connectedCallback(),this._motionMedia=window.matchMedia?.("(prefers-reduced-motion: reduce)"),this._reducedMotion=!!this._motionMedia?.matches,this._motionMedia?.addEventListener?.("change",this._onMotionChange),this._ensureMetadata()}disconnectedCallback(){this._metadataRelease?.(),this._metadataRelease=void 0,this._metadataConnection=null,this._clearDemo(),this._motionMedia?.removeEventListener?.("change",this._onMotionChange),this._motionMedia=void 0,super.disconnectedCallback()}willUpdate(t){t.has("hass")&&this._ensureMetadata();const e=this.presentation,s=t.get("presentation");t.has("presentation")&&s?.binding!==e?.binding&&this._clearDemo(),e&&this._demoKind&&("icon_ripple"!==e.display||"none"!==e.pulse.kind)&&this._clearDemo()}_ensureMetadata(){const t=this.hass?.connection||null;t&&t!==this._metadataConnection&&(this._metadataRelease?.(),this._metadataConnection=t,this._metadataRelease=dl(this.hass,()=>this.requestUpdate()))}_clearDemo(){window.clearTimeout(this._demoTimer),this._demoTimer=0,this._demoUntil=0,this._demoKind=null}get _lang(){return l(this.hass)}_t(t,e){return Wt(this._lang,t,e)}_providerText(t){return"houseplan"===t.domain?this._t("marker.preview.virtual_provider"):t.label.toLowerCase()===t.domain.toLowerCase()?t.domain:`${t.label} (${t.domain})`}_providers(){return this.presentation&&this.registry?function(t,e,s,i=pl(t)){if("virtual"===e)return[{domain:"houseplan",label:"House Plan",confidence:"registry-owner"}];const o=e.indexOf(":");if(o<1)return[];const a=e.slice(0,o),n=e.slice(o+1);if("entity"===a){const e=gl(t,n,s,i);return e?[e]:[]}if("device"!==a)return[];const r=s.devices?.[n]||t?.devices?.[n];if(!r)return[];const l=[r.config_entry_id,...Array.isArray(r.config_entries)?r.config_entries:[]].filter(t=>"string"==typeof t&&!!t).map(e=>{const s=i.configEntries[e];return _l(t,s?.domain,"registry-owner",i,e)});if(l.some(Boolean))return ml(l);const h=[];for(const[e,o]of Object.entries(s.entities||{}))o?.device_id===n&&null==o?.disabled_by&&h.push(gl(t,e,s,i));return h.some(Boolean)?ml(h):ml((Array.isArray(r.identifiers)?r.identifiers:[]).map(e=>{const s=Array.isArray(e)?e[0]:null;return _l(t,s,"identifier-fallback",i)}))}(this.hass,this.presentation.binding,this.registry,pl(this.hass)):[]}_providerSummary(t){if(!t.length)return this._t("marker.preview.unknown_provider");const e=t.slice(0,2).map(t=>this._providerText(t)),s=t.length-e.length;return e.join(", ")+(s>0?` · ${this._t("marker.preview.more_sources",{n:s})}`:"")}_sourceSummary(t){const e=t.visualSources;return e.length?1===e.length?`${e[0].name} · ${e[0].eid} · ${this._sourceProvider(e[0].eid)}`:2===e.length?e.map(t=>t.name).join(" · "):this._t("marker.preview.multiple_sources",{n:e.length}):this._t("marker.preview.no_source")}_stateSummary(t){if(!t.visualSources.length)return this._t("marker.preview.no_state");if(1===t.visualSources.length)return t.visualSources[0].stateText||this._t("marker.preview.no_state");const e=[...new Set(t.visualSources.map(t=>t.stateText).filter(Boolean))];return 1===e.length?e[0]:this._t("marker.preview.mixed_states")}_reason(t){return this._t(`marker.preview.reason.${t}`)}_sourceProvider(t){if(!this.registry)return this._t("marker.preview.unknown_provider");const e=gl(this.hass,t,this.registry,pl(this.hass));return e?this._providerText(e):this._t("marker.preview.unknown_provider")}render(){const t=this.presentation;if(!t)return d;const e=!!this._demoKind&&this._demoUntil>Date.now()&&"icon_ripple"===t.display&&"none"===t.pulse.kind,s=e?(()=>{const e=jt(t.pulse,this._demoKind,this._demoGeneration,this._reducedMotion,"short"===this._demoKind?this._demoUntil:null);return{...t,pulse:e,classes:[...t.classes.filter(t=>!t.startsWith("pulse-")),`pulse-${e.kind}`,...e.generation%2==0?["pulse-gen2"]:[]]}})():t,i=this._providers(),o="none"!==t.pulse.kind,a=s.scale*(s.pulse.animated?s.pulse.diameterScale:1);let n=-a/2,r=a/2,l=-a/2,h=a/2;if(s.valueBadge){const t=s.scale*Math.min(4,Math.max(.9,.29*s.valueBadge.text.length+.28)),e=.7*s.scale,i=.6*s.scale;"right"===s.valueBadge.position&&(r=Math.max(r,i+t)),"left"===s.valueBadge.position&&(n=Math.min(n,-i-t)),"top"===s.valueBadge.position&&(l=Math.min(l,-i-e)),"bottom"===s.valueBadge.position&&(h=Math.max(h,i+e))}if(null!=s.lqiText){const t=s.scale*("bottom"===s.valueBadge?.position?1.55:.95);h=Math.max(h,t)}const c=Math.min(1,2.35/Math.max(1,r-n),2.35/Math.max(1,h-l)),u=Math.round(100*c),_=[`left:calc(50% - ${54*((n+r)/2)*c}px)`,`top:calc(50% - ${54*((l+h)/2)*c}px)`,c<1?`transform:scale(${c})`:""].filter(Boolean).join(";"),m=["dev",Gt(this.hass),...s.classes,"virtual"===s.binding?"virtual":"",s.haDisabled?"ghost ha-disabled":"",null!=s.valueText?"valonly":""].filter(Boolean).join(" "),g=qt(s).join(";"),f=e?this._t("continuous"===this._demoKind?"marker.preview.demo_continuous_notice":"marker.preview.demo_short_notice"):this._reason(t.explanation.reason),b=[this.deviceName,this._providerSummary(i),this._stateSummary(t),f,t.valueFullText||"",Ut(t.valueBadge),null!=t.lqiText&&t.lqiBand?this._t(`marker.lqi_a11y_${t.lqiBand}`,{value:t.lqiText}):""].filter(Boolean).join(". ");return p`<section class="devicepreview">
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="previewhead">
|
||
<strong>${this._t("marker.preview.title")}</strong>
|
||
<span class="previewbadge ${e?"example":""}">
|
||
${this._t(e?"marker.preview.example":"marker.preview.actual")}
|
||
</span>
|
||
</div>
|
||
<div class="previewgrid">
|
||
<div class="previewstage" role="img" aria-label=${b}>
|
||
<div class="previewfit" style=${_}>
|
||
<div class=${m} style=${g}>
|
||
${Kt(i,{disabledTitle:this._reason("ha_disabled")})}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="previewfacts" aria-live="polite">
|
||
<div><span>${this._t("marker.preview.integration")}</span><b>${this._providerSummary(s)}</b></div>
|
||
<div><span>${this._t("marker.preview.source")}</span><b>${this._sourceSummary(t)}</b></div>
|
||
<div><span>${this._t("marker.preview.current_state")}</span><b>${this._stateSummary(t)}</b></div>
|
||
<div><span>${this._t("marker.preview.result")}</span><b>${f}</b></div>
|
||
${t.fallbackReason?p`<p class="previewnotice">${this._reason(t.fallbackReason)}</p>`:d}
|
||
${t.explanation.notices.map(t=>p`<p class="previewnotice">${this._reason(t)}</p>`)}
|
||
${c<1?p`<p class="previewnotice">${this._t("marker.preview.scaled",{n:u})}</p>`:d}
|
||
${e&&this._reducedMotion?p`<p class="previewnotice">${this._t("marker.preview.reduced_motion")}</p>`:d}
|
||
</div>
|
||
</div>
|
||
${t.visualSources.length||t.criticalSources.length?p`<details class="previewdetails">
|
||
<summary>${this._t("marker.preview.details")}</summary>
|
||
<div class="previewtable">
|
||
${[...t.visualSources,...t.criticalSources].map(t=>p`
|
||
<div class="previewsource">
|
||
<b>${t.name}</b><code>${t.eid}</code>
|
||
<span>${t.stateText||t.state}</span>
|
||
<span>${this._sourceProvider(t.eid)}</span>
|
||
</div>`)}
|
||
</div>
|
||
</details>`:d}
|
||
${"icon_ripple"===t.display?p`<div class="previewdemos">
|
||
<button class="previewdemo" type="button"
|
||
?disabled=${o||"continuous"===this._demoKind}
|
||
title=${o?this._t("marker.preview.demo_already_visible"):""}
|
||
@click=${this._startShortDemo}>
|
||
<ha-icon icon="mdi:motion-play-outline"></ha-icon>
|
||
${this._t("marker.preview.demo_short")}
|
||
</button>
|
||
<button class="previewdemo" type="button"
|
||
?disabled=${o}
|
||
title=${o?this._t("marker.preview.demo_already_visible"):""}
|
||
@click=${this._toggleContinuousDemo}>
|
||
<ha-icon icon=${"continuous"===this._demoKind?"mdi:stop-circle-outline":"mdi:repeat"}></ha-icon>
|
||
${this._t("continuous"===this._demoKind?"marker.preview.stop_continuous":"marker.preview.demo_continuous")}
|
||
</button>
|
||
</div>`:d}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</section>`}}yl.properties={hass:{attribute:!1},presentation:{attribute:!1},registry:{attribute:!1},deviceName:{attribute:!1}},yl.styles=[Ht,At`:host{display:block;min-width:0;}.devicepreview{margin:4px 0 14px;padding:14px;border:1px solid var(--divider-color,rgba(127,127,127,0.28));border-radius:14px;background:color-mix(in srgb,var(--card-background-color,#20232b) 92%,var(--primary-color,#03a9f4));color:var(--primary-text-color,#fff);overflow:hidden;}.previewhead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px;}.previewbadge{padding:3px 9px;border-radius:999px;color:var(--secondary-text-color,#9aa0aa);background:color-mix(in srgb,var(--secondary-text-color,#9aa0aa) 12%,transparent);font-size:12px;font-weight:700;}.previewbadge.example{color:var(--warning-color,#ffb300);}.previewgrid{display:grid;grid-template-columns:minmax(170px,0.8fr) minmax(240px,1.2fr);gap:16px;align-items:stretch;}.previewstage{position:relative;min-height:168px;border-radius:12px;background:var(--secondary-background-color,rgba(0,0,0,0.16));overflow:hidden;pointer-events:none;container-type:inline-size;--icon-size:54px;--device-base-size:48.6px;}.previewfit{position:absolute;left:50%;top:50%;transform-origin:center;}.previewstage .dev{left:0;top:0;cursor:default;}:host([data-pointer-hover]) .previewstage .dev:hover{z-index:2;}.previewfacts{min-width:0;display:grid;align-content:start;gap:8px;}.previewfacts>div{display:grid;grid-template-columns:minmax(115px,0.8fr) minmax(0,1.3fr);gap:8px;}.previewfacts span{color:var(--secondary-text-color,#9aa0aa);}.previewfacts b{min-width:0;overflow-wrap:anywhere;}.previewnotice{margin:2px 0 0;color:var(--secondary-text-color,#9aa0aa);font-size:13px;}.previewdetails{margin-top:12px;}.previewdetails summary{cursor:pointer;color:var(--secondary-text-color,#9aa0aa);}.previewtable{display:grid;gap:8px;margin-top:9px;}.previewsource{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:3px 10px;font-size:13px;}.previewsource>*{min-width:0;overflow-wrap:anywhere;}.previewsource code{color:var(--secondary-text-color,#9aa0aa);}.previewdemo{min-height:40px;display:inline-flex;align-items:center;gap:8px;padding:8px 12px;border:1px solid var(--divider-color,rgba(127,127,127,0.35));border-radius:10px;background:transparent;color:inherit;cursor:pointer;}.previewdemos{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px;}.previewdemo:focus-visible{outline:2px solid var(--primary-color,#03a9f4);outline-offset:2px;}.previewdemo:disabled{opacity:0.5;cursor:not-allowed;}@media (max-width:640px){.previewgrid{grid-template-columns:minmax(0,1fr);}.previewstage{min-height:142px;}.previewfacts>div{grid-template-columns:minmax(0,1fr);gap:2px;}}`],customElements.get("hp-device-preview")||customElements.define("hp-device-preview",yl);const wl={revision:0,topologies:[],states:{}};class $l extends Ot{constructor(){super(...arguments),this.value={enabled:!1,z2mBaseTopics:[]},this.savedEnabled=!1,this.devices=[],this._runtime=null,this._snapshot=wl,this._topicText="zigbee2mqtt",this._invalidTopic=!1,this.embedded=!1}disconnectedCallback(){this._release?.(),this._release=void 0,super.disconnectedCallback()}updated(t){t.has("hass")&&(this._release?.(),this._release=void 0,this._runtime=null,this._snapshot=wl),this.savedEnabled&&this._admin&&this._ensureRuntime()}willUpdate(t){t.has("value")&&(this._topicText=(this.value.z2mBaseTopics.length?this.value.z2mBaseTopics:["zigbee2mqtt"]).join("\n"),this._invalidTopic=!1)}get _admin(){return!0===this.hass?.user?.is_admin}_t(t,e){return sa(l(this.hass),t,e)}_help(){const t=l(this.hass);return ia(t,"help")&&ia(t,"help_aria")?p`<hp-help .text=${this._t("help")}
|
||
.ariaLabel=${this._t("help_aria")}></hp-help>`:d}async _ensureRuntime(){return this._runtime||(this._runtime=await import("./zigbee-topology-runtime-BID93LUv.js"),this._snapshot=this._runtime.zigbeeTopologyRuntimeSnapshot(this.hass),this._release=this._runtime.subscribeZigbeeTopology(this.hass,()=>{this._snapshot=this._runtime.zigbeeTopologyRuntimeSnapshot(this.hass),this.requestUpdate()}),this.requestUpdate()),this._runtime}_emit(t){this._admin&&this.dispatchEvent(new CustomEvent("hp-topology-settings-change",{detail:t,bubbles:!0,composed:!0}))}_topics(){return this.value.z2mBaseTopics.length?this.value.z2mBaseTopics:["zigbee2mqtt"]}_editTopics(t){this._topicText=t;const e=t.split(/[\r\n,]+/).map(t=>t.trim()).filter(Boolean),i=e.map(Vt).filter(Boolean);this._invalidTopic=i.length!==e.length,this._invalidTopic?this.requestUpdate():this._emit({...this.value,z2mBaseTopics:[...new Set(i)].slice(0,8)})}_status(t){const e=this._snapshot.states[t];if(!e)return this._t("status_idle");if("loading"===e.phase)return this._t("status_loading");if("error"===e.phase)return this._t(`error_${e.error||"provider"}`);if("ready"!==e.phase||!e.obtainedAt)return this._t("status_idle");const i=new Date(e.obtainedAt).toLocaleTimeString(l(this.hass),{hour:"2-digit",minute:"2-digit"}),s=this._snapshot.topologies.find(e=>"zha"===t?"zha"===e.provider:`z2m:${e.instanceId}`===t),o=!!s&&!!this.registry&&oa(s,this.devices,this.registry).warnings.length>0;return e.partial||o?this._t("status_partial",{time:i}):s&&!s.links.length?this._t("status_no_links",{time:i}):this._t(Date.now()-e.obtainedAt>aa?"status_stale":"status_ready",{time:i})}_busy(t){return"loading"===this._snapshot.states[t]?.phase}async _readZha(){this.savedEnabled&&this._admin&&(await this._ensureRuntime()).readZhaTopology(this.hass)}async _refreshZ2m(t){this.savedEnabled&&this._admin&&(await this._ensureRuntime()).refreshZ2mTopology(this.hass,t)}render(){if(this.embedded)return this._renderEmbedded();const t=this._admin,e=this.value.enabled,i=t&&this.savedEnabled,s=this._topics();return p`
|
||
========
|
||
</section>`}}fl.properties={hass:{attribute:!1},presentation:{attribute:!1},registry:{attribute:!1},deviceName:{attribute:!1}},fl.styles=[Ht,Et`:host{display:block;min-width:0;}.devicepreview{margin:4px 0 14px;padding:14px;border:1px solid var(--divider-color,rgba(127,127,127,0.28));border-radius:14px;background:color-mix(in srgb,var(--card-background-color,#20232b) 92%,var(--primary-color,#03a9f4));color:var(--primary-text-color,#fff);overflow:hidden;}.previewhead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px;}.previewbadge{padding:3px 9px;border-radius:999px;color:var(--secondary-text-color,#9aa0aa);background:color-mix(in srgb,var(--secondary-text-color,#9aa0aa) 12%,transparent);font-size:12px;font-weight:700;}.previewbadge.example{color:var(--warning-color,#ffb300);}.previewgrid{display:grid;grid-template-columns:minmax(170px,0.8fr) minmax(240px,1.2fr);gap:16px;align-items:stretch;}.previewstage{position:relative;min-height:168px;border-radius:12px;background:var(--secondary-background-color,rgba(0,0,0,0.16));overflow:hidden;pointer-events:none;container-type:inline-size;--icon-size:54px;--device-base-size:48.6px;}.previewfit{position:absolute;left:50%;top:50%;transform-origin:center;}.previewstage .dev{left:0;top:0;cursor:default;}:host([data-pointer-hover]) .previewstage .dev:hover{z-index:2;}.previewfacts{min-width:0;display:grid;align-content:start;gap:8px;}.previewfacts>div{display:grid;grid-template-columns:minmax(115px,0.8fr) minmax(0,1.3fr);gap:8px;}.previewfacts span{color:var(--secondary-text-color,#9aa0aa);}.previewfacts b{min-width:0;overflow-wrap:anywhere;}.previewnotice{margin:2px 0 0;color:var(--secondary-text-color,#9aa0aa);font-size:13px;}.previewdetails{margin-top:12px;}.previewdetails summary{cursor:pointer;color:var(--secondary-text-color,#9aa0aa);}.previewtable{display:grid;gap:8px;margin-top:9px;}.previewsource{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:3px 10px;font-size:13px;}.previewsource>*{min-width:0;overflow-wrap:anywhere;}.previewsource code{color:var(--secondary-text-color,#9aa0aa);}.previewdemo{min-height:40px;display:inline-flex;align-items:center;gap:8px;padding:8px 12px;border:1px solid var(--divider-color,rgba(127,127,127,0.35));border-radius:10px;background:transparent;color:inherit;cursor:pointer;}.previewdemos{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px;}.previewdemo:focus-visible{outline:2px solid var(--primary-color,#03a9f4);outline-offset:2px;}.previewdemo:disabled{opacity:0.5;cursor:not-allowed;}@media (max-width:640px){.previewgrid{grid-template-columns:minmax(0,1fr);}.previewstage{min-height:142px;}.previewfacts>div{grid-template-columns:minmax(0,1fr);gap:2px;}}`],customElements.get("hp-device-preview")||customElements.define("hp-device-preview",fl);const bl={revision:0,topologies:[],states:{}};class vl extends Ot{constructor(){super(...arguments),this.value={enabled:!1,z2mBaseTopics:[]},this.savedEnabled=!1,this.devices=[],this._runtime=null,this._snapshot=bl,this._topicText="zigbee2mqtt",this._invalidTopic=!1,this.embedded=!1}disconnectedCallback(){this._release?.(),this._release=void 0,super.disconnectedCallback()}updated(t){t.has("hass")&&(this._release?.(),this._release=void 0,this._runtime=null,this._snapshot=bl),this.savedEnabled&&this._admin&&this._ensureRuntime()}willUpdate(t){t.has("value")&&(this._topicText=(this.value.z2mBaseTopics.length?this.value.z2mBaseTopics:["zigbee2mqtt"]).join("\n"),this._invalidTopic=!1)}get _admin(){return!0===this.hass?.user?.is_admin}_t(t,e){return sa(l(this.hass),t,e)}_help(){const t=l(this.hass);return ea(t,"help")&&ea(t,"help_aria")?p`<hp-help .text=${this._t("help")}
|
||
.ariaLabel=${this._t("help_aria")}></hp-help>`:d}async _ensureRuntime(){return this._runtime||(this._runtime=await import("./zigbee-topology-runtime-srlatNZm.js"),this._snapshot=this._runtime.zigbeeTopologyRuntimeSnapshot(this.hass),this._release=this._runtime.subscribeZigbeeTopology(this.hass,()=>{this._snapshot=this._runtime.zigbeeTopologyRuntimeSnapshot(this.hass),this.requestUpdate()}),this.requestUpdate()),this._runtime}_emit(t){this._admin&&this.dispatchEvent(new CustomEvent("hp-topology-settings-change",{detail:t,bubbles:!0,composed:!0}))}_topics(){return this.value.z2mBaseTopics.length?this.value.z2mBaseTopics:["zigbee2mqtt"]}_editTopics(t){this._topicText=t;const e=t.split(/[\r\n,]+/).map(t=>t.trim()).filter(Boolean),s=e.map(Vt).filter(Boolean);this._invalidTopic=s.length!==e.length,this._invalidTopic?this.requestUpdate():this._emit({...this.value,z2mBaseTopics:[...new Set(s)].slice(0,8)})}_status(t){const e=this._snapshot.states[t];if(!e)return this._t("status_idle");if("loading"===e.phase)return this._t("status_loading");if("error"===e.phase)return this._t(`error_${e.error||"provider"}`);if("ready"!==e.phase||!e.obtainedAt)return this._t("status_idle");const s=new Date(e.obtainedAt).toLocaleTimeString(l(this.hass),{hour:"2-digit",minute:"2-digit"}),i=this._snapshot.topologies.find(e=>"zha"===t?"zha"===e.provider:`z2m:${e.instanceId}`===t),o=!!i&&!!this.registry&&ia(i,this.devices,this.registry).warnings.length>0;return e.partial||o?this._t("status_partial",{time:s}):i&&!i.links.length?this._t("status_no_links",{time:s}):this._t(Date.now()-e.obtainedAt>oa?"status_stale":"status_ready",{time:s})}_busy(t){return"loading"===this._snapshot.states[t]?.phase}async _readZha(){this.savedEnabled&&this._admin&&(await this._ensureRuntime()).readZhaTopology(this.hass)}async _refreshZ2m(t){this.savedEnabled&&this._admin&&(await this._ensureRuntime()).refreshZ2mTopology(this.hass,t)}render(){if(this.embedded)return this._renderEmbedded();const t=this._admin,e=this.value.enabled,s=t&&this.savedEnabled,i=this._topics();return p`
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="section">${this._t("title")}${this._help()}</div>
|
||
<label class="toggle">
|
||
${customElements.get("ha-switch")?p`<ha-switch .checked=${e} .disabled=${!t}
|
||
@change=${t=>this._emit({...this.value,enabled:!!t.target.checked})}></ha-switch>`:p`<input type="checkbox" .checked=${e} ?disabled=${!t}
|
||
@change=${t=>this._emit({...this.value,enabled:t.target.checked})} />`}
|
||
<span>${this._t("toggle")}</span>
|
||
</label>
|
||
<div class="hint">${this._t("hint")}</div>
|
||
${t?d:p`<div class="hint">${this._t("admin_only")}</div>`}
|
||
${e?p`<div class="providers">
|
||
${this.savedEnabled?d:p`<div class="hint">${this._t("save_first")}</div>`}
|
||
<div class="provider">
|
||
<div class="provider-title">${this._t("zha")}</div>
|
||
<div class="hint">${this._t("zha_hint")}</div>
|
||
<div class="actions">
|
||
<button ?disabled=${!i||this._busy("zha")} @click=${this._readZha}>
|
||
<ha-icon icon="mdi:access-point-network"></ha-icon>${this._t("zha_read")}
|
||
</button>
|
||
<span class="status">${this._status("zha")}</span>
|
||
</div>
|
||
</div>
|
||
<div class="provider">
|
||
<div class="provider-title">${this._t("z2m")}</div>
|
||
<label class="hint" for="z2m-topics">${this._t("z2m_topics")}</label>
|
||
<textarea id="z2m-topics" ?disabled=${!t}
|
||
.value=${this._topicText} @input=${t=>this._editTopics(t.target.value)}></textarea>
|
||
${this._invalidTopic?p`<div class="warning">${this._t("error_invalid_topic")}</div>`:d}
|
||
<div class="warning">${this._t("z2m_warning")}</div>
|
||
${s.map(t=>p`<div class="actions">
|
||
<button ?disabled=${!i||this._invalidTopic||this._busy(`z2m:${t}`)}
|
||
@click=${()=>this._refreshZ2m(t)}>
|
||
<ha-icon icon="mdi:refresh"></ha-icon>${this._t("z2m_update")} · ${t}
|
||
</button>
|
||
<span class="status">${this._status(`z2m:${t}`)}</span>
|
||
</div>`)}
|
||
</div>
|
||
</div>`:d}
|
||
`}_renderEmbedded(){wo(this);const t=this._admin,e=this.value.enabled,i=t&&this.savedEnabled,s=this._topics();return p`
|
||
<label class="hpf-toggle">
|
||
<span class="hpf-toggle-icon" aria-hidden="true"><ha-icon icon="mdi:zigbee"></ha-icon></span>
|
||
<span class="hpf-toggle-title"><span>${this._t("toggle")}</span></span>
|
||
<span class="hpf-toggle-caption">${this._t("hint")}</span>
|
||
<input type="checkbox" .checked=${e} ?disabled=${!t} aria-label=${this._t("toggle")}
|
||
@change=${t=>this._emit({...this.value,enabled:t.target.checked})} />
|
||
</label>
|
||
${t?d:p`<p class="hpf-hint">${this._t("admin_only")}</p>`}
|
||
${e?p`
|
||
${this.savedEnabled?d:p`<div class="hpf-callout"><ha-icon icon="mdi:information-outline"></ha-icon><p>${this._t("save_first")}</p></div>`}
|
||
<div class="hpf-sub"><h4>${this._t("zha")}</h4></div>
|
||
<p class="hpf-hint">${this._t("zha_hint")}</p>
|
||
<div class="hpf-actions">
|
||
<button class="btn ghost" ?disabled=${!i||this._busy("zha")} @click=${this._readZha}>
|
||
<ha-icon icon="mdi:access-point-network"></ha-icon>${this._t("zha_read")}
|
||
</button>
|
||
<span class="hpf-hint">${this._status("zha")}</span>
|
||
</div>
|
||
<div class="hpf-sub"><h4>${this._t("z2m")}</h4></div>
|
||
<div class="hpf-field">
|
||
<span class="hpf-label hpf-labelrow"><label for="z2m-topics">${this._t("z2m_topics")}</label></span>
|
||
<textarea id="z2m-topics" class="hpf-input" rows="2" spellcheck="false" ?disabled=${!t}
|
||
aria-invalid=${this._invalidTopic?"true":d}
|
||
.value=${this._topicText} @input=${t=>this._editTopics(t.target.value)}></textarea>
|
||
${this._invalidTopic?p`<p class="hpf-error" role="alert">${this._t("error_invalid_topic")}</p>`:d}
|
||
</div>
|
||
<div class="hpf-callout hpf-warning"><ha-icon icon="mdi:alert-outline"></ha-icon><p>${this._t("z2m_warning")}</p></div>
|
||
${s.map(t=>p`<div class="hpf-actions">
|
||
<button class="btn ghost" ?disabled=${!i||this._invalidTopic||this._busy(`z2m:${t}`)}
|
||
@click=${()=>this._refreshZ2m(t)}>
|
||
<ha-icon icon="mdi:refresh"></ha-icon>${this._t("z2m_update")} · ${t}
|
||
</button>
|
||
<span class="hpf-hint">${this._status(`z2m:${t}`)}</span>
|
||
</div>`)}`:d}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
`}}$l.properties={hass:{attribute:!1},value:{attribute:!1},embedded:{type:Boolean,reflect:!0},savedEnabled:{type:Boolean,attribute:"saved-enabled"},devices:{attribute:!1},registry:{attribute:!1}},$l.styles=At`:host{display:block;color:inherit;font:inherit;}.section{margin-top:18px;font-weight:700;display:flex;align-items:center;gap:2px;}.toggle{display:flex;align-items:center;gap:10px;margin-top:10px;}.hint,.status{color:var(--secondary-text-color,#9aa0aa);font-size:12px;line-height:1.45;}.hint{margin-top:6px;}.providers{display:grid;gap:14px;margin-top:12px;padding-left:34px;}.provider{display:grid;gap:7px;}.provider-title{font-weight:650;}.actions{display:flex;align-items:center;flex-wrap:wrap;gap:8px;}textarea{box-sizing:border-box;width:100%;min-height:58px;resize:vertical;border:1px solid var(--divider-color,#666);border-radius:8px;padding:8px;color:var(--primary-text-color,inherit);background:var(--card-background-color,#202126);font:inherit;}button{display:inline-flex;align-items:center;gap:6px;min-height:36px;border:1px solid var(--divider-color,#666);border-radius:9px;padding:7px 11px;color:inherit;background:transparent;cursor:pointer;font:inherit;font-weight:600;}button:disabled,textarea:disabled{opacity:.5;cursor:default;}.warning{color:var(--warning-color,#d89300);font-size:12px;line-height:1.45;}:host([embedded]){display:grid;gap:12px;}:host([embedded]) textarea.hpf-input{min-height:72px;border-radius:7px;padding:8px 10px;border-color:var(--hpf-line,var(--divider-color,#666));background:var(--hpf-surface,var(--card-background-color,#202126));}:host([embedded]) textarea[aria-invalid="true"]{border-color:var(--hpf-danger,var(--error-color,#db543d));}:host([embedded]) .hpf-actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;}:host([embedded]) button{min-height:44px;border-radius:8px;padding:9px 14px;font-weight:400;border-color:var(--hpf-line,var(--divider-color,#666));}:host([embedded]) .hpf-hint{margin:0;}`,customElements.get("hp-zigbee-topology-settings")||customElements.define("hp-zigbee-topology-settings",$l);const kl=(t,e)=>[t[0]-e[0],t[1]-e[1]],xl=(t,e)=>[t[0]+e[0],t[1]+e[1]],Ml=(t,e)=>t[0]*e[0]+t[1]*e[1],Cl=t=>Math.hypot(t[0],t[1]);function Sl(t){let e=0;for(let i=0;i<t.length;i++){const s=t[i],o=t[(i+1)%t.length];e+=s[0]*o[1]-o[0]*s[1]}return e/2}function Pl(t,e,i){const s=kl(i,e),o=Ml(s,s);if(o<1e-12)return Cl(kl(t,e));let a=Ml(kl(t,e),s)/o;return a=Math.max(0,Math.min(1,a)),Cl(kl(t,[e[0]+s[0]*a,e[1]+s[1]*a]))}function Il(t,e){const i=t[e],s=t[(e+1)%t.length],o=kl(s,i),a=Cl(o)||1;let n=[o[1]/a,-o[0]/a];const r=[(i[0]+s[0])/2,(i[1]+s[1])/2],l=Math.max(.01*a,1e-4);return function(t,e){let i=!1;for(let s=0,o=e.length-1;s<e.length;o=s++){const a=e[s][0],n=e[s][1],r=e[o][0],l=e[o][1];n>t[1]!=l>t[1]&&t[0]<(r-a)*(t[1]-n)/(l-n)+a&&(i=!i)}return i}([r[0]+n[0]*l,r[1]+n[1]*l],t)&&(n=[-n[0],-n[1]]),n}function Dl(t){const e=t.length;if(e<3)return!1;for(let i=0;i<e;i++)for(let s=i+1;s<e;s++)if(s!==i&&(s+1)%e!==i&&(i+1)%e!==s&&Jt(t[i],t[(i+1)%e],t[s],t[(s+1)%e]))return!1;return!0}function Ll(t,e,i=1e-6){let s=1/0;for(const[o,a]of e){const e=kl(a,o),n=Cl(e);if(n<i)continue;const r=[e[0]/n,e[1]/n],l=t=>(t[0]-o[0])*r[1]-(t[1]-o[1])*r[0],h=t=>(t[0]-o[0])*r[0]+(t[1]-o[1])*r[1],c=i,d=n-i;for(const e of t){const t=Math.abs(l(e));if(t<=i)continue;const o=h(e);o<=c||o>=d||t<s&&(s=t)}for(let e=0;e<t.length;e++){const o=t[e],a=t[(e+1)%t.length],n=l(o),r=l(a);if(Math.abs(n)<=i||Math.abs(r)<=i)continue;const p=h(o),u=h(a),_=Math.max(c,Math.min(p,u)),m=Math.min(d,Math.max(p,u));if(m-_<=i)continue;const g=u-p;if(Math.abs(g)<i){s=Math.min(s,Math.abs(n),Math.abs(r));continue}const f=t=>Math.abs(n+(t-p)/g*(r-n));s=Math.min(s,f(_),f(m))}}return s}function Tl(t,e,i){if(Xt(t,e,i))return!0;if(Zt(t,e,i)||Zt(e,t,i))return!1;let s=0;try{const i=Qt([[...t.map(t=>[t[0],t[1]]),[t[0][0],t[0][1]]]],[[...e.map(t=>[t[0],t[1]]),[e[0][0],e[0][1]]]]);for(const t of i)t?.[0]&&(s+=te(t[0]))}catch{return!1}return s>Math.max(1e-7,i*i)}function Rl(t,e,i){for(const s of e)for(let e=0;e<s.length;e++){const o=s[e],a=s[(e+1)%s.length],n=kl(a,o),r=Cl(n);if(r<i)continue;const l=[n[0]/r,n[1]/r];if(Math.abs((t.x-o[0])*l[1]-(t.y-o[1])*l[0])>i)continue;const h=(t.x-o[0])*l[0]+(t.y-o[1])*l[1];if(h-t.length/2>=-i&&h+t.length/2<=r+i)return!0}return!1}function Fl(t,e,i){const s=Math.abs(e[0]-t[0]),o=Math.abs(e[1]-t[1]);return s<=i&&o>i?"v":o<=i&&s>i?"h":null}function zl(t,e,i){return Math.abs(t[0]-e[0])<=i&&Math.abs(t[1]-e[1])<=i}function Nl(t,e,i,s,o){return zl(t,i,o)&&zl(e,s,o)||zl(t,s,o)&&zl(e,i,o)}function El(t,e,i,s,o){const a=Fl(t,e,o);return a&&Fl(i,s,o)===a?"h"===a?Math.abs(t[1]-i[1])>o||Math.abs(t[1]-s[1])>o?0:Math.max(0,Math.min(Math.max(t[0],e[0]),Math.max(i[0],s[0]))-Math.max(Math.min(t[0],e[0]),Math.min(i[0],s[0]))):Math.abs(t[0]-i[0])>o||Math.abs(t[0]-s[0])>o?0:Math.max(0,Math.min(Math.max(t[1],e[1]),Math.max(i[1],s[1]))-Math.max(Math.min(t[1],e[1]),Math.min(i[1],s[1]))):0}function Al(t,e,i,s){const o=t.length,a=Fl(t[(e-1+o)%o],t[e],s),n=Fl(t[(e+1)%o],t[(e+2)%o],s),r="h"===i?"v":"h";return a===r&&n===r}function Ol(t){let e=1/0,i=1/0,s=-1/0,o=-1/0;for(const a of t)e=Math.min(e,a[0]),i=Math.min(i,a[1]),s=Math.max(s,a[0]),o=Math.max(o,a[1]);return[e,i,s,o]}function Bl(t,e,i){const s=Ol(t),o=Ol(e);return s[2]<o[0]-i||o[2]<s[0]-i||s[3]<o[1]-i||o[3]<s[1]-i}function Hl(t,e,i,s){const o=s.eps;return"circle"===t.kind?Pl(t.center,e,i)<t.radius+(s.movingHalf||0)-o:El(e,i,t.a,t.b,o)>o}const Wl=(t,e)=>"h"===e?t[0]:t[1],Gl=(t,e)=>"h"===e?t[1]:t[0];function jl(t,e,i,s,o){const a=t.find(t=>t.id===e);if(!a)return null;const n=a.poly[i],r=a.poly[(i+1)%a.poly.length],l=Fl(n,r,o);if(!l)return null;const h=0===s?r:n,c=0===s?n:r,d=Wl(h,l),p=Wl(c,l),u=Gl(h,l),_=function(t,e,i,s){const o=[];for(const a of t)for(let t=0;t<a.poly.length;t++){const n=a.poly[t],r=a.poly[(t+1)%a.poly.length];if(Fl(n,r,s)!==e||Math.abs(Gl(n,e)-i)>s||Math.abs(Gl(r,e)-i)>s)continue;const l=Wl(n,e),h=Wl(r,e),c=Math.min(l,h),d=Math.max(l,h);d-c>s&&o.push({roomId:a.id,edge:t,lo:c,hi:d})}return o.sort((t,e)=>t.lo-e.lo||t.hi-e.hi||t.roomId.localeCompare(e.roomId)||t.edge-e.edge)}(t,l,u,o),m=function(t,e,i,s){const o=[e,i];for(const a of t){const t=Math.max(e,a.lo),n=Math.min(i,a.hi);n-t>s&&o.push(t,n)}const a=[...new Set(o)].sort((t,e)=>t-e),n=[];for(let e=0;e+1<a.length;e++){const i=a[e],o=a[e+1];if(o-i<=s)continue;const r=(i+o)/2,l=[...new Set(t.filter(t=>r>t.lo-s&&r<t.hi+s).map(t=>t.roomId))].sort();n.push({lo:i,hi:o,owners:l})}return n}(_,Math.min(d,p),Math.max(d,p),o);return!m.length||m.some(t=>t.owners.length<1||t.owners.length>2)?null:{roomId:e,edge:i,movedEndpoint:s,axis:l,line:u,fixed:d,moving:p,intervals:_,baseline:m}}function Ul(t,e,i){const s=[];for(const o of t.intervals){const a=e.polys[o.roomId];if(!a){s.push(o);continue}if(o.edge<0||o.edge>=a.length)continue;const n=a[o.edge],r=a[(o.edge+1)%a.length];if(Fl(n,r,i)!==t.axis||Math.abs(Gl(n,t.axis)-t.line)>i||Math.abs(Gl(r,t.axis)-t.line)>i)continue;const l=Wl(n,t.axis),h=Wl(r,t.axis),c=Math.min(l,h),d=Math.max(l,h);d-c>i&&s.push({...o,lo:c,hi:d})}return s}function ql(t,e,i){return new Set(t.filter(t=>e>t.lo-i&&e<t.hi+i).map(t=>t.roomId)).size}function Kl(t,e,i){for(const s of e.sideOwnership){const e=t.polys[s.roomId];if(!e)return!1;const o=e[s.edge],a=e[(s.edge+1)%e.length];if(Fl(o,a,i)!==s.axis)return!1;const n=Wl(0===s.movedEndpoint?o:a,s.axis),r=Ul(s,t,i),l=(s.moving>=s.fixed?s.baseline[s.baseline.length-1]:s.baseline[0]).owners.length;if(l<1||l>2)return!1;const h=Math.min(s.fixed,s.moving,n),c=Math.max(s.fixed,s.moving,n),d=[h,c,s.fixed,s.moving,n];for(const t of s.intervals)d.push(t.lo,t.hi);for(const t of r)d.push(t.lo,t.hi);const p=[...new Set(d.filter(t=>t>=h&&t<=c))].sort((t,e)=>t-e),u=Math.min(s.fixed,s.moving),_=Math.max(s.fixed,s.moving),m=Math.min(s.fixed,n),g=Math.max(s.fixed,n);for(let t=0;t+1<p.length;t++){const e=p[t],o=p[t+1];if(o-e<=i)continue;const a=(e+o)/2,n=a>u-i&&a<_+i,h=a>m-i&&a<g+i;if(!n&&!h)continue;const c=ql(s.intervals,a,i),d=ql(r,a,i);if(c>2||d>2)return!1;if(n&&h){if(c!==d)return!1}else if(!n&&h){if(d!==l||c>0&&c!==d)return!1}else if(2===c?2!==d:d>1)return!1}}return!0}function Vl(t,e,i,s){const o=[i.n[0]*s,i.n[1]*s],a={polys:{},openings:{},movedSpans:{}};for(const e of i.roomIds){const s=t.find(t=>t.id===e),n=i.edgeByRoom[e];if(!s||null==n)continue;const r=(n+1)%s.poly.length;a.polys[e]=s.poly.map((t,e)=>e===n||e===r?xl(t,o):[...t]),a.movedSpans[e]=[[xl(s.poly[n],o),xl(s.poly[r],o)]]}for(const t of e)i.movingOpeningIds.includes(t.id)&&(a.openings[t.id]=[t.x+o[0],t.y+o[1]]);return a}function Jl(t,e,i,s,o,a,n,r){if(!function(t,e,i,s){if(Pl([t.x,t.y],e,i)>2*s)return!1;const o=Cl(kl(i,e));if(o<=s)return!1;const a=[(i[0]-e[0])/o,(i[1]-e[1])/o],n=(t.x-e[0])*a[0]+(t.y-e[1])*a[1];return n>=-s&&n<=o+s}(t,e,i,r))return!0;if(Pl([t.x,t.y],s,o)>2*r)return!1;const l=0===a?s:o;return Cl(kl([t.x,t.y],l))>=t.length/2+n-r}function Yl(t,e,i,s){const o=s.movingHalf||0;return"circle"===t.kind?Pl(t.center,e,i)<t.radius+o-s.eps:function(t,e,i,s){return Jt(t,e,i,s)?0:Math.min(Pl(t,i,s),Pl(e,i,s),Pl(i,t,e),Pl(s,t,e))}(e,i,t.a,t.b)<(t.half||0)+o-s.eps}function Zl(t,e,i,s,o){const{eps:a,minDim:n}=o;if(!Number.isFinite(s)||i.roomIds.length<1||i.roomIds.length>2)return!1;const r=Vl(t,e,i,s);if(Object.keys(r.polys).length!==i.roomIds.length)return!1;if(!Kl(r,i,a))return!1;const l=new Set(i.roomIds),h=t=>r.polys[t.id]||t.poly;for(const s of i.roomIds){const l=t.find(t=>t.id===s),h=r.polys[s],c=i.edgeByRoom[s];if(!l||!h||h.length!==i.topology[s]||h.length!==l.poly.length||!Dl(h))return!1;const d=l.poly.length,p=(c-1+d)%d,u=[p,c,(c+1)%d];for(const t of u)if(Yt(h[t],h[(t+1)%d]))return!1;const _=Sl(l.poly),m=Sl(h);if(Math.abs(m)<a||_*m<=0)return!1;const g=[l.poly[c],l.poly[(c+1)%l.poly.length]],f=r.movedSpans[s],b=Ll(l.poly,[g],a);if(Ll(h,f,a)<Math.min(n,b)-a)return!1;const v=[l.poly[p],l.poly[c]],y=[h[p],h[c]],w=[l.poly[(c+1)%d],l.poly[(c+2)%d]],$=[h[(c+1)%d],h[(c+2)%d]],k=Fl(h[c],h[(c+1)%d],a),x="h"===k?"v":"v"===k?"h":null;if(!x||Fl(...y,a)!==x||Fl(...$,a)!==x)return!1;for(const t of e)if(!i.movingOpeningIds.includes(t.id)){if(!Jl(t,...v,...y,1,o.movingHalf||0,a))return!1;if(!Jl(t,...w,...$,0,o.movingHalf||0,a))return!1}}if(2===i.roomIds.length){const[t,e]=i.roomIds,s=r.polys[t],o=r.polys[e],n=i.edgeByRoom[t],l=i.edgeByRoom[e];if(!Nl(s[n],s[(n+1)%s.length],o[l],o[(l+1)%o.length],a))return!1}for(const e of i.roomIds){const i=t.find(t=>t.id===e),s=r.polys[e];for(const o of t){if(o.id===e||l.has(o.id))continue;const t=h(o);if(!Bl(i.poly,o.poly,a)||!Bl(s,t,a))if(Zt(i.poly,o.poly,a)){if(!Zt(s,t,a))return!1}else if(Zt(o.poly,i.poly,a)){if(!Zt(t,s,a))return!1}else if(Zt(s,t,a)||Zt(t,s,a)||Tl(s,t,a))return!1}}const c=r.polys[i.roomId],d=i.edgeByRoom[i.roomId],p=c[d],u=c[(d+1)%c.length];if(Math.abs(s)>a)for(const t of o.obstacles||[])if(Yl(t,p,u,o))return!1;for(const t of e){if(!i.movingOpeningIds.includes(t.id))continue;const e=r.openings[t.id];if(!e||t.hosted)return!1;if(!Rl({...t,x:e[0],y:e[1]},[c],2*a))return!1}return!0}const Xl=new WeakMap,Ql=t=>"number"==typeof t&&Number.isFinite(t),th=(t,e)=>{const i=new Map;for(const s of t||[])!Ql(s?.cm)||!e&&s.cm<=0||i.set(s.cm,(i.get(s.cm)||0)+1);return i},eh=t=>[String(t),"см"].join(" ");function ih(t,e,i={}){if(i.allowClear)return[];const s=!0===i.exactMultiplicity,o=th(t,s),a=th(e,s),n=[];for(const[t,e]of o){const i=a.get(t)||0;0===i?n.push({invariant:"wall_records",kind:"lost",owner:eh(t),reference:`было ${e}`,detail:"записи этой толщины исчезли целиком"}):s&&i!==e&&n.push({invariant:"wall_records",kind:"count",owner:eh(t),reference:`было ${e}, стало ${i}`,detail:"изменилось число записей этой толщины"})}if(s)for(const[t,e]of a)o.has(t)||n.push({invariant:"wall_records",kind:"count",owner:eh(t),reference:`было 0, стало ${e}`,detail:"появились записи новой толщины"});return n}class sh{constructor(){this._selectedRoomId=null,this._session=null,this._eligibility=null}get dragging(){return null!==this._session}ownsPointer(t){return this._session?.pointerId===t}get selectedRoomId(){return this._selectedRoomId}get snapshotIdentity(){return this._session?.snapshotIdentity||null}get activePointerId(){return this._session?.pointerId??null}get moved(){return!0===this._session?.moved}get delta(){return this._session?.delta||0}get rooms(){return this._session?.rooms||null}get openings(){return this._session?.openings||null}get plan(){return this._session?.plan||null}get preview(){return this._session?.accepted?.preview||null}get liveLabels(){return this._session?.accepted?.labels||null}selectRoom(t){this._selectedRoomId=t}restoreSelection(t){this._selectedRoomId=t}escapeIdle(){return this._selectedRoomId?(this._selectedRoomId=null,"selection-cleared"):"exit-tool"}resolve(t,e,i){this._eligibility&&this._eligibility.context===t||(this._eligibility={context:t,values:new Map});const s=this._eligibility.values.get(e);if(s)return s;const o=i();return this._eligibility.values.set(e,o),o}begin(t){return!this._session&&(this._session={pointerId:t.pointerId,start:[...t.start],roomId:t.roomId,plan:t.plan,options:t.options,rooms:t.rooms,openings:t.openings,snapshotIdentity:t.snapshotIdentity,before:t.before,moved:!1,delta:0,changedRoomIds:[...t.plan.roomIds],rejectionNotified:!1,wallUnionBefore:t.wallUnionBefore,epochBefore:t.epochBefore,accepted:null},!0)}move(t){const e=this._session;if(!e||e.pointerId!==t.pointerId)return{kind:"no-op"};const i=(s=e.start,o=t.point,a=e.plan.n,[s?.[0],s?.[1],o?.[0],o?.[1],a?.[0],a?.[1]].every(Number.isFinite)?(o[0]-s[0])*a[0]+(o[1]-s[1])*a[1]:0);var s,o,a;const n=t.snap([e.plan.a[0]+e.plan.n[0]*i,e.plan.a[1]+e.plan.n[1]*i]),r=(n[0]-e.plan.a[0])*e.plan.n[0]+(n[1]-e.plan.a[1])*e.plan.n[1],l=function(t,e,i,s,o,a){if(!Number.isFinite(s)||Math.abs(s)<1e-9)return 0;const n=Math.sign(s),r=Math.abs(s),l=Math.max(Math.abs(o),1e-6);let h=Xl.get(i);h&&h.opts===a||(h={opts:a,values:new Map},Xl.set(i,h));const c=h.values;let d=0;for(let s=Math.min(l,r),o=0;o<4096&&s<=r+1e-9;o++,s=Math.min(r,s+l)){const o=n*s,h=`${o.toFixed(9)}|${l.toFixed(9)}`;let p=c.get(h);if(void 0===p&&(p=Zl(t,e,i,o,a),c.size<4096&&c.set(h,p)),!p)break;if(d=o,Math.abs(s-r)<=1e-9)break}return d}(e.rooms,e.openings,e.plan,r,t.step,e.options);if(e.moved&&l===e.delta)return{kind:"no-op"};const h=Vl(e.rooms,e.openings,e.plan,l);let c;try{if(c=t.project(e.snapshotIdentity,h.polys,h.openings,e.changedRoomIds,e.rooms),!c.ok)return this._projectionRejected(e);if(ih(c.value.beforeWalls,c.value.afterWalls,{exactMultiplicity:!0}).length)return this._projectionRejected(e)}catch{return this._projectionRejected(e)}const d=e.accepted,p={preview:c.value.preview,labels:null,artifact:c.value.artifact,beforeWalls:c.value.beforeWalls,afterWalls:c.value.afterWalls};e.accepted=p;try{t.publish(p.preview,p.artifact),p.labels=t.measure(h,e.plan)}catch{e.accepted=d;try{t.publish(d?.preview||null,d?.artifact||null)}catch{}return this._projectionRejected(e)}return e.moved=!0,e.delta=l,{kind:"accepted",preview:c.value.preview,labels:p.labels,artifact:c.value.artifact}}finish(t){const e=this._session;if(!e||e.pointerId!==t.pointerId)return{kind:"no-op"};const i=e.accepted;let s;if(e.moved&&Math.abs(e.delta)>1e-9&&i)if(t.currentSnapshotIdentity!==e.snapshotIdentity)s={kind:"rejected",reason:"stale-snapshot"};else if(Zl(e.rooms,e.openings,e.plan,e.delta,e.options))if(ih(i.beforeWalls,i.afterWalls,{exactMultiplicity:!0}).length)s={kind:"rejected",reason:"wall-records"};else{let o=!1;try{o=t.validatePreview(i.preview)}catch{o=!1}s=o?{kind:"commit",preview:i.preview,before:e.before}:{kind:"rejected",reason:"invalid-candidate"}}else s={kind:"rejected",reason:"invalid-topology"};else s={kind:"no-op"};return this._session=null,"commit"===s.kind&&(this._eligibility=null),s}cancel(t,e){const i=this._session;if(!i||void 0!==e&&i.pointerId!==e)return{kind:"no-op"};this._session=null,this._eligibility=null;const s=t===i.snapshotIdentity;return{kind:"cancelled",restoreWallUnion:s?i.wallUnionBefore:null,restoreEpoch:s?i.epochBefore:null}}reset(){this._selectedRoomId=null,this._session=null,this._eligibility=null}_projectionRejected(t){const e=!t.rejectionNotified;return t.rejectionNotified=!0,{kind:"rejected",notify:e}}}const oh=t=>"object"==typeof t&&null!==t?t:null,ah=t=>Array.isArray(t)?t.flatMap(t=>{const e=oh(t);return e?[e]:[]}):[],nh=t=>{if(!Array.isArray(t))return null;const e=Number(t[0]),i=Number(t[1]);return Number.isFinite(e)&&Number.isFinite(i)?[e,i]:null};function rh(t){const e=(i=t.poly,Array.isArray(i)?i.flatMap(t=>{const e=nh(t);return e?[e]:[]}):[]);var i;if(e.length>=3)return e;const s=Number(t.x),o=Number(t.y),a=Number(t.w),n=Number(t.h);return[s,o,a,n].every(Number.isFinite)?[[s,o],[s+a,o],[s+a,o+n],[s,o+n]]:[]}function lh(t){if(!t.length)return null;const e=t.map(t=>t[0]),i=t.map(t=>t[1]);return{minX:Math.min(...e),minY:Math.min(...i),maxX:Math.max(...e),maxY:Math.max(...i)}}function hh(t,e){const i=oh(t);if(!i)return null;const s=ah(i.rooms),o=new Set(function(t,e){const i=ah(t),s=new Set(e);return i.flatMap(t=>{const e=String(t.id||"");return e&&s.has(e)?[e]:[]})}(s,e)),a=s.filter(t=>o.has(String(t.id||"")));if(!lh(a.flatMap(rh))||!a.length)return null;const n=Number(i.cell_cm),r=Number.isFinite(n)&&n>0?n:5,l=a.flatMap(t=>{const e=rh(t);return e.map((t,i)=>[t,e[(i+1)%e.length]])}),h=.02*A,c=(t,e,i)=>{const s=i[0]-e[0],o=i[1]-e[1],a=s*s+o*o,n=a>0?Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*o)/a)):0;return Math.hypot(t[0]-e[0]-n*s,t[1]-e[1]-n*o)},d=(t,e)=>Math.min(...l.map(([i,s])=>((t,e,i,s)=>{const o=(t,e,i)=>(e[0]-t[0])*(i[1]-t[1])-(e[1]-t[1])*(i[0]-t[0]),a=o(t,e,i),n=o(t,e,s),r=o(i,s,t),l=o(i,s,e);return a*n<=h*h&&r*l<=h*h&&Math.min(t[0],e[0])<=Math.max(i[0],s[0])+h&&Math.min(i[0],s[0])<=Math.max(t[0],e[0])+h&&Math.min(t[1],e[1])<=Math.max(i[1],s[1])+h&&Math.min(i[1],s[1])<=Math.max(t[1],e[1])+h?0:Math.min(c(t,i,s),c(e,i,s),c(i,t,e),c(s,t,e))})(t,e,i,s))),p=t=>{const e=nh(t.a),i=nh(t.b);if(e&&i)return((t,e)=>l.some(([i,s])=>{const o=s[0]-i[0],a=s[1]-i[1],n=Math.hypot(o,a);if(!(n>h))return!1;const r=t=>Math.abs((t[0]-i[0])*a-(t[1]-i[1])*o)/n;if(r(t)>h||r(e)>h)return!1;const l=t=>((t[0]-i[0])*o+(t[1]-i[1])*a)/(n*n),c=l(t),d=l(e);return Math.min(1,Math.max(c,d))-Math.max(0,Math.min(c,d))>h}))(e,i);const[s]=String(t.key||"").split("@"),o=s?.split(",").map(Number)||[];return 2!==o.length||!o.every(Number.isFinite)||l.some(([t,e])=>c(o,t,e)<=h)},u=ah(i.walls).filter(p),_=ah(i.wall_segments).filter(p),m=Math.max(0,...[...u,..._].map(t=>Number(t.cm)).filter(Number.isFinite))/r*A/2,g=ah(i.partitions).filter(t=>{const e=nh(t.a),i=nh(t.b);if(!e||!i)return!0;const s=Math.max(0,Number(t.cm)||0)/r*A/2;return d(e,i)<=m+s+h}),f=ah(i.wall_columns).filter(t=>{const e=nh(t.center);if(!e)return!0;const i=Math.max(0,Number(t.cm)||0)/r*A;return l.some(([t,s])=>c(e,t,s)<=m+i+h)}),b=new Set(g.map(t=>String(t.id||"")).filter(Boolean)),v=ah(i.openings).filter(t=>{const e=oh(t.host);if("partition"===e?.kind)return b.has(String(e.id||""));const i=nh([t.x,t.y]);return!i||l.some(([t,e])=>c(i,t,e)<=h)});return{...i,rooms:a,walls:u,wall_segments:_,open_spans:ah(i.open_spans).filter(p),partitions:g,wall_columns:f,openings:v}}const ch=t=>"object"==typeof t&&null!==t?t:null,dh=t=>Array.isArray(t)?t.flatMap(t=>{const e=ch(t);return e?[e]:[]}):[],ph=t=>{if(!Array.isArray(t))return null;const e=Number(t[0]),i=Number(t[1]);return Number.isFinite(e)&&Number.isFinite(i)?[e,i]:null},uh=t=>JSON.stringify(t??null),_h=(t,e=1e8)=>`${Math.round(t[0]*e)},${Math.round(t[1]*e)}`,mh=(t,e,i=1e-8)=>Math.hypot(t[0]-e[0],t[1]-e[1])<=i,gh=(t,e,i)=>{const s=i[0]-e[0],o=i[1]-e[1],a=s*s+o*o,n=a>0?Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*o)/a)):0;return Math.hypot(t[0]-e[0]-n*s,t[1]-e[1]-n*o)},fh=(t,e,i)=>(e[0]-t[0])*(i[1]-t[1])-(e[1]-t[1])*(i[0]-t[0]),bh=(t,e,i,s)=>{const o=2e-4*A,a=fh(t,e,i),n=fh(t,e,s),r=fh(i,s,t),l=fh(i,s,e);return a*n<=o*o&&r*l<=o*o&&Math.min(t[0],e[0])<=Math.max(i[0],s[0])+o&&Math.min(i[0],s[0])<=Math.max(t[0],e[0])+o&&Math.min(t[1],e[1])<=Math.max(i[1],s[1])+o&&Math.min(i[1],s[1])<=Math.max(t[1],e[1])+o?0:Math.min(gh(t,i,s),gh(e,i,s),gh(i,t,e),gh(s,t,e))},vh=t=>{const e=(i=t.poly,Array.isArray(i)?i.flatMap(t=>{const e=ph(t);return e?[e]:[]}):[]);var i;if(e.length>=3)return e;const s=Number(t.x),o=Number(t.y),a=Number(t.w),n=Number(t.h);return[s,o,a,n].every(Number.isFinite)?[[s,o],[s+a,o],[s+a,o+n],[s,o+n]]:[]},yh=t=>{const e=vh(t);return e.map((t,i)=>[t,e[(i+1)%e.length]])},wh=(t,e)=>Math.max(0,Number(t)||0)/e*A,$h=(t,e=15)=>{const i=Number(t.cm);return Number.isFinite(i)?Math.max(0,i):e},kh=t=>Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0]),xh=(t,e)=>{let i=Math.abs(kh(t)-kh(e));return i%=Math.PI,i=Math.min(i,Math.PI-i),i<=Math.PI/180&&Math.abs(t.cm-e.cm)<=1e-6};function Mh(t,e){const i=ch(t),s=dh(i?.partitions).find(t=>t.id===e);if(!s)return null;const o=ph(s.a),a=ph(s.b),n=Number(s.cm);return!o||!a||!Number.isFinite(n)||n<0||mh(o,a)?null:{partitionId:e,a:o,b:a,cm:n}}function Ch(t,e){const i=ch(t);if(!i)return null;const s=Number(i.cell_cm),o=Number.isFinite(s)&&s>0?s:5,a=wh(5,o),n=wh(e.cm,o)/2,r=dh(i.rooms),l=dh(i.wall_segments),h=new Map(l.map(t=>[String(t.id||""),t])),c=dh(i.walls),d=t=>{const e=Array.isArray(t.wall_ids)?t.wall_ids.map(String):[];return yh(t).map(([t,i],s)=>{const a=[h.get(e[s]),...c.filter(e=>{const s=ph(e.a),o=ph(e.b);if(s&&o)return bh(t,i,s,o)<=.02*A;const[a]=String(e.key||"").split("@"),n=ph(a?.split(",").map(Number));return!!n&&gh(n,t,i)<=.02*A})].filter(t=>!!t),n=Math.max(15,...a.map(t=>$h(t,15)));return{a:t,b:i,half:wh(n,o)/2}})},p=r.flatMap(t=>{const i=String(t.id||""),s=d(t).some(({a:t,b:i,half:s})=>bh(e.a,e.b,t,i)<=n+s+a);return i&&s?[i]:[]}),u=new Set(p);if(p.length){const t=r.filter(t=>u.has(String(t.id||""))).flatMap(d);for(const e of r){const i=String(e.id||"");i&&!u.has(i)&&(d(e).some(({a:e,b:i,half:s})=>t.some(t=>bh(e,i,t.a,t.b)<=s+t.half+.02*A))&&u.add(i))}}const _=[...u],m=r.filter(t=>u.has(String(t.id||""))),g=new Set(m.flatMap(t=>Array.isArray(t.wall_ids)?t.wall_ids.map(String):[])),f=dh(i.wall_segments).filter(t=>g.has(String(t.id||""))),b=m.flatMap(yh),v=dh(i.walls).filter(t=>{const e=ph(t.a),i=ph(t.b);if(e&&i)return b.some(([t,s])=>bh(e,i,t,s)<=.02*A);const[s]=String(t.key||"").split("@"),o=ph(s?.split(",").map(Number));return!o||b.some(([t,e])=>gh(o,t,e)<=.02*A)}),{segments:y,malformedPartitions:w}=function(t){const e=[],i=[];for(const s of dh(t.partitions)){const t=ph(s.a),o=ph(s.b);t&&o?e.push({key:`partition:${String(s.id||uh(s))}`,source:s,a:t,b:o,cm:$h(s,0)}):i.push(s)}return{segments:e,malformedPartitions:i}}(i),$=new Set(y.flatMap(t=>bh(e.a,e.b,t.a,t.b)<=n+wh(t.cm,o)/2+a?[t.key]:[]));let k=!0;for(;k;){k=!1;const t=y.filter(t=>$.has(t.key));for(const e of y)$.has(e.key)||t.some(t=>xh(t,e)&&(mh(t.a,e.a)||mh(t.a,e.b)||mh(t.b,e.a)||mh(t.b,e.b)))&&($.add(e.key),k=!0)}const x=new Set(y.filter(t=>$.has(t.key)).flatMap(t=>[_h(t.a),_h(t.b)]));for(const t of y)(x.has(_h(t.a))||x.has(_h(t.b)))&&$.add(t.key);const M=y.filter(t=>$.has(t.key)),C=M.map(t=>t.source).concat(w),S=dh(i.wall_columns).filter(t=>{const i=ph(t.center);if(!i)return!0;const s=wh(Number(t.cm),o)/2,r="circle"===t.shape?s:s*Math.SQRT2;return gh(i,e.a,e.b)<=n+r+a}),P=new Set(C.map(t=>String(t.id||""))),I=new Set(f.map(t=>String(t.id||""))),D=dh(i.openings).filter(t=>{const i=ch(t.host);if("partition"===i?.kind)return P.has(String(i.id||""));if("wall"===i?.kind&&I.has(String(i.id||"")))return!0;const s=ph([t.x,t.y]);return!s||gh(s,e.a,e.b)<=n+a}),L=dh(i.open_spans).filter(t=>{const i=ph(t.a),s=ph(t.b);return!i||!s||bh(e.a,e.b,i,s)<=n+a});return{space:{...i,rooms:m,walls:v,wall_segments:f,open_spans:L,openings:D,partitions:C,wall_columns:S},roomIds:_,segmentCount:f.length+M.length}}const Sh=1e3;const Ph=(t,e)=>(t._clearGeometryGesture(),t._restoreGeometryStateLocal(e),t.host._showToast(t.host._t("toast.geometry_unsafe")),!1);function Ih(t,e,i){const{host:s}=t,o=s._serverCfg,a=s._activeWallChainPartitionIds[s._activeWallChainPartitionIds.length-1]||null,n=()=>t._commitPhysicalGeometry(e,i);if(!i||!o||!a||10!==Number(o.model_version||0))return n();const r=o.spaces.find(t=>t.id===i.spaceId);if(!r||!function(t,e,i){const s=ch(t),o=ch(e);if(!s||!o||String(s.spaceId||"")!==String(o.id||""))return!1;if(["rooms","openings","walls","wall_segments","open_spans","wall_columns","decor"].some(t=>uh(s[t]??[])!==uh(o[t]??[])))return!1;const a=ch(s.plan_transform)||{},n={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==o[t]&&(n[t]=o[t]);if(uh(a)!==uh(n))return!1;const r=dh(s.partitions),l=dh(o.partitions);if(l.length!==r.length+1||uh(l.slice(0,-1))!==uh(r))return!1;const h=l[l.length-1],c=ph(h.a),d=ph(h.b);return h.id===i&&!!c&&!!d&&!mh(c,d)&&Number.isFinite(Number(h.cm))&&Number(h.cm)>=0}(i,r,a))return n();let l;try{l=ir(o).config}catch(e){return t._clearGeometryGesture(),t._restoreGeometryStateLocal(i),t._showWallModelMigrationBlocked(e),!1}const h=l.spaces.find(t=>t.id===i.spaceId),c=Mh(h,a);if(!h||!c)return n();const d=JSON.parse(JSON.stringify(o));if(!t._restoreGeometryStateInConfig(d,i))return n();const p=d.spaces.find(t=>t.id===i.spaceId),u=Ch(h,c),_=Ch(p,c);if(!u||!_)return n();const m={...l,spaces:[u.space]},g={...d,spaces:[_.space]};let f=null,b=!1;try{const t=s._path.length>=2?s._path.map(t=>[t[0]/Sh,t[1]/Sh]):[];b=Fn(h)<=Fn(i,t)&&s._checkSpacePhysicalGeometry(m,i.spaceId,t=>{f=t}).ok}catch{b=!1}if(!b)return Ph(t,i);const v=t._junctionLimitsIntroduced(m,g,i.spaceId,f,u.roomIds);if(v.length)return t._clearGeometryGesture(),t._restoreGeometryStateLocal(i),s._showToast(t._junctionLimitLabel(v[0])),!1;or(o,l);const y=o.spaces.find(t=>t.id===i.spaceId),w=y?.partitions?.find(t=>t.id===a),$=s._activeWallChainPartitionIds.length-1;w&&$>=0&&s._path.length===s._wallChainSegmentCms.length+1&&(s._path[$]=[w.a[0]*Sh,w.a[1]*Sh],s._path[$+1]=[w.b[0]*Sh,w.b[1]*Sh],s._wallChainSegmentCms[$]=Number(w.cm)),t._recordGeometry(e,i);const k=s._pendingPhysicalWrites.get(i.spaceId);return s._pendingPhysicalWrites.set(i.spaceId,{before:k?.before||i,fingerprint:ee(y)}),t._saveConfig(),!0}const Dh=(t,e)=>[(t[0]-e.x)/Math.max(1e-9,e.w)*e.stageWidth,(t[1]-e.y)/Math.max(1e-9,e.h)*e.stageHeight];function Lh(t){const{poly:e,edge:i,text:s,view:o}=t,a=e[i],n=e[(i+1)%e.length],r=[(a[0]+n[0])/2,(a[1]+n[1])/2],l=function(t,e){const i=t[e],s=t[(e+1)%t.length],o=s[0]-i[0],a=s[1]-i[1],n=Math.hypot(o,a)||1;return(t=>{let e=0;for(let i=0;i<t.length;i++){const s=t[i],o=t[(i+1)%t.length];e+=s[0]*o[1]-o[0]*s[1]}return e/2})(t)>=0?[-a/n,o/n]:[a/n,-o/n]}(e,i),h=Math.hypot(n[0]-a[0],n[1]-a[1])||1,c=[(n[0]-a[0])/h,(n[1]-a[1])/h],d=Dh(r,o),p=Dh(t.gearCenter,o),u=Math.max(34,7.2*s.length+12),_=Math.abs(l[0])>=Math.abs(l[1])?Math.max(28,u/2+4):Math.max(28,13),m=d[0]+l[0]*_,g=d[1]+l[1]*_,f=e=>{return i=m+c[0]*e,s=g+c[1]*e,o=u,a=18,n=p[0],r=p[1],l=t.gearWidthPx,h=t.gearHeightPx,2*Math.abs(i-n)<o+l+8&&2*Math.abs(s-r)<a+h+8;var i,s,o,a,n,r,l,h};let b=0;if(f(0)){const t=(Math.abs(c[0])>=Math.abs(c[1])?c[0]:c[1])>0?-1:1,e=Math.max(o.stageWidth,o.stageHeight,64);for(let i=4;i<=e;i+=4){const e=i*t;if(!f(e)){b=e;break}const s=-e;if(!f(s)){b=s;break}}}const v=l[0]*_+c[0]*b,y=l[1]*_+c[1]*b,w=Math.hypot(v,y)||1,$=y/w*12,k=[r[0]+v/w*12*o.w/Math.max(1,o.stageWidth),r[1]+$*o.h/Math.max(1,o.stageHeight)];return{anchor:r,offsetXPx:v,offsetYPx:y,tangentOffsetPx:b,side:Math.abs(l[0])>=Math.abs(l[1])?l[0]<0?"left":"right":l[1]<0?"above":"below",leader:{a:r,b:k}}}const Th=t=>{let e=(t%360+360)%360;return e>180&&(e-=360),e};function Rh(t,e,i,s,o,a=0,n=[t,e],r){const l=1e-7,h=(t,e,i,s,o)=>{const a=Math.max(0,Math.min(1,((t[0]-e[0])*i+(t[1]-e[1])*s)/o));return{t:a,x:e[0]+a*i,y:e[1]+a*s}},c=t=>{if(!t||!Number.isFinite(t[0])||!Number.isFinite(t[1]))return null;const e=Math.hypot(t[0],t[1]);return e>1e-9?[t[0]/e,t[1]/e]:null},d=c(r);let p=null;for(const r of s){const s=Number(r?.a?.[0]),u=Number(r?.a?.[1]),_=Number(r?.b?.[0]),m=Number(r?.b?.[1]);if(![s,u,_,m].every(Number.isFinite))continue;const g=_-s,f=m-u,b=g*g+f*f;if(!(b>1e-18))continue;const v=Math.sqrt(b),y=h(n,[s,u],g,f,b),w=Math.hypot(n[0]-y.x,n[1]-y.y);if(!(w<o))continue;let $=c(r.normal),k=0;if($){const t=r.axisA?.length>=2?r.axisA:r.a,e=r.axisB?.length>=2?r.axisB:r.b,i=Number(e[0])-Number(t[0]),s=Number(e[1])-Number(t[1]),o=i*i+s*s;if(o>1e-18&&[t[0],t[1],e[0],e[1]].every(Number.isFinite)){const e=h(n,t,i,s,o),a=(n[0]-e.x)*$[0]+(n[1]-e.y)*$[1];if(a>l)k=2;else if(a<-1e-7){if(r.roomSide)continue;k=-2}else d&&(k=$[0]*d[0]+$[1]*d[1])}}else{let t=n[0]-y.x,e=n[1]-y.y;const i=Math.hypot(t,e);if(i>l)t/=i,e/=i,k=2;else if(d)[t,e]=d,k=1;else{const i=s<_||s===_&&u<=m;t=-(i?f:-f)/v,e=(i?g:-g)/v}$=[t,e]}const x=h([t,e],[s,u],g,f,b);let M=x.t,C=x.x,S=x.y;if(Number.isFinite(a)&&a>0){const t=Math.round(M*v/a)*a;M=Math.max(0,Math.min(1,t/v)),C=s+M*g,S=u+M*f}const P=Th(180*Math.atan2(-$[0],$[1])/Math.PI),I={cx:C+$[0]*(i/2),cy:S+$[1]*(i/2),angle:P,dist:w,sideScore:k,stableId:"string"==typeof r.stableId?r.stableId:""};(!p||I.dist<p.dist-l||Math.abs(I.dist-p.dist)<=l&&(I.sideScore>p.sideScore+l||Math.abs(I.sideScore-p.sideScore)<=l&&I.stableId.localeCompare(p.stableId)<0))&&(p=I)}return p&&{cx:p.cx,cy:p.cy,angle:p.angle,dist:p.dist}}const Fh=t=>Array.isArray(t)&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),zh=(t,e)=>{const i=t=>`${t[0].toFixed(9)},${t[1].toFixed(9)}`,s=i(t),o=i(e);return s<=o?`${s}|${o}`:`${o}|${s}`};function Nh(t,e,i,s,o,a,n=1){const r=[],l=new Map;for(const h of t||[]){const c="string"==typeof h?.id?h.id:"";if(!c)continue;const d=kt(t,c,e,i,s,o,a,n);if(d)for(let t=0;t<d.poly.length;t++){const e=d.poly[t],i=d.poly[(t+1)%d.poly.length];if(!Fh(e)||!Fh(i))continue;const s=i[0]-e[0],o=i[1]-e[1];if(!(Math.hypot(s,o)>1e-9))continue;const a=ne(d.poly,t),n=Number(d.offsets[t]),h=Number.isFinite(n)&&n>0?n:0,p=[e[0],e[1]],u=[i[0],i[1]],_=zh(p,u),m=l.get(_)||new Set;m.add(c),l.set(_,m),r.push({a:[p[0]+a[0]*h,p[1]+a[1]*h],b:[u[0]+a[0]*h,u[1]+a[1]*h],axisA:p,axisB:u,normal:a,owner:"room",stableId:`room:${c}:${_}`,roomId:c,atomId:_,half:h})}}const h=[];for(const t of r){const{atomId:e,half:i,...s}=t;if(!(1===l.get(e)?.size&&i>1e-9)){h.push(s);continue}const o=s.normal;h.push({...s,roomSide:"inside",stableId:`${s.stableId}:inside`}),h.push({...s,a:[s.axisA[0]-o[0]*i,s.axisA[1]-o[1]*i],b:[s.axisB[0]-o[0]*i,s.axisB[1]-o[1]*i],normal:[-o[0],-o[1]],roomSide:"outside",stableId:`${s.stableId}:outside`})}return h}function Eh(t){const e=[],i=new Set;for(const s of t||[])if(Array.isArray(s)&&!(s.length<2))for(let t=0;t<s.length;t++){const o=s[t],a=s[(t+1)%s.length];if(!Fh(o)||!Fh(a))continue;if(!(Math.hypot(a[0]-o[0],a[1]-o[1])>1e-9))continue;const n=[o[0],o[1]],r=[a[0],a[1]],l=`physical:${zh(n,r)}`;i.has(l)||(i.add(l),e.push({a:n,b:r,axisA:[...n],axisB:[...r],normal:null,owner:"physical",stableId:l}))}return e}const Ah=new WeakMap;const Oh=1e-9,Bh=2e-7,Hh=1e7,Wh=t=>{const e=Math.sign(t)*Math.floor(Math.abs(t)*Hh+.5)/Hh;return Object.is(e,-0)?0:e},Gh=t=>`${Wh(t[0])},${Wh(t[1])}`,jh=(t,e)=>Math.hypot(e[0]-t[0],e[1]-t[1]),Uh=(t,e,i)=>t/(e||1)*i,qh=(t,e)=>Math.atan2(e[1]-t[1],e[0]-t[0]),Kh=t=>Array.isArray(t)&&t.length>=2&&t.every(t=>Number.isFinite(t)),Vh=t=>(t||[]).filter(t=>Kh(t?.a)&&Kh(t?.b)&&jh(t.a,t.b)>Oh);function Jh(t,{minAngleDeg:e=15,maxValence:i=6}={}){const s=new Map;for(const e of Vh(t))for(const[t,i]of[[e.a,e.b],[e.b,e.a]]){const e=s.get(Gh(t))||[];e.push(qh(t,i)),s.set(Gh(t),e)}const o=[];for(const[t,a]of s){if(a.length>i&&o.push({rule:"valence",subject:t,actual:a.length,limit:i}),a.length<2)continue;const s=[...a].sort((t,e)=>t-e);let n=1/0;for(let t=0;t<s.length;t++){let e=s[(t+1)%s.length]-s[t];t===s.length-1&&(e+=2*Math.PI);const i=180*e/Math.PI;i>Oh&&i<n&&(n=i)}n<e-1e-9&&o.push({rule:"angle",subject:t,actual:n,limit:e})}return o}const Yh=t=>(180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI%180+180)%180,Zh=(t,e,i=1)=>{const s=Math.abs(Yh(t)-Yh(e));return Math.min(s,180-s)<=i},Xh=t=>{const e=new Map;for(const i of t)for(const t of[i.a,i.b]){const s=e.get(Gh(t));s?s.push(i):e.set(Gh(t),[i])}return e};function Qh(t,e,i){const s=Vh(e),o=i??Xh(s),a=new Set([t]);let n=jh(t.a,t.b);const r=[t.a,t.b];for(;r.length;){const e=r.pop();for(const i of o.get(Gh(e))||[])a.has(i)||Zh(i,t)&&Number(i.cm||0)===Number(t.cm||0)&&(a.add(i),n+=jh(i.a,i.b),r.push(i.a,i.b))}return n}function tc(t,e,i,{minLengthCm:s=20}={}){const o=[],a=Vh(t),n=Xh(a);for(const t of a){const r=Qh(t,a,n)/i*(e||1),l=Math.max(s,Number(t.cm)>0?Number(t.cm):0);r<l-1e-9&&o.push({rule:"length",subject:String(t.id||Gh(t.a)),actual:r,limit:l})}return o}const ec=(t,e,i)=>{const s=i[0]-e[0],o=i[1]-e[1],a=s*s+o*o,n=a<=Oh?0:Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*o)/a));return Math.hypot(t[0]-(e[0]+s*n),t[1]-(e[1]+o*n))};function ic(t,e,i,{minDistanceCm:s=5}={}){const o=Vh(t),a=new Map;for(const t of o)a.set(Gh(t.a),t.a),a.set(Gh(t.b),t.b);const n=Uh(s,e,i),r=n>Oh?n:1,l=(t,e)=>`${Math.floor(t/r)},${Math.floor(e/r)}`,h=new Map;for(const[t,e]of a){const i=l(e[0],e[1]),s=h.get(i);s?s.push([t,e]):h.set(i,[[t,e]])}const c=new Map;for(const t of o){const e=Math.min(t.a[0],t.b[0])-n,i=Math.max(t.a[0],t.b[0])+n,s=Math.min(t.a[1],t.b[1])-n,o=Math.max(t.a[1],t.b[1])+n;for(let a=Math.floor(e/r);a<=Math.floor(i/r);a++)for(let e=Math.floor(s/r);e<=Math.floor(o/r);e++){const i=`${a},${e}`,s=c.get(i);s?s.push(t):c.set(i,[t])}}const d=[];for(const[t,o]of a){const a=Math.floor(o[0]/r),l=Math.floor(o[1]/r);for(let r=-1;r<=1;r++)for(let c=-1;c<=1;c++)for(const[p,u]of h.get(`${a+r},${l+c}`)||[]){if(t>=p)continue;const a=jh(o,u);a<=Bh||a<n-1e-9&&d.push({rule:"distance",subject:`${t} ↔ ${p}`,actual:a/i*(e||1),limit:s})}for(const r of c.get(`${a},${l}`)||[]){if(Gh(r.a)===t||Gh(r.b)===t)continue;const a=ec(o,r.a,r.b);a<=Bh||a<n-1e-9&&d.push({rule:"distance",subject:`${t} → ${String(r.id||Gh(r.a))}`,actual:a/i*(e||1),limit:s})}}return d}function sc(t,e,i,s,{minClearanceCm2:o=25}={}){const a=(e||[]).filter(Kh),n=a.length<3?0:Math.abs(a.reduce((t,e,i)=>{const s=a[(i+1)%a.length];return t+(e[0]*s[1]-s[0]*e[1])},0))/2,r=(i||1)/s,l=n*r*r;return l<o-1e-9?[{rule:"clearance",subject:t,actual:l,limit:o}]:[]}function oc(t,e){const i=new Map;for(const t of e||[])i.set(t.rule,(i.get(t.rule)||0)+1);const s=new Map;for(const e of t||[])s.set(e.rule,[...s.get(e.rule)||[],e]);const o=[];for(const[t,e]of s){const s=e.length-(i.get(t)||0);s>0&&o.push(...e.slice(0,s))}return o}const ac=new Set(["group","template","derivative","min_max","threshold","integration","statistics","trend","utility_meter","tod","switch_as_x","schedule"]);function nc(t){const{hass:e,devices:i,markers:s,showEntities:o,currentBinding:a,currentDeviceId:n,labels:r}=t,l=ce(s),h=new Set(s.filter(t=>t.removed).map(t=>t.binding)),c=new Set;for(const t of i)t.id!==n&&("device"===t.bindingKind&&t.bindingRef&&c.add(`device:${t.bindingRef}`),"entity"===t.bindingKind&&t.bindingRef&&c.add(`entity:${t.bindingRef}`));const d=new Set;for(const t of i)"device"===t.bindingKind&&t.name&&d.add(`${t.name.trim()}|${t.area||""}`);const p=[];for(const t of Object.values(e?.devices||{})){if(!t||"service"===t.entry_type)continue;const e=`device:${t.id}`;if(c.has(e))continue;const i=String(t.name_by_user||t.name||t.id).trim();e!==a&&!h.has(e)&&d.has(`${i}|${t.area_id||""}`)||p.push({value:e,label:i,sub:(t.model||r.device)+("Group"===t.model?r.z2mGroup:""),kind:"device",ref:t.id,areaId:t.area_id||"",model:t.model||""})}for(const[t,i]of Object.entries(e?.entities||{})){const s=`entity:${t}`;if(c.has(s))continue;if(de(e,t,l)&&!h.has(s))continue;const o=ac.has(i?.platform),a="group"===i?.platform;if(!o&&!a)continue;if(i?.hidden&&!h.has(s))continue;const n=e?.states?.[t];p.push({value:s,label:i?.name||n?.attributes?.friendly_name||t,sub:`${t.split(".")[0]} · ${a?r.group:r.helper}`,kind:"entity",ref:t,areaId:i?.area_id||i?.device_id&&e?.devices?.[i.device_id]?.area_id||"",model:"",parentDeviceId:i?.device_id||void 0})}if(o){const t=new Set(p.map(t=>t.value));for(const[i,s]of Object.entries(e?.entities||{})){const o=`entity:${i}`;if(c.has(o)||t.has(o)||s?.hidden&&!h.has(o))continue;const a=!!s?.device_id&&l.devices.has(s.device_id);if(de(e,i,l)&&!h.has(o)&&!a)continue;const n=e?.states?.[i],d=s?.device_id?e?.devices?.[s.device_id]:null,u=d?String(d.name_by_user||d.name||""):"";p.push({value:o,label:s?.name||n?.attributes?.friendly_name||i,sub:`${i.split(".")[0]} · ${r.entity}${u?` · ${u}`:""}`,kind:"entity",ref:i,areaId:s?.area_id||d?.area_id||"",model:"",parentDeviceId:s?.device_id||void 0})}}return p.sort((t,e)=>t.label.localeCompare(e.label)||t.value.localeCompare(e.value))}const rc={kind:"active",enabledEntityIds:[],allEntityIds:[]};function lc(t){return t.startsWith("entity:")?"entity":"device"}function hc(t){const e=t.binding.indexOf(":"),i=e>=0?t.binding.slice(e+1):"",s=Object.keys(t).filter(t=>!["id","binding","hidden"].includes(t));return t.id===`h${i}`&&0===s.length}function cc(t,e="main"){const{dialog:i,device:s}=t;if(!s)return p``;t.setup.syncMarker(s.marker?.id||s.id);const o=La(s,t.registryHass),a="saved_unsupported"===o.reason,n=()=>t.updateDialog({radar:i.radar,radarTouched:!0,radarRemove:!0}),r=()=>{i.radar?t.updateDialog({radar:i.radar,radarEligible:!0,radarTouched:!0,radarRemove:!1}):(()=>{const e=t.spaceModelById(s.space)||t.currentSpace();if(!e)return;const i=t.position(s),o=Ra(s,e,[i.x,i.y],t.registryHass,!0);o&&t.updateDialog({radar:o,radarEligible:!0,radarTouched:!0,radarRemove:!1})})()},l=!!i.radar&&!i.radarRemove;!l&&t.setup.isActive()&&t.setup.reset();const h=Io({id:"marker-radar-presence",icon:"mdi:radar",title:t.t("radar.declare"),caption:"ld2450"===o.reason?t.t("radar.detected_ld2450"):"radar_metadata"===o.reason?t.t("radar.detected"):void 0,checked:l||a,disabled:a||"virtual"===i.bindingMode,onChange:t=>{t?r():n()}});if(a||"virtual"===i.bindingMode&&s.marker?.radar)return p`<div class="radaradditional">
|
||
========
|
||
`}}vl.properties={hass:{attribute:!1},value:{attribute:!1},embedded:{type:Boolean,reflect:!0},savedEnabled:{type:Boolean,attribute:"saved-enabled"},devices:{attribute:!1},registry:{attribute:!1}},vl.styles=Et`:host{display:block;color:inherit;font:inherit;}.section{margin-top:18px;font-weight:700;display:flex;align-items:center;gap:2px;}.toggle{display:flex;align-items:center;gap:10px;margin-top:10px;}.hint,.status{color:var(--secondary-text-color,#9aa0aa);font-size:12px;line-height:1.45;}.hint{margin-top:6px;}.providers{display:grid;gap:14px;margin-top:12px;padding-left:34px;}.provider{display:grid;gap:7px;}.provider-title{font-weight:650;}.actions{display:flex;align-items:center;flex-wrap:wrap;gap:8px;}textarea{box-sizing:border-box;width:100%;min-height:58px;resize:vertical;border:1px solid var(--divider-color,#666);border-radius:8px;padding:8px;color:var(--primary-text-color,inherit);background:var(--card-background-color,#202126);font:inherit;}button{display:inline-flex;align-items:center;gap:6px;min-height:36px;border:1px solid var(--divider-color,#666);border-radius:9px;padding:7px 11px;color:inherit;background:transparent;cursor:pointer;font:inherit;font-weight:600;}button:disabled,textarea:disabled{opacity:.5;cursor:default;}.warning{color:var(--warning-color,#d89300);font-size:12px;line-height:1.45;}:host([embedded]){display:grid;gap:12px;}:host([embedded]) textarea.hpf-input{min-height:72px;border-radius:7px;padding:8px 10px;border-color:var(--hpf-line,var(--divider-color,#666));background:var(--hpf-surface,var(--card-background-color,#202126));}:host([embedded]) textarea[aria-invalid="true"]{border-color:var(--hpf-danger,var(--error-color,#db543d));}:host([embedded]) .hpf-actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;}:host([embedded]) button{min-height:44px;border-radius:8px;padding:9px 14px;font-weight:400;border-color:var(--hpf-line,var(--divider-color,#666));}:host([embedded]) .hpf-hint{margin:0;}`,customElements.get("hp-zigbee-topology-settings")||customElements.define("hp-zigbee-topology-settings",vl);const yl=(t,e)=>[t[0]-e[0],t[1]-e[1]],wl=(t,e)=>[t[0]+e[0],t[1]+e[1]],$l=(t,e)=>t[0]*e[0]+t[1]*e[1],kl=t=>Math.hypot(t[0],t[1]);function xl(t){let e=0;for(let s=0;s<t.length;s++){const i=t[s],o=t[(s+1)%t.length];e+=i[0]*o[1]-o[0]*i[1]}return e/2}function Ml(t,e,s){const i=yl(s,e),o=$l(i,i);if(o<1e-12)return kl(yl(t,e));let a=$l(yl(t,e),i)/o;return a=Math.max(0,Math.min(1,a)),kl(yl(t,[e[0]+i[0]*a,e[1]+i[1]*a]))}function Cl(t,e){const s=t[e],i=t[(e+1)%t.length],o=yl(i,s),a=kl(o)||1;let n=[o[1]/a,-o[0]/a];const r=[(s[0]+i[0])/2,(s[1]+i[1])/2],l=Math.max(.01*a,1e-4);return function(t,e){let s=!1;for(let i=0,o=e.length-1;i<e.length;o=i++){const a=e[i][0],n=e[i][1],r=e[o][0],l=e[o][1];n>t[1]!=l>t[1]&&t[0]<(r-a)*(t[1]-n)/(l-n)+a&&(s=!s)}return s}([r[0]+n[0]*l,r[1]+n[1]*l],t)&&(n=[-n[0],-n[1]]),n}function Sl(t){const e=t.length;if(e<3)return!1;for(let s=0;s<e;s++)for(let i=s+1;i<e;i++)if(i!==s&&(i+1)%e!==s&&(s+1)%e!==i&&Jt(t[s],t[(s+1)%e],t[i],t[(i+1)%e]))return!1;return!0}function Pl(t,e,s=1e-6){let i=1/0;for(const[o,a]of e){const e=yl(a,o),n=kl(e);if(n<s)continue;const r=[e[0]/n,e[1]/n],l=t=>(t[0]-o[0])*r[1]-(t[1]-o[1])*r[0],h=t=>(t[0]-o[0])*r[0]+(t[1]-o[1])*r[1],c=s,d=n-s;for(const e of t){const t=Math.abs(l(e));if(t<=s)continue;const o=h(e);o<=c||o>=d||t<i&&(i=t)}for(let e=0;e<t.length;e++){const o=t[e],a=t[(e+1)%t.length],n=l(o),r=l(a);if(Math.abs(n)<=s||Math.abs(r)<=s)continue;const p=h(o),u=h(a),_=Math.max(c,Math.min(p,u)),m=Math.min(d,Math.max(p,u));if(m-_<=s)continue;const g=u-p;if(Math.abs(g)<s){i=Math.min(i,Math.abs(n),Math.abs(r));continue}const f=t=>Math.abs(n+(t-p)/g*(r-n));i=Math.min(i,f(_),f(m))}}return i}function Il(t,e,s){if(Xt(t,e,s))return!0;if(Yt(t,e,s)||Yt(e,t,s))return!1;let i=0;try{const s=Qt([[...t.map(t=>[t[0],t[1]]),[t[0][0],t[0][1]]]],[[...e.map(t=>[t[0],t[1]]),[e[0][0],e[0][1]]]]);for(const t of s)t?.[0]&&(i+=te(t[0]))}catch{return!1}return i>Math.max(1e-7,s*s)}function Dl(t,e,s){for(const i of e)for(let e=0;e<i.length;e++){const o=i[e],a=i[(e+1)%i.length],n=yl(a,o),r=kl(n);if(r<s)continue;const l=[n[0]/r,n[1]/r];if(Math.abs((t.x-o[0])*l[1]-(t.y-o[1])*l[0])>s)continue;const h=(t.x-o[0])*l[0]+(t.y-o[1])*l[1];if(h-t.length/2>=-s&&h+t.length/2<=r+s)return!0}return!1}function Ll(t,e,s){const i=Math.abs(e[0]-t[0]),o=Math.abs(e[1]-t[1]);return i<=s&&o>s?"v":o<=s&&i>s?"h":null}function Tl(t,e,s){return Math.abs(t[0]-e[0])<=s&&Math.abs(t[1]-e[1])<=s}function Rl(t,e,s,i,o){return Tl(t,s,o)&&Tl(e,i,o)||Tl(t,i,o)&&Tl(e,s,o)}function zl(t,e,s,i,o){const a=Ll(t,e,o);return a&&Ll(s,i,o)===a?"h"===a?Math.abs(t[1]-s[1])>o||Math.abs(t[1]-i[1])>o?0:Math.max(0,Math.min(Math.max(t[0],e[0]),Math.max(s[0],i[0]))-Math.max(Math.min(t[0],e[0]),Math.min(s[0],i[0]))):Math.abs(t[0]-s[0])>o||Math.abs(t[0]-i[0])>o?0:Math.max(0,Math.min(Math.max(t[1],e[1]),Math.max(s[1],i[1]))-Math.max(Math.min(t[1],e[1]),Math.min(s[1],i[1]))):0}function Fl(t,e,s,i){const o=t.length,a=Ll(t[(e-1+o)%o],t[e],i),n=Ll(t[(e+1)%o],t[(e+2)%o],i),r="h"===s?"v":"h";return a===r&&n===r}function Nl(t){let e=1/0,s=1/0,i=-1/0,o=-1/0;for(const a of t)e=Math.min(e,a[0]),s=Math.min(s,a[1]),i=Math.max(i,a[0]),o=Math.max(o,a[1]);return[e,s,i,o]}function Al(t,e,s){const i=Nl(t),o=Nl(e);return i[2]<o[0]-s||o[2]<i[0]-s||i[3]<o[1]-s||o[3]<i[1]-s}function El(t,e,s,i){const o=i.eps;return"circle"===t.kind?Ml(t.center,e,s)<t.radius+(i.movingHalf||0)-o:zl(e,s,t.a,t.b,o)>o}const Ol=(t,e)=>"h"===e?t[0]:t[1],Bl=(t,e)=>"h"===e?t[1]:t[0];function Hl(t,e,s,i,o){const a=t.find(t=>t.id===e);if(!a)return null;const n=a.poly[s],r=a.poly[(s+1)%a.poly.length],l=Ll(n,r,o);if(!l)return null;const h=0===i?r:n,c=0===i?n:r,d=Ol(h,l),p=Ol(c,l),u=Bl(h,l),_=function(t,e,s,i){const o=[];for(const a of t)for(let t=0;t<a.poly.length;t++){const n=a.poly[t],r=a.poly[(t+1)%a.poly.length];if(Ll(n,r,i)!==e||Math.abs(Bl(n,e)-s)>i||Math.abs(Bl(r,e)-s)>i)continue;const l=Ol(n,e),h=Ol(r,e),c=Math.min(l,h),d=Math.max(l,h);d-c>i&&o.push({roomId:a.id,edge:t,lo:c,hi:d})}return o.sort((t,e)=>t.lo-e.lo||t.hi-e.hi||t.roomId.localeCompare(e.roomId)||t.edge-e.edge)}(t,l,u,o),m=function(t,e,s,i){const o=[e,s];for(const a of t){const t=Math.max(e,a.lo),n=Math.min(s,a.hi);n-t>i&&o.push(t,n)}const a=[...new Set(o)].sort((t,e)=>t-e),n=[];for(let e=0;e+1<a.length;e++){const s=a[e],o=a[e+1];if(o-s<=i)continue;const r=(s+o)/2,l=[...new Set(t.filter(t=>r>t.lo-i&&r<t.hi+i).map(t=>t.roomId))].sort();n.push({lo:s,hi:o,owners:l})}return n}(_,Math.min(d,p),Math.max(d,p),o);return!m.length||m.some(t=>t.owners.length<1||t.owners.length>2)?null:{roomId:e,edge:s,movedEndpoint:i,axis:l,line:u,fixed:d,moving:p,intervals:_,baseline:m}}function Wl(t,e,s){const i=[];for(const o of t.intervals){const a=e.polys[o.roomId];if(!a){i.push(o);continue}if(o.edge<0||o.edge>=a.length)continue;const n=a[o.edge],r=a[(o.edge+1)%a.length];if(Ll(n,r,s)!==t.axis||Math.abs(Bl(n,t.axis)-t.line)>s||Math.abs(Bl(r,t.axis)-t.line)>s)continue;const l=Ol(n,t.axis),h=Ol(r,t.axis),c=Math.min(l,h),d=Math.max(l,h);d-c>s&&i.push({...o,lo:c,hi:d})}return i}function jl(t,e,s){return new Set(t.filter(t=>e>t.lo-s&&e<t.hi+s).map(t=>t.roomId)).size}function Gl(t,e,s){for(const i of e.sideOwnership){const e=t.polys[i.roomId];if(!e)return!1;const o=e[i.edge],a=e[(i.edge+1)%e.length];if(Ll(o,a,s)!==i.axis)return!1;const n=Ol(0===i.movedEndpoint?o:a,i.axis),r=Wl(i,t,s),l=(i.moving>=i.fixed?i.baseline[i.baseline.length-1]:i.baseline[0]).owners.length;if(l<1||l>2)return!1;const h=Math.min(i.fixed,i.moving,n),c=Math.max(i.fixed,i.moving,n),d=[h,c,i.fixed,i.moving,n];for(const t of i.intervals)d.push(t.lo,t.hi);for(const t of r)d.push(t.lo,t.hi);const p=[...new Set(d.filter(t=>t>=h&&t<=c))].sort((t,e)=>t-e),u=Math.min(i.fixed,i.moving),_=Math.max(i.fixed,i.moving),m=Math.min(i.fixed,n),g=Math.max(i.fixed,n);for(let t=0;t+1<p.length;t++){const e=p[t],o=p[t+1];if(o-e<=s)continue;const a=(e+o)/2,n=a>u-s&&a<_+s,h=a>m-s&&a<g+s;if(!n&&!h)continue;const c=jl(i.intervals,a,s),d=jl(r,a,s);if(c>2||d>2)return!1;if(n&&h){if(c!==d)return!1}else if(!n&&h){if(d!==l||c>0&&c!==d)return!1}else if(2===c?2!==d:d>1)return!1}}return!0}function ql(t,e,s,i){const o=[s.n[0]*i,s.n[1]*i],a={polys:{},openings:{},movedSpans:{}};for(const e of s.roomIds){const i=t.find(t=>t.id===e),n=s.edgeByRoom[e];if(!i||null==n)continue;const r=(n+1)%i.poly.length;a.polys[e]=i.poly.map((t,e)=>e===n||e===r?wl(t,o):[...t]),a.movedSpans[e]=[[wl(i.poly[n],o),wl(i.poly[r],o)]]}for(const t of e)s.movingOpeningIds.includes(t.id)&&(a.openings[t.id]=[t.x+o[0],t.y+o[1]]);return a}function Ul(t,e,s,i,o,a,n,r){if(!function(t,e,s,i){if(Ml([t.x,t.y],e,s)>2*i)return!1;const o=kl(yl(s,e));if(o<=i)return!1;const a=[(s[0]-e[0])/o,(s[1]-e[1])/o],n=(t.x-e[0])*a[0]+(t.y-e[1])*a[1];return n>=-i&&n<=o+i}(t,e,s,r))return!0;if(Ml([t.x,t.y],i,o)>2*r)return!1;const l=0===a?i:o;return kl(yl([t.x,t.y],l))>=t.length/2+n-r}function Kl(t,e,s,i){const o=i.movingHalf||0;return"circle"===t.kind?Ml(t.center,e,s)<t.radius+o-i.eps:function(t,e,s,i){return Jt(t,e,s,i)?0:Math.min(Ml(t,s,i),Ml(e,s,i),Ml(s,t,e),Ml(i,t,e))}(e,s,t.a,t.b)<(t.half||0)+o-i.eps}function Vl(t,e,s,i,o){const{eps:a,minDim:n}=o;if(!Number.isFinite(i)||s.roomIds.length<1||s.roomIds.length>2)return!1;const r=ql(t,e,s,i);if(Object.keys(r.polys).length!==s.roomIds.length)return!1;if(!Gl(r,s,a))return!1;const l=new Set(s.roomIds),h=t=>r.polys[t.id]||t.poly;for(const i of s.roomIds){const l=t.find(t=>t.id===i),h=r.polys[i],c=s.edgeByRoom[i];if(!l||!h||h.length!==s.topology[i]||h.length!==l.poly.length||!Sl(h))return!1;const d=l.poly.length,p=(c-1+d)%d,u=[p,c,(c+1)%d];for(const t of u)if(Zt(h[t],h[(t+1)%d]))return!1;const _=xl(l.poly),m=xl(h);if(Math.abs(m)<a||_*m<=0)return!1;const g=[l.poly[c],l.poly[(c+1)%l.poly.length]],f=r.movedSpans[i],b=Pl(l.poly,[g],a);if(Pl(h,f,a)<Math.min(n,b)-a)return!1;const v=[l.poly[p],l.poly[c]],y=[h[p],h[c]],w=[l.poly[(c+1)%d],l.poly[(c+2)%d]],$=[h[(c+1)%d],h[(c+2)%d]],k=Ll(h[c],h[(c+1)%d],a),x="h"===k?"v":"v"===k?"h":null;if(!x||Ll(...y,a)!==x||Ll(...$,a)!==x)return!1;for(const t of e)if(!s.movingOpeningIds.includes(t.id)){if(!Ul(t,...v,...y,1,o.movingHalf||0,a))return!1;if(!Ul(t,...w,...$,0,o.movingHalf||0,a))return!1}}if(2===s.roomIds.length){const[t,e]=s.roomIds,i=r.polys[t],o=r.polys[e],n=s.edgeByRoom[t],l=s.edgeByRoom[e];if(!Rl(i[n],i[(n+1)%i.length],o[l],o[(l+1)%o.length],a))return!1}for(const e of s.roomIds){const s=t.find(t=>t.id===e),i=r.polys[e];for(const o of t){if(o.id===e||l.has(o.id))continue;const t=h(o);if(!Al(s.poly,o.poly,a)||!Al(i,t,a))if(Yt(s.poly,o.poly,a)){if(!Yt(i,t,a))return!1}else if(Yt(o.poly,s.poly,a)){if(!Yt(t,i,a))return!1}else if(Yt(i,t,a)||Yt(t,i,a)||Il(i,t,a))return!1}}const c=r.polys[s.roomId],d=s.edgeByRoom[s.roomId],p=c[d],u=c[(d+1)%c.length];if(Math.abs(i)>a)for(const t of o.obstacles||[])if(Kl(t,p,u,o))return!1;for(const t of e){if(!s.movingOpeningIds.includes(t.id))continue;const e=r.openings[t.id];if(!e||t.hosted)return!1;if(!Dl({...t,x:e[0],y:e[1]},[c],2*a))return!1}return!0}const Jl=new WeakMap,Zl=t=>"number"==typeof t&&Number.isFinite(t),Yl=(t,e)=>{const s=new Map;for(const i of t||[])!Zl(i?.cm)||!e&&i.cm<=0||s.set(i.cm,(s.get(i.cm)||0)+1);return s},Xl=t=>[String(t),"см"].join(" ");function Ql(t,e,s={}){if(s.allowClear)return[];const i=!0===s.exactMultiplicity,o=Yl(t,i),a=Yl(e,i),n=[];for(const[t,e]of o){const s=a.get(t)||0;0===s?n.push({invariant:"wall_records",kind:"lost",owner:Xl(t),reference:`было ${e}`,detail:"записи этой толщины исчезли целиком"}):i&&s!==e&&n.push({invariant:"wall_records",kind:"count",owner:Xl(t),reference:`было ${e}, стало ${s}`,detail:"изменилось число записей этой толщины"})}if(i)for(const[t,e]of a)o.has(t)||n.push({invariant:"wall_records",kind:"count",owner:Xl(t),reference:`было 0, стало ${e}`,detail:"появились записи новой толщины"});return n}class th{constructor(){this._selectedRoomId=null,this._session=null,this._eligibility=null}get dragging(){return null!==this._session}ownsPointer(t){return this._session?.pointerId===t}get selectedRoomId(){return this._selectedRoomId}get snapshotIdentity(){return this._session?.snapshotIdentity||null}get activePointerId(){return this._session?.pointerId??null}get moved(){return!0===this._session?.moved}get delta(){return this._session?.delta||0}get rooms(){return this._session?.rooms||null}get openings(){return this._session?.openings||null}get plan(){return this._session?.plan||null}get preview(){return this._session?.accepted?.preview||null}get liveLabels(){return this._session?.accepted?.labels||null}selectRoom(t){this._selectedRoomId=t}restoreSelection(t){this._selectedRoomId=t}escapeIdle(){return this._selectedRoomId?(this._selectedRoomId=null,"selection-cleared"):"exit-tool"}resolve(t,e,s){this._eligibility&&this._eligibility.context===t||(this._eligibility={context:t,values:new Map});const i=this._eligibility.values.get(e);if(i)return i;const o=s();return this._eligibility.values.set(e,o),o}begin(t){return!this._session&&(this._session={pointerId:t.pointerId,start:[...t.start],roomId:t.roomId,plan:t.plan,options:t.options,rooms:t.rooms,openings:t.openings,snapshotIdentity:t.snapshotIdentity,before:t.before,moved:!1,delta:0,changedRoomIds:[...t.plan.roomIds],rejectionNotified:!1,wallUnionBefore:t.wallUnionBefore,epochBefore:t.epochBefore,accepted:null},!0)}move(t){const e=this._session;if(!e||e.pointerId!==t.pointerId)return{kind:"no-op"};const s=(i=e.start,o=t.point,a=e.plan.n,[i?.[0],i?.[1],o?.[0],o?.[1],a?.[0],a?.[1]].every(Number.isFinite)?(o[0]-i[0])*a[0]+(o[1]-i[1])*a[1]:0);var i,o,a;const n=t.snap([e.plan.a[0]+e.plan.n[0]*s,e.plan.a[1]+e.plan.n[1]*s]),r=(n[0]-e.plan.a[0])*e.plan.n[0]+(n[1]-e.plan.a[1])*e.plan.n[1],l=function(t,e,s,i,o,a){if(!Number.isFinite(i)||Math.abs(i)<1e-9)return 0;const n=Math.sign(i),r=Math.abs(i),l=Math.max(Math.abs(o),1e-6);let h=Jl.get(s);h&&h.opts===a||(h={opts:a,values:new Map},Jl.set(s,h));const c=h.values;let d=0;for(let i=Math.min(l,r),o=0;o<4096&&i<=r+1e-9;o++,i=Math.min(r,i+l)){const o=n*i,h=`${o.toFixed(9)}|${l.toFixed(9)}`;let p=c.get(h);if(void 0===p&&(p=Vl(t,e,s,o,a),c.size<4096&&c.set(h,p)),!p)break;if(d=o,Math.abs(i-r)<=1e-9)break}return d}(e.rooms,e.openings,e.plan,r,t.step,e.options);if(e.moved&&l===e.delta)return{kind:"no-op"};const h=ql(e.rooms,e.openings,e.plan,l);let c;try{if(c=t.project(e.snapshotIdentity,h.polys,h.openings,e.changedRoomIds,e.rooms),!c.ok)return this._projectionRejected(e);if(Ql(c.value.beforeWalls,c.value.afterWalls,{exactMultiplicity:!0}).length)return this._projectionRejected(e)}catch{return this._projectionRejected(e)}const d=e.accepted,p={preview:c.value.preview,labels:null,artifact:c.value.artifact,beforeWalls:c.value.beforeWalls,afterWalls:c.value.afterWalls};e.accepted=p;try{t.publish(p.preview,p.artifact),p.labels=t.measure(h,e.plan)}catch{e.accepted=d;try{t.publish(d?.preview||null,d?.artifact||null)}catch{}return this._projectionRejected(e)}return e.moved=!0,e.delta=l,{kind:"accepted",preview:c.value.preview,labels:p.labels,artifact:c.value.artifact}}finish(t){const e=this._session;if(!e||e.pointerId!==t.pointerId)return{kind:"no-op"};const s=e.accepted;let i;if(e.moved&&Math.abs(e.delta)>1e-9&&s)if(t.currentSnapshotIdentity!==e.snapshotIdentity)i={kind:"rejected",reason:"stale-snapshot"};else if(Vl(e.rooms,e.openings,e.plan,e.delta,e.options))if(Ql(s.beforeWalls,s.afterWalls,{exactMultiplicity:!0}).length)i={kind:"rejected",reason:"wall-records"};else{let o=!1;try{o=t.validatePreview(s.preview)}catch{o=!1}i=o?{kind:"commit",preview:s.preview,before:e.before}:{kind:"rejected",reason:"invalid-candidate"}}else i={kind:"rejected",reason:"invalid-topology"};else i={kind:"no-op"};return this._session=null,"commit"===i.kind&&(this._eligibility=null),i}cancel(t,e){const s=this._session;if(!s||void 0!==e&&s.pointerId!==e)return{kind:"no-op"};this._session=null,this._eligibility=null;const i=t===s.snapshotIdentity;return{kind:"cancelled",restoreWallUnion:i?s.wallUnionBefore:null,restoreEpoch:i?s.epochBefore:null}}reset(){this._selectedRoomId=null,this._session=null,this._eligibility=null}_projectionRejected(t){const e=!t.rejectionNotified;return t.rejectionNotified=!0,{kind:"rejected",notify:e}}}const eh=t=>"object"==typeof t&&null!==t?t:null,sh=t=>Array.isArray(t)?t.flatMap(t=>{const e=eh(t);return e?[e]:[]}):[],ih=t=>{if(!Array.isArray(t))return null;const e=Number(t[0]),s=Number(t[1]);return Number.isFinite(e)&&Number.isFinite(s)?[e,s]:null};function oh(t){const e=(s=t.poly,Array.isArray(s)?s.flatMap(t=>{const e=ih(t);return e?[e]:[]}):[]);var s;if(e.length>=3)return e;const i=Number(t.x),o=Number(t.y),a=Number(t.w),n=Number(t.h);return[i,o,a,n].every(Number.isFinite)?[[i,o],[i+a,o],[i+a,o+n],[i,o+n]]:[]}function ah(t){if(!t.length)return null;const e=t.map(t=>t[0]),s=t.map(t=>t[1]);return{minX:Math.min(...e),minY:Math.min(...s),maxX:Math.max(...e),maxY:Math.max(...s)}}function nh(t,e){const s=eh(t);if(!s)return null;const i=sh(s.rooms),o=new Set(function(t,e){const s=sh(t),i=new Set(e);return s.flatMap(t=>{const e=String(t.id||"");return e&&i.has(e)?[e]:[]})}(i,e)),a=i.filter(t=>o.has(String(t.id||"")));if(!ah(a.flatMap(oh))||!a.length)return null;const n=Number(s.cell_cm),r=Number.isFinite(n)&&n>0?n:5,l=a.flatMap(t=>{const e=oh(t);return e.map((t,s)=>[t,e[(s+1)%e.length]])}),h=.02*E,c=(t,e,s)=>{const i=s[0]-e[0],o=s[1]-e[1],a=i*i+o*o,n=a>0?Math.max(0,Math.min(1,((t[0]-e[0])*i+(t[1]-e[1])*o)/a)):0;return Math.hypot(t[0]-e[0]-n*i,t[1]-e[1]-n*o)},d=(t,e)=>Math.min(...l.map(([s,i])=>((t,e,s,i)=>{const o=(t,e,s)=>(e[0]-t[0])*(s[1]-t[1])-(e[1]-t[1])*(s[0]-t[0]),a=o(t,e,s),n=o(t,e,i),r=o(s,i,t),l=o(s,i,e);return a*n<=h*h&&r*l<=h*h&&Math.min(t[0],e[0])<=Math.max(s[0],i[0])+h&&Math.min(s[0],i[0])<=Math.max(t[0],e[0])+h&&Math.min(t[1],e[1])<=Math.max(s[1],i[1])+h&&Math.min(s[1],i[1])<=Math.max(t[1],e[1])+h?0:Math.min(c(t,s,i),c(e,s,i),c(s,t,e),c(i,t,e))})(t,e,s,i))),p=t=>{const e=ih(t.a),s=ih(t.b);if(e&&s)return((t,e)=>l.some(([s,i])=>{const o=i[0]-s[0],a=i[1]-s[1],n=Math.hypot(o,a);if(!(n>h))return!1;const r=t=>Math.abs((t[0]-s[0])*a-(t[1]-s[1])*o)/n;if(r(t)>h||r(e)>h)return!1;const l=t=>((t[0]-s[0])*o+(t[1]-s[1])*a)/(n*n),c=l(t),d=l(e);return Math.min(1,Math.max(c,d))-Math.max(0,Math.min(c,d))>h}))(e,s);const[i]=String(t.key||"").split("@"),o=i?.split(",").map(Number)||[];return 2!==o.length||!o.every(Number.isFinite)||l.some(([t,e])=>c(o,t,e)<=h)},u=sh(s.walls).filter(p),_=sh(s.wall_segments).filter(p),m=Math.max(0,...[...u,..._].map(t=>Number(t.cm)).filter(Number.isFinite))/r*E/2,g=sh(s.partitions).filter(t=>{const e=ih(t.a),s=ih(t.b);if(!e||!s)return!0;const i=Math.max(0,Number(t.cm)||0)/r*E/2;return d(e,s)<=m+i+h}),f=sh(s.wall_columns).filter(t=>{const e=ih(t.center);if(!e)return!0;const s=Math.max(0,Number(t.cm)||0)/r*E;return l.some(([t,i])=>c(e,t,i)<=m+s+h)}),b=new Set(g.map(t=>String(t.id||"")).filter(Boolean)),v=sh(s.openings).filter(t=>{const e=eh(t.host);if("partition"===e?.kind)return b.has(String(e.id||""));const s=ih([t.x,t.y]);return!s||l.some(([t,e])=>c(s,t,e)<=h)});return{...s,rooms:a,walls:u,wall_segments:_,open_spans:sh(s.open_spans).filter(p),partitions:g,wall_columns:f,openings:v}}const rh=t=>"object"==typeof t&&null!==t?t:null,lh=t=>Array.isArray(t)?t.flatMap(t=>{const e=rh(t);return e?[e]:[]}):[],hh=t=>{if(!Array.isArray(t))return null;const e=Number(t[0]),s=Number(t[1]);return Number.isFinite(e)&&Number.isFinite(s)?[e,s]:null},ch=t=>JSON.stringify(t??null),dh=(t,e=1e8)=>`${Math.round(t[0]*e)},${Math.round(t[1]*e)}`,ph=(t,e,s=1e-8)=>Math.hypot(t[0]-e[0],t[1]-e[1])<=s,uh=(t,e,s)=>{const i=s[0]-e[0],o=s[1]-e[1],a=i*i+o*o,n=a>0?Math.max(0,Math.min(1,((t[0]-e[0])*i+(t[1]-e[1])*o)/a)):0;return Math.hypot(t[0]-e[0]-n*i,t[1]-e[1]-n*o)},_h=(t,e,s)=>(e[0]-t[0])*(s[1]-t[1])-(e[1]-t[1])*(s[0]-t[0]),mh=(t,e,s,i)=>{const o=2e-4*E,a=_h(t,e,s),n=_h(t,e,i),r=_h(s,i,t),l=_h(s,i,e);return a*n<=o*o&&r*l<=o*o&&Math.min(t[0],e[0])<=Math.max(s[0],i[0])+o&&Math.min(s[0],i[0])<=Math.max(t[0],e[0])+o&&Math.min(t[1],e[1])<=Math.max(s[1],i[1])+o&&Math.min(s[1],i[1])<=Math.max(t[1],e[1])+o?0:Math.min(uh(t,s,i),uh(e,s,i),uh(s,t,e),uh(i,t,e))},gh=t=>{const e=(s=t.poly,Array.isArray(s)?s.flatMap(t=>{const e=hh(t);return e?[e]:[]}):[]);var s;if(e.length>=3)return e;const i=Number(t.x),o=Number(t.y),a=Number(t.w),n=Number(t.h);return[i,o,a,n].every(Number.isFinite)?[[i,o],[i+a,o],[i+a,o+n],[i,o+n]]:[]},fh=t=>{const e=gh(t);return e.map((t,s)=>[t,e[(s+1)%e.length]])},bh=(t,e)=>Math.max(0,Number(t)||0)/e*E,vh=(t,e=15)=>{const s=Number(t.cm);return Number.isFinite(s)?Math.max(0,s):e},yh=t=>Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0]),wh=(t,e)=>{let s=Math.abs(yh(t)-yh(e));return s%=Math.PI,s=Math.min(s,Math.PI-s),s<=Math.PI/180&&Math.abs(t.cm-e.cm)<=1e-6};function $h(t,e){const s=rh(t),i=lh(s?.partitions).find(t=>t.id===e);if(!i)return null;const o=hh(i.a),a=hh(i.b),n=Number(i.cm);return!o||!a||!Number.isFinite(n)||n<0||ph(o,a)?null:{partitionId:e,a:o,b:a,cm:n}}function kh(t,e){const s=rh(t);if(!s)return null;const i=Number(s.cell_cm),o=Number.isFinite(i)&&i>0?i:5,a=bh(5,o),n=bh(e.cm,o)/2,r=lh(s.rooms),l=lh(s.wall_segments),h=new Map(l.map(t=>[String(t.id||""),t])),c=lh(s.walls),d=t=>{const e=Array.isArray(t.wall_ids)?t.wall_ids.map(String):[];return fh(t).map(([t,s],i)=>{const a=[h.get(e[i]),...c.filter(e=>{const i=hh(e.a),o=hh(e.b);if(i&&o)return mh(t,s,i,o)<=.02*E;const[a]=String(e.key||"").split("@"),n=hh(a?.split(",").map(Number));return!!n&&uh(n,t,s)<=.02*E})].filter(t=>!!t),n=Math.max(15,...a.map(t=>vh(t,15)));return{a:t,b:s,half:bh(n,o)/2}})},p=r.flatMap(t=>{const s=String(t.id||""),i=d(t).some(({a:t,b:s,half:i})=>mh(e.a,e.b,t,s)<=n+i+a);return s&&i?[s]:[]}),u=new Set(p);if(p.length){const t=r.filter(t=>u.has(String(t.id||""))).flatMap(d);for(const e of r){const s=String(e.id||"");s&&!u.has(s)&&(d(e).some(({a:e,b:s,half:i})=>t.some(t=>mh(e,s,t.a,t.b)<=i+t.half+.02*E))&&u.add(s))}}const _=[...u],m=r.filter(t=>u.has(String(t.id||""))),g=new Set(m.flatMap(t=>Array.isArray(t.wall_ids)?t.wall_ids.map(String):[])),f=lh(s.wall_segments).filter(t=>g.has(String(t.id||""))),b=m.flatMap(fh),v=lh(s.walls).filter(t=>{const e=hh(t.a),s=hh(t.b);if(e&&s)return b.some(([t,i])=>mh(e,s,t,i)<=.02*E);const[i]=String(t.key||"").split("@"),o=hh(i?.split(",").map(Number));return!o||b.some(([t,e])=>uh(o,t,e)<=.02*E)}),{segments:y,malformedPartitions:w}=function(t){const e=[],s=[];for(const i of lh(t.partitions)){const t=hh(i.a),o=hh(i.b);t&&o?e.push({key:`partition:${String(i.id||ch(i))}`,source:i,a:t,b:o,cm:vh(i,0)}):s.push(i)}return{segments:e,malformedPartitions:s}}(s),$=new Set(y.flatMap(t=>mh(e.a,e.b,t.a,t.b)<=n+bh(t.cm,o)/2+a?[t.key]:[]));let k=!0;for(;k;){k=!1;const t=y.filter(t=>$.has(t.key));for(const e of y)$.has(e.key)||t.some(t=>wh(t,e)&&(ph(t.a,e.a)||ph(t.a,e.b)||ph(t.b,e.a)||ph(t.b,e.b)))&&($.add(e.key),k=!0)}const x=new Set(y.filter(t=>$.has(t.key)).flatMap(t=>[dh(t.a),dh(t.b)]));for(const t of y)(x.has(dh(t.a))||x.has(dh(t.b)))&&$.add(t.key);const M=y.filter(t=>$.has(t.key)),C=M.map(t=>t.source).concat(w),S=lh(s.wall_columns).filter(t=>{const s=hh(t.center);if(!s)return!0;const i=bh(Number(t.cm),o)/2,r="circle"===t.shape?i:i*Math.SQRT2;return uh(s,e.a,e.b)<=n+r+a}),P=new Set(C.map(t=>String(t.id||""))),I=new Set(f.map(t=>String(t.id||""))),D=lh(s.openings).filter(t=>{const s=rh(t.host);if("partition"===s?.kind)return P.has(String(s.id||""));if("wall"===s?.kind&&I.has(String(s.id||"")))return!0;const i=hh([t.x,t.y]);return!i||uh(i,e.a,e.b)<=n+a}),L=lh(s.open_spans).filter(t=>{const s=hh(t.a),i=hh(t.b);return!s||!i||mh(e.a,e.b,s,i)<=n+a});return{space:{...s,rooms:m,walls:v,wall_segments:f,open_spans:L,openings:D,partitions:C,wall_columns:S},roomIds:_,segmentCount:f.length+M.length}}const xh=1e3;const Mh=(t,e)=>(t._clearGeometryGesture(),t._restoreGeometryStateLocal(e),t.host._showToast(t.host._t("toast.geometry_unsafe")),!1);function Ch(t,e,s){const{host:i}=t,o=i._serverCfg,a=i._activeWallChainPartitionIds[i._activeWallChainPartitionIds.length-1]||null,n=()=>t._commitPhysicalGeometry(e,s);if(!s||!o||!a||10!==Number(o.model_version||0))return n();const r=o.spaces.find(t=>t.id===s.spaceId);if(!r||!function(t,e,s){const i=rh(t),o=rh(e);if(!i||!o||String(i.spaceId||"")!==String(o.id||""))return!1;if(["rooms","openings","walls","wall_segments","open_spans","wall_columns","decor"].some(t=>ch(i[t]??[])!==ch(o[t]??[])))return!1;const a=rh(i.plan_transform)||{},n={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==o[t]&&(n[t]=o[t]);if(ch(a)!==ch(n))return!1;const r=lh(i.partitions),l=lh(o.partitions);if(l.length!==r.length+1||ch(l.slice(0,-1))!==ch(r))return!1;const h=l[l.length-1],c=hh(h.a),d=hh(h.b);return h.id===s&&!!c&&!!d&&!ph(c,d)&&Number.isFinite(Number(h.cm))&&Number(h.cm)>=0}(s,r,a))return n();let l;try{l=Qn(o).config}catch(e){return t._clearGeometryGesture(),t._restoreGeometryStateLocal(s),t._showWallModelMigrationBlocked(e),!1}const h=l.spaces.find(t=>t.id===s.spaceId),c=$h(h,a);if(!h||!c)return n();const d=JSON.parse(JSON.stringify(o));if(!t._restoreGeometryStateInConfig(d,s))return n();const p=d.spaces.find(t=>t.id===s.spaceId),u=kh(h,c),_=kh(p,c);if(!u||!_)return n();const m={...l,spaces:[u.space]},g={...d,spaces:[_.space]};let f=null,b=!1;try{const t=i._path.length>=2?i._path.map(t=>[t[0]/xh,t[1]/xh]):[];b=Ln(h)<=Ln(s,t)&&i._checkSpacePhysicalGeometry(m,s.spaceId,t=>{f=t}).ok}catch{b=!1}if(!b)return Mh(t,s);const v=t._junctionLimitsIntroduced(m,g,s.spaceId,f,u.roomIds);if(v.length)return t._clearGeometryGesture(),t._restoreGeometryStateLocal(s),i._showToast(t._junctionLimitLabel(v[0])),!1;er(o,l);const y=o.spaces.find(t=>t.id===s.spaceId),w=y?.partitions?.find(t=>t.id===a),$=i._activeWallChainPartitionIds.length-1;w&&$>=0&&i._path.length===i._wallChainSegmentCms.length+1&&(i._path[$]=[w.a[0]*xh,w.a[1]*xh],i._path[$+1]=[w.b[0]*xh,w.b[1]*xh],i._wallChainSegmentCms[$]=Number(w.cm)),t._recordGeometry(e,s);const k=i._pendingPhysicalWrites.get(s.spaceId);return i._pendingPhysicalWrites.set(s.spaceId,{before:k?.before||s,fingerprint:ee(y)}),t._saveConfig(),!0}const Sh=(t,e)=>[(t[0]-e.x)/Math.max(1e-9,e.w)*e.stageWidth,(t[1]-e.y)/Math.max(1e-9,e.h)*e.stageHeight];function Ph(t){const{poly:e,edge:s,text:i,view:o}=t,a=e[s],n=e[(s+1)%e.length],r=[(a[0]+n[0])/2,(a[1]+n[1])/2],l=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(t=>{let e=0;for(let s=0;s<t.length;s++){const i=t[s],o=t[(s+1)%t.length];e+=i[0]*o[1]-o[0]*i[1]}return e/2})(t)>=0?[-a/n,o/n]:[a/n,-o/n]}(e,s),h=Math.hypot(n[0]-a[0],n[1]-a[1])||1,c=[(n[0]-a[0])/h,(n[1]-a[1])/h],d=Sh(r,o),p=Sh(t.gearCenter,o),u=Math.max(34,7.2*i.length+12),_=Math.abs(l[0])>=Math.abs(l[1])?Math.max(28,u/2+4):Math.max(28,13),m=d[0]+l[0]*_,g=d[1]+l[1]*_,f=e=>{return s=m+c[0]*e,i=g+c[1]*e,o=u,a=18,n=p[0],r=p[1],l=t.gearWidthPx,h=t.gearHeightPx,2*Math.abs(s-n)<o+l+8&&2*Math.abs(i-r)<a+h+8;var s,i,o,a,n,r,l,h};let b=0;if(f(0)){const t=(Math.abs(c[0])>=Math.abs(c[1])?c[0]:c[1])>0?-1:1,e=Math.max(o.stageWidth,o.stageHeight,64);for(let s=4;s<=e;s+=4){const e=s*t;if(!f(e)){b=e;break}const i=-e;if(!f(i)){b=i;break}}}const v=l[0]*_+c[0]*b,y=l[1]*_+c[1]*b,w=Math.hypot(v,y)||1,$=y/w*12,k=[r[0]+v/w*12*o.w/Math.max(1,o.stageWidth),r[1]+$*o.h/Math.max(1,o.stageHeight)];return{anchor:r,offsetXPx:v,offsetYPx:y,tangentOffsetPx:b,side:Math.abs(l[0])>=Math.abs(l[1])?l[0]<0?"left":"right":l[1]<0?"above":"below",leader:{a:r,b:k}}}const Ih=t=>{let e=(t%360+360)%360;return e>180&&(e-=360),e};function Dh(t,e,s,i,o,a=0,n=[t,e],r){const l=1e-7,h=(t,e,s,i,o)=>{const a=Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*i)/o));return{t:a,x:e[0]+a*s,y:e[1]+a*i}},c=t=>{if(!t||!Number.isFinite(t[0])||!Number.isFinite(t[1]))return null;const e=Math.hypot(t[0],t[1]);return e>1e-9?[t[0]/e,t[1]/e]:null},d=c(r);let p=null;for(const r of i){const i=Number(r?.a?.[0]),u=Number(r?.a?.[1]),_=Number(r?.b?.[0]),m=Number(r?.b?.[1]);if(![i,u,_,m].every(Number.isFinite))continue;const g=_-i,f=m-u,b=g*g+f*f;if(!(b>1e-18))continue;const v=Math.sqrt(b),y=h(n,[i,u],g,f,b),w=Math.hypot(n[0]-y.x,n[1]-y.y);if(!(w<o))continue;let $=c(r.normal),k=0;if($){const t=r.axisA?.length>=2?r.axisA:r.a,e=r.axisB?.length>=2?r.axisB:r.b,s=Number(e[0])-Number(t[0]),i=Number(e[1])-Number(t[1]),o=s*s+i*i;if(o>1e-18&&[t[0],t[1],e[0],e[1]].every(Number.isFinite)){const e=h(n,t,s,i,o),a=(n[0]-e.x)*$[0]+(n[1]-e.y)*$[1];if(a>l)k=2;else if(a<-1e-7){if(r.roomSide)continue;k=-2}else d&&(k=$[0]*d[0]+$[1]*d[1])}}else{let t=n[0]-y.x,e=n[1]-y.y;const s=Math.hypot(t,e);if(s>l)t/=s,e/=s,k=2;else if(d)[t,e]=d,k=1;else{const s=i<_||i===_&&u<=m;t=-(s?f:-f)/v,e=(s?g:-g)/v}$=[t,e]}const x=h([t,e],[i,u],g,f,b);let M=x.t,C=x.x,S=x.y;if(Number.isFinite(a)&&a>0){const t=Math.round(M*v/a)*a;M=Math.max(0,Math.min(1,t/v)),C=i+M*g,S=u+M*f}const P=Ih(180*Math.atan2(-$[0],$[1])/Math.PI),I={cx:C+$[0]*(s/2),cy:S+$[1]*(s/2),angle:P,dist:w,sideScore:k,stableId:"string"==typeof r.stableId?r.stableId:""};(!p||I.dist<p.dist-l||Math.abs(I.dist-p.dist)<=l&&(I.sideScore>p.sideScore+l||Math.abs(I.sideScore-p.sideScore)<=l&&I.stableId.localeCompare(p.stableId)<0))&&(p=I)}return p&&{cx:p.cx,cy:p.cy,angle:p.angle,dist:p.dist}}const Lh=t=>Array.isArray(t)&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),Th=(t,e)=>{const s=t=>`${t[0].toFixed(9)},${t[1].toFixed(9)}`,i=s(t),o=s(e);return i<=o?`${i}|${o}`:`${o}|${i}`};function Rh(t,e,s,i,o,a,n=1){const r=[],l=new Map;for(const h of t||[]){const c="string"==typeof h?.id?h.id:"";if(!c)continue;const d=kt(t,c,e,s,i,o,a,n);if(d)for(let t=0;t<d.poly.length;t++){const e=d.poly[t],s=d.poly[(t+1)%d.poly.length];if(!Lh(e)||!Lh(s))continue;const i=s[0]-e[0],o=s[1]-e[1];if(!(Math.hypot(i,o)>1e-9))continue;const a=ne(d.poly,t),n=Number(d.offsets[t]),h=Number.isFinite(n)&&n>0?n:0,p=[e[0],e[1]],u=[s[0],s[1]],_=Th(p,u),m=l.get(_)||new Set;m.add(c),l.set(_,m),r.push({a:[p[0]+a[0]*h,p[1]+a[1]*h],b:[u[0]+a[0]*h,u[1]+a[1]*h],axisA:p,axisB:u,normal:a,owner:"room",stableId:`room:${c}:${_}`,roomId:c,atomId:_,half:h})}}const h=[];for(const t of r){const{atomId:e,half:s,...i}=t;if(!(1===l.get(e)?.size&&s>1e-9)){h.push(i);continue}const o=i.normal;h.push({...i,roomSide:"inside",stableId:`${i.stableId}:inside`}),h.push({...i,a:[i.axisA[0]-o[0]*s,i.axisA[1]-o[1]*s],b:[i.axisB[0]-o[0]*s,i.axisB[1]-o[1]*s],normal:[-o[0],-o[1]],roomSide:"outside",stableId:`${i.stableId}:outside`})}return h}function zh(t){const e=[],s=new Set;for(const i of t||[])if(Array.isArray(i)&&!(i.length<2))for(let t=0;t<i.length;t++){const o=i[t],a=i[(t+1)%i.length];if(!Lh(o)||!Lh(a))continue;if(!(Math.hypot(a[0]-o[0],a[1]-o[1])>1e-9))continue;const n=[o[0],o[1]],r=[a[0],a[1]],l=`physical:${Th(n,r)}`;s.has(l)||(s.add(l),e.push({a:n,b:r,axisA:[...n],axisB:[...r],normal:null,owner:"physical",stableId:l}))}return e}const Fh=new WeakMap;const Nh=1e-9,Ah=2e-7,Eh=1e7,Oh=t=>{const e=Math.sign(t)*Math.floor(Math.abs(t)*Eh+.5)/Eh;return Object.is(e,-0)?0:e},Bh=t=>`${Oh(t[0])},${Oh(t[1])}`,Hh=(t,e)=>Math.hypot(e[0]-t[0],e[1]-t[1]),Wh=(t,e,s)=>t/(e||1)*s,jh=(t,e)=>Math.atan2(e[1]-t[1],e[0]-t[0]),Gh=t=>Array.isArray(t)&&t.length>=2&&t.every(t=>Number.isFinite(t)),qh=t=>(t||[]).filter(t=>Gh(t?.a)&&Gh(t?.b)&&Hh(t.a,t.b)>Nh);function Uh(t,{minAngleDeg:e=15,maxValence:s=6}={}){const i=new Map;for(const e of qh(t))for(const[t,s]of[[e.a,e.b],[e.b,e.a]]){const e=i.get(Bh(t))||[];e.push(jh(t,s)),i.set(Bh(t),e)}const o=[];for(const[t,a]of i){if(a.length>s&&o.push({rule:"valence",subject:t,actual:a.length,limit:s}),a.length<2)continue;const i=[...a].sort((t,e)=>t-e);let n=1/0;for(let t=0;t<i.length;t++){let e=i[(t+1)%i.length]-i[t];t===i.length-1&&(e+=2*Math.PI);const s=180*e/Math.PI;s>Nh&&s<n&&(n=s)}n<e-1e-9&&o.push({rule:"angle",subject:t,actual:n,limit:e})}return o}const Kh=t=>(180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI%180+180)%180,Vh=(t,e,s=1)=>{const i=Math.abs(Kh(t)-Kh(e));return Math.min(i,180-i)<=s},Jh=t=>{const e=new Map;for(const s of t)for(const t of[s.a,s.b]){const i=e.get(Bh(t));i?i.push(s):e.set(Bh(t),[s])}return e};function Zh(t,e,s){const i=qh(e),o=s??Jh(i),a=new Set([t]);let n=Hh(t.a,t.b);const r=[t.a,t.b];for(;r.length;){const e=r.pop();for(const s of o.get(Bh(e))||[])a.has(s)||Vh(s,t)&&Number(s.cm||0)===Number(t.cm||0)&&(a.add(s),n+=Hh(s.a,s.b),r.push(s.a,s.b))}return n}function Yh(t,e,s,{minLengthCm:i=20}={}){const o=[],a=qh(t),n=Jh(a);for(const t of a){const r=Zh(t,a,n)/s*(e||1),l=Math.max(i,Number(t.cm)>0?Number(t.cm):0);r<l-1e-9&&o.push({rule:"length",subject:String(t.id||Bh(t.a)),actual:r,limit:l})}return o}const Xh=(t,e,s)=>{const i=s[0]-e[0],o=s[1]-e[1],a=i*i+o*o,n=a<=Nh?0:Math.max(0,Math.min(1,((t[0]-e[0])*i+(t[1]-e[1])*o)/a));return Math.hypot(t[0]-(e[0]+i*n),t[1]-(e[1]+o*n))};function Qh(t,e,s,{minDistanceCm:i=5}={}){const o=qh(t),a=new Map;for(const t of o)a.set(Bh(t.a),t.a),a.set(Bh(t.b),t.b);const n=Wh(i,e,s),r=n>Nh?n:1,l=(t,e)=>`${Math.floor(t/r)},${Math.floor(e/r)}`,h=new Map;for(const[t,e]of a){const s=l(e[0],e[1]),i=h.get(s);i?i.push([t,e]):h.set(s,[[t,e]])}const c=new Map;for(const t of o){const e=Math.min(t.a[0],t.b[0])-n,s=Math.max(t.a[0],t.b[0])+n,i=Math.min(t.a[1],t.b[1])-n,o=Math.max(t.a[1],t.b[1])+n;for(let a=Math.floor(e/r);a<=Math.floor(s/r);a++)for(let e=Math.floor(i/r);e<=Math.floor(o/r);e++){const s=`${a},${e}`,i=c.get(s);i?i.push(t):c.set(s,[t])}}const d=[];for(const[t,o]of a){const a=Math.floor(o[0]/r),l=Math.floor(o[1]/r);for(let r=-1;r<=1;r++)for(let c=-1;c<=1;c++)for(const[p,u]of h.get(`${a+r},${l+c}`)||[]){if(t>=p)continue;const a=Hh(o,u);a<=Ah||a<n-1e-9&&d.push({rule:"distance",subject:`${t} ↔ ${p}`,actual:a/s*(e||1),limit:i})}for(const r of c.get(`${a},${l}`)||[]){if(Bh(r.a)===t||Bh(r.b)===t)continue;const a=Xh(o,r.a,r.b);a<=Ah||a<n-1e-9&&d.push({rule:"distance",subject:`${t} → ${String(r.id||Bh(r.a))}`,actual:a/s*(e||1),limit:i})}}return d}function tc(t,e,s,i,{minClearanceCm2:o=25}={}){const a=(e||[]).filter(Gh),n=a.length<3?0:Math.abs(a.reduce((t,e,s)=>{const i=a[(s+1)%a.length];return t+(e[0]*i[1]-i[0]*e[1])},0))/2,r=(s||1)/i,l=n*r*r;return l<o-1e-9?[{rule:"clearance",subject:t,actual:l,limit:o}]:[]}function ec(t,e){const s=new Map;for(const t of e||[])s.set(t.rule,(s.get(t.rule)||0)+1);const i=new Map;for(const e of t||[])i.set(e.rule,[...i.get(e.rule)||[],e]);const o=[];for(const[t,e]of i){const i=e.length-(s.get(t)||0);i>0&&o.push(...e.slice(0,i))}return o}const sc=new Set(["group","template","derivative","min_max","threshold","integration","statistics","trend","utility_meter","tod","switch_as_x","schedule"]);function ic(t){const{hass:e,devices:s,markers:i,showEntities:o,currentBinding:a,currentDeviceId:n,labels:r}=t,l=ce(i),h=new Set(i.filter(t=>t.removed).map(t=>t.binding)),c=new Set;for(const t of s)t.id!==n&&("device"===t.bindingKind&&t.bindingRef&&c.add(`device:${t.bindingRef}`),"entity"===t.bindingKind&&t.bindingRef&&c.add(`entity:${t.bindingRef}`));const d=new Set;for(const t of s)"device"===t.bindingKind&&t.name&&d.add(`${t.name.trim()}|${t.area||""}`);const p=[];for(const t of Object.values(e?.devices||{})){if(!t||"service"===t.entry_type)continue;const e=`device:${t.id}`;if(c.has(e))continue;const s=String(t.name_by_user||t.name||t.id).trim();e!==a&&!h.has(e)&&d.has(`${s}|${t.area_id||""}`)||p.push({value:e,label:s,sub:(t.model||r.device)+("Group"===t.model?r.z2mGroup:""),kind:"device",ref:t.id,areaId:t.area_id||"",model:t.model||""})}for(const[t,s]of Object.entries(e?.entities||{})){const i=`entity:${t}`;if(c.has(i))continue;if(de(e,t,l)&&!h.has(i))continue;const o=sc.has(s?.platform),a="group"===s?.platform;if(!o&&!a)continue;if(s?.hidden&&!h.has(i))continue;const n=e?.states?.[t];p.push({value:i,label:s?.name||n?.attributes?.friendly_name||t,sub:`${t.split(".")[0]} · ${a?r.group:r.helper}`,kind:"entity",ref:t,areaId:s?.area_id||s?.device_id&&e?.devices?.[s.device_id]?.area_id||"",model:"",parentDeviceId:s?.device_id||void 0})}if(o){const t=new Set(p.map(t=>t.value));for(const[s,i]of Object.entries(e?.entities||{})){const o=`entity:${s}`;if(c.has(o)||t.has(o)||i?.hidden&&!h.has(o))continue;const a=!!i?.device_id&&l.devices.has(i.device_id);if(de(e,s,l)&&!h.has(o)&&!a)continue;const n=e?.states?.[s],d=i?.device_id?e?.devices?.[i.device_id]:null,u=d?String(d.name_by_user||d.name||""):"";p.push({value:o,label:i?.name||n?.attributes?.friendly_name||s,sub:`${s.split(".")[0]} · ${r.entity}${u?` · ${u}`:""}`,kind:"entity",ref:s,areaId:i?.area_id||d?.area_id||"",model:"",parentDeviceId:i?.device_id||void 0})}}return p.sort((t,e)=>t.label.localeCompare(e.label)||t.value.localeCompare(e.value))}const oc={kind:"active",enabledEntityIds:[],allEntityIds:[]};function ac(t){return t.startsWith("entity:")?"entity":"device"}function nc(t){const e=t.binding.indexOf(":"),s=e>=0?t.binding.slice(e+1):"",i=Object.keys(t).filter(t=>!["id","binding","hidden"].includes(t));return t.id===`h${s}`&&0===i.length}function rc(t,e="main"){const{dialog:s,device:i}=t;if(!i)return p``;t.setup.syncMarker(i.marker?.id||i.id);const o=Pa(i,t.registryHass),a="saved_unsupported"===o.reason,n=()=>t.updateDialog({radar:s.radar,radarTouched:!0,radarRemove:!0}),r=()=>{s.radar?t.updateDialog({radar:s.radar,radarEligible:!0,radarTouched:!0,radarRemove:!1}):(()=>{const e=t.spaceModelById(i.space)||t.currentSpace();if(!e)return;const s=t.position(i),o=Da(i,e,[s.x,s.y],t.registryHass,!0);o&&t.updateDialog({radar:o,radarEligible:!0,radarTouched:!0,radarRemove:!1})})()},l=!!s.radar&&!s.radarRemove;!l&&t.setup.isActive()&&t.setup.reset();const h=So({id:"marker-radar-presence",icon:"mdi:radar",title:t.t("radar.declare"),caption:"ld2450"===o.reason?t.t("radar.detected_ld2450"):"radar_metadata"===o.reason?t.t("radar.detected"):void 0,checked:l||a,disabled:a||"virtual"===s.bindingMode,onChange:t=>{t?r():n()}});if(a||"virtual"===s.bindingMode&&i.marker?.radar)return p`<div class="radaradditional">
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
${h}
|
||
<fieldset class="markerlightgroup radargroup">
|
||
<legend>${t.t("radar.title")}</legend>
|
||
<p class="muted">${t.t("radar.saved_unsupported")}</p>
|
||
<div class="row">
|
||
<button class="btn danger" type="button" @click=${n}>
|
||
<ha-icon icon="mdi:radar-off"></ha-icon>${t.t("radar.remove")}
|
||
</button>
|
||
</div>
|
||
</fieldset>
|
||
</div>`;if("virtual"===i.bindingMode)return p``;if(!l)return p`<div class="radaradditional">${h}</div>`;const c=i.radar,u=function(t,e){const i=Object.keys(e?.states||{});return{numeric:i.filter(t=>t.startsWith("sensor.")).sort(),binary:i.filter(t=>t.startsWith("binary_sensor.")).sort()}}(0,t.planHass),_=(e,i,s,o="radar.source_choose")=>p`<select class="areasel" @change=${t=>s(t.target.value)}>
|
||
<option value="" ?selected=${!e}>${t.t(o)}</option>
|
||
${e&&!i.includes(e)?p`<option value=${e} selected>${e} · ${t.t("radar.source_missing")}</option>`:d}
|
||
${i.map(i=>{const s=t.registryHass.entities?.[i],o=s?.device_id?t.registryHass.devices?.[s.device_id]:void 0,a=o?.name_by_user||o?.name||"",n=t.planHass.states?.[i]?.attributes?.friendly_name||i;return p`<option value=${i} ?selected=${i===e}>
|
||
${n} · ${i}${a?` · ${a}`:""}
|
||
</option>`})}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</select>`,m=(e,i=!0)=>{t.setup.reset(),t.updateDialog({radar:{...c,...e,calibrationOverride:i?void 0:c.calibrationOverride,inspection:void 0,inspectError:void 0},radarTouched:!0,radarRemove:!1})},g=t.spaceModelById(s.space)||t.currentSpace(),f=g?.rooms||[],b="esphome_ld2450_v1"===c.profile||"cartesian_v1"===c.profile,v=(e=c)=>{const i=f.find(t=>t.id===e.roomId);g&&i&&Na(e,g.cellCm||5)?((!Array.isArray(i.poly)||i.poly.length<3)&&t.toast(t.t("radar.no_contour")),t.setup.begin(s.marker?.id||s.id,e,i,g.cellCm||5,t.configRev)||t.toast(t.t("radar.invalid"))):t.toast(t.t("radar.invalid"))},y=(t,e,i)=>{const s=[...c[t]];s[e]=i,m({[t]:s})},w=(t,e,i)=>{const s=[...c[t]];s[e]=i,m({[t]:s})},$=(t,e,i)=>{const s=[...c[t]];s[e]=i,m({[t]:s})},k=()=>{c.xEntities.length>=8||m({xEntities:[...c.xEntities,""],yEntities:[...c.yEntities,""],distanceEntities:[...c.distanceEntities,""],angleEntities:[...c.angleEntities,""],slotPresenceEntities:[...c.slotPresenceEntities,""],swapXY:[...c.swapXY,!1],xSigns:[...c.xSigns,1],ySigns:[...c.ySigns,1]})},x=t=>m({xEntities:c.xEntities.filter((e,i)=>i!==t),yEntities:c.yEntities.filter((e,i)=>i!==t),distanceEntities:c.distanceEntities.filter((e,i)=>i!==t),angleEntities:c.angleEntities.filter((e,i)=>i!==t),slotPresenceEntities:c.slotPresenceEntities.filter((e,i)=>i!==t),swapXY:c.swapXY.filter((e,i)=>i!==t),xSigns:c.xSigns.filter((e,i)=>i!==t),ySigns:c.ySigns.filter((e,i)=>i!==t)});return p`<div class="radaradditional">
|
||
========
|
||
</select>`,m=(e,s=!0)=>{t.setup.reset(),t.updateDialog({radar:{...c,...e,calibrationOverride:s?void 0:c.calibrationOverride,inspection:void 0,inspectError:void 0},radarTouched:!0,radarRemove:!1})},g=t.spaceModelById(i.space)||t.currentSpace(),f=g?.rooms||[],b="esphome_ld2450_v1"===c.profile||"cartesian_v1"===c.profile,v=(e=c)=>{const s=f.find(t=>t.id===e.roomId);g&&s&&Ra(e,g.cellCm||5)?((!Array.isArray(s.poly)||s.poly.length<3)&&t.toast(t.t("radar.no_contour")),t.setup.begin(i.marker?.id||i.id,e,s,g.cellCm||5,t.configRev)||t.toast(t.t("radar.invalid"))):t.toast(t.t("radar.invalid"))},y=(t,e,s)=>{const i=[...c[t]];i[e]=s,m({[t]:i})},w=(t,e,s)=>{const i=[...c[t]];i[e]=s,m({[t]:i})},$=(t,e,s)=>{const i=[...c[t]];i[e]=s,m({[t]:i})},k=()=>{c.xEntities.length>=8||m({xEntities:[...c.xEntities,""],yEntities:[...c.yEntities,""],distanceEntities:[...c.distanceEntities,""],angleEntities:[...c.angleEntities,""],slotPresenceEntities:[...c.slotPresenceEntities,""],swapXY:[...c.swapXY,!1],xSigns:[...c.xSigns,1],ySigns:[...c.ySigns,1]})},x=t=>m({xEntities:c.xEntities.filter((e,s)=>s!==t),yEntities:c.yEntities.filter((e,s)=>s!==t),distanceEntities:c.distanceEntities.filter((e,s)=>s!==t),angleEntities:c.angleEntities.filter((e,s)=>s!==t),slotPresenceEntities:c.slotPresenceEntities.filter((e,s)=>s!==t),swapXY:c.swapXY.filter((e,s)=>s!==t),xSigns:c.xSigns.filter((e,s)=>s!==t),ySigns:c.ySigns.filter((e,s)=>s!==t)});return p`<div class="radaradditional">
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
${h}
|
||
<fieldset class="markerlightgroup radargroup">
|
||
<legend><span>${t.t("radar.title")}</span>${t.help("radar.help")}</legend>
|
||
<label class="srcrow">
|
||
${t.boolInput(c.enabled,t=>m({enabled:t},!1))}
|
||
<span>${t.t("radar.enabled")}</span>
|
||
</label>
|
||
<label class="srcrow">
|
||
${t.boolInput(c.showLive,t=>m({showLive:t},!1))}
|
||
<span>${t.t("radar.show_live")}</span>
|
||
</label>
|
||
<label for="radar-profile">${t.t("radar.profile")}</label>
|
||
<select id="radar-profile" class="areasel" @change=${t=>m({profile:t.target.value})}>
|
||
${["esphome_ld2450_v1","cartesian_v1","polar_v1","range_v1","zones_v1","presence_v1"].map(e=>p`<option value=${e} ?selected=${e===c.profile}>
|
||
${t.t(`radar.profile_${e}`)}
|
||
</option>`)}
|
||
</select>
|
||
<label for="radar-room">${t.t("radar.room")}</label>
|
||
<select id="radar-room" class="areasel" @change=${t=>m({roomId:t.target.value})}>
|
||
<option value="" ?selected=${!c.roomId}>${t.t("radar.room_choose")}</option>
|
||
${f.map(t=>p`<option value=${t.id||""}
|
||
?selected=${t.id===c.roomId}>${t.name}</option>`)}
|
||
</select>
|
||
|
||
${b?c.xEntities.map((e,i)=>p`
|
||
<div class="radartargetheading">
|
||
<strong>${t.t("radar.target",{n:i+1})}</strong>
|
||
${"cartesian_v1"===c.profile&&c.xEntities.length>1?p`<button class="iconbtn" type="button" title=${t.t("btn.delete")}
|
||
@click=${()=>x(i)}><ha-icon icon="mdi:close"></ha-icon></button>`:d}
|
||
</div>
|
||
<label>${t.t("radar.axis_x")}</label>
|
||
${_(e,u.numeric,t=>y("xEntities",i,t))}
|
||
<label>${t.t("radar.axis_y")}</label>
|
||
${_(c.yEntities[i]||"",u.numeric,t=>y("yEntities",i,t))}
|
||
${"cartesian_v1"===c.profile?p`
|
||
<label class="srcrow">
|
||
${t.boolInput(!0===c.swapXY[i],t=>((t,e,i)=>{const s=[...c[t]];s[e]=i,m({[t]:s})})("swapXY",i,t))}
|
||
<span>${t.t("radar.swap_axes")}</span>
|
||
</label>
|
||
<div class="colorrow radarcoordinates">
|
||
<label>${t.t("radar.axis_x_sign")}<select class="areasel"
|
||
@change=${t=>$("xSigns",i,-1===Number(t.target.value)?-1:1)}>
|
||
<option value="1" ?selected=${-1!==c.xSigns[i]}>+1</option>
|
||
<option value="-1" ?selected=${-1===c.xSigns[i]}>−1</option>
|
||
</select></label>
|
||
<label>${t.t("radar.axis_y_sign")}<select class="areasel"
|
||
@change=${t=>$("ySigns",i,-1===Number(t.target.value)?-1:1)}>
|
||
<option value="1" ?selected=${-1!==c.ySigns[i]}>+1</option>
|
||
<option value="-1" ?selected=${-1===c.ySigns[i]}>−1</option>
|
||
</select></label>
|
||
</div>
|
||
`:d}
|
||
<label>${t.t("radar.presence_gate")}</label>
|
||
${_(c.slotPresenceEntities[i]||"",u.binary,t=>w("slotPresenceEntities",i,t),"radar.source_optional")}
|
||
`):d}
|
||
${"cartesian_v1"===c.profile&&c.xEntities.length<8?p`<button class="btn ghost" type="button" @click=${k}>
|
||
<ha-icon icon="mdi:plus"></ha-icon>${t.t("radar.add_target")}
|
||
</button>`:d}
|
||
${"polar_v1"===c.profile?p`
|
||
${c.distanceEntities.map((e,i)=>p`
|
||
<div class="radartargetheading">
|
||
<strong>${t.t("radar.target",{n:i+1})}</strong>
|
||
${c.distanceEntities.length>1?p`<button class="iconbtn" type="button"
|
||
title=${t.t("btn.delete")} @click=${()=>x(i)}>
|
||
<ha-icon icon="mdi:close"></ha-icon></button>`:d}
|
||
</div>
|
||
<label>${t.t("radar.distance_source")}</label>
|
||
${_(e,u.numeric,t=>w("distanceEntities",i,t))}
|
||
<label>${t.t("radar.angle_source")}</label>
|
||
${_(c.angleEntities[i]||"",u.numeric,t=>w("angleEntities",i,t))}
|
||
<label>${t.t("radar.presence_gate")}</label>
|
||
${_(c.slotPresenceEntities[i]||"",u.binary,t=>w("slotPresenceEntities",i,t),"radar.source_optional")}
|
||
`)}
|
||
${c.distanceEntities.length<8?p`<button class="btn ghost" type="button"
|
||
@click=${k}><ha-icon icon="mdi:plus"></ha-icon>${t.t("radar.add_target")}</button>`:d}
|
||
<label>${t.t("radar.angle_unit")}</label>
|
||
<select class="areasel" @change=${t=>m({angleUnit:t.target.value})}>
|
||
<option value="degrees" ?selected=${"degrees"===c.angleUnit}>${t.t("radar.degrees")}</option>
|
||
<option value="radians" ?selected=${"radians"===c.angleUnit}>${t.t("radar.radians")}</option>
|
||
</select>
|
||
<label>${t.t("radar.angle_zero")}</label>
|
||
<select class="areasel" @change=${t=>m({angleZero:t.target.value})}>
|
||
<option value="forward" ?selected=${"forward"===c.angleZero}>${t.t("radar.angle_forward")}</option>
|
||
<option value="right" ?selected=${"right"===c.angleZero}>${t.t("radar.angle_right")}</option>
|
||
</select>
|
||
<label class="srcrow">
|
||
${t.boolInput(c.angleClockwise,t=>m({angleClockwise:t}))}
|
||
<span>${t.t("radar.angle_clockwise")}</span>
|
||
</label>
|
||
`:d}
|
||
${"range_v1"===c.profile?p`
|
||
${c.rangeEntities.map((e,i)=>p`
|
||
<div class="radartargetheading">
|
||
<strong>${t.t("radar.range_channel",{n:i+1})}</strong>
|
||
${c.rangeEntities.length>1?p`<button class="iconbtn" type="button"
|
||
title=${t.t("btn.delete")} @click=${()=>(t=>m({rangeEntities:c.rangeEntities.filter((e,i)=>i!==t),rangePresenceEntities:c.rangePresenceEntities.filter((e,i)=>i!==t)}))(i)}>
|
||
<ha-icon icon="mdi:close"></ha-icon></button>`:d}
|
||
</div>
|
||
<label>${t.t("radar.distance_source")}</label>
|
||
${_(e,u.numeric,t=>w("rangeEntities",i,t))}
|
||
<label>${t.t("radar.presence_gate")}</label>
|
||
${_(c.rangePresenceEntities[i]||"",u.binary,t=>w("rangePresenceEntities",i,t),"radar.source_optional")}
|
||
`)}
|
||
${c.rangeEntities.length<2?p`<button class="btn ghost" type="button"
|
||
@click=${()=>{c.rangeEntities.length>=2||m({rangeEntities:[...c.rangeEntities,""],rangePresenceEntities:[...c.rangePresenceEntities,""]})}}><ha-icon icon="mdi:plus"></ha-icon>${t.t("radar.add_range")}</button>`:d}
|
||
`:d}
|
||
${"zones_v1"===c.profile?p`
|
||
<label>${t.t("radar.zone_source")}</label>
|
||
${_(c.zoneEntity,"occupancy"===c.zoneKind?u.binary:u.numeric,t=>m({zoneEntity:t}))}
|
||
<select class="areasel" @change=${t=>m({zoneKind:t.target.value,zoneEntity:""})}>
|
||
<option value="occupancy" ?selected=${"occupancy"===c.zoneKind}>${t.t("radar.occupancy")}</option>
|
||
<option value="count" ?selected=${"count"===c.zoneKind}>${t.t("radar.count")}</option>
|
||
</select>
|
||
`:d}
|
||
<label>${t.t("radar.occupancy_source")}</label>
|
||
${_(c.occupancyEntity,u.binary,t=>m({occupancyEntity:t}),"radar.source_optional")}
|
||
<label>${t.t("radar.count_source")}</label>
|
||
${_(c.countEntity,u.numeric,t=>m({countEntity:t}),"radar.source_optional")}
|
||
<label>${t.t("radar.availability_source")}</label>
|
||
${_(c.availabilityEntity,u.binary,t=>m({availabilityEntity:t}),"radar.source_optional")}
|
||
|
||
<label class="dispsection">${t.t("radar.mount")}</label>
|
||
<p class="muted">${t.t("radar.mount_hint")}</p>
|
||
<div class="colorrow radarcoordinates">
|
||
<label>X <input class="tempin" inputmode="decimal" .value=${c.mountX}
|
||
@input=${t=>m({mountX:t.target.value})}></label>
|
||
<label>Y <input class="tempin" inputmode="decimal" .value=${c.mountY}
|
||
@input=${t=>m({mountY:t.target.value})}></label>
|
||
<label>${t.t("radar.heading")} <input class="tempin" type="number" min="0" max="359.999" step="1"
|
||
.value=${c.heading} @input=${t=>m({heading:t.target.value})}></label>
|
||
</div>
|
||
<div class="colorrow radarcoordinates">
|
||
<label>${t.t("radar.range_cm")} <input class="tempin" type="number" min="1" max="10000"
|
||
.value=${c.rangeCm} @input=${t=>m({rangeCm:t.target.value})}></label>
|
||
<label>${t.t("radar.fov_deg")} <input class="tempin" type="number" min="1" max="360"
|
||
.value=${c.fovDeg} @input=${t=>m({fovDeg:t.target.value})}></label>
|
||
</div>
|
||
${"esphome_ld2450_v1"!==c.profile&&"zones_v1"!==c.profile&&"presence_v1"!==c.profile?p`
|
||
<label>${t.t("radar.unit")}</label>
|
||
<select class="areasel" @change=${t=>m({unit:t.target.value})}>${["mm","cm","m","in","ft"].map(t=>p`
|
||
<option value=${t} ?selected=${t===c.unit}>${t}</option>`)}</select>
|
||
`:d}
|
||
<label class="srcrow">
|
||
${t.boolInput(c.mirror,t=>m({mirror:t}))}
|
||
<span>${t.t("radar.mirror")}</span>
|
||
</label>
|
||
<div class="row">
|
||
<button class="btn" type="button" @click=${()=>v()}>
|
||
<ha-icon icon="mdi:map-marker-radius"></ha-icon>${t.t("radar.configure_on_plan")}
|
||
</button>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${c.original?p`<button class="btn ghost" type="button" @click=${()=>v({...c,installationId:Ca(),calibrationOverride:void 0,inspection:void 0,inspectError:void 0})}>
|
||
<ha-icon icon="mdi:restart"></ha-icon>${t.t("radar.change_installation")}
|
||
</button>`:d}
|
||
<button class="btn" type="button" ?disabled=${c.inspectBusy} @click=${async()=>{if(c.inspectBusy||!g)return;const e=Na(c,g.cellCm||5);if(e){t.updateDialog({radar:{...c,inspectBusy:!0,inspectError:void 0}});try{const o=await t.hass.callWS({type:"houseplan/radar/setup/inspect",marker_id:s.marker?.id||s.id,draft_sources:{radar:e}});if(t.dialogDeviceId()!==i.devId)return;t.updateDialog({radar:{...c,inspectBusy:!1,inspection:o}})}catch(e){if(t.dialogDeviceId()!==i.devId)return;const s=`radar.error_${String(e&&"object"==typeof e&&"code"in e&&e.code||"invalid_radar")}`,o=t.t(s);t.updateDialog({radar:{...c,inspectBusy:!1,inspectError:o===s?t.t("radar.error_invalid_radar"):o}})}}else t.toast(t.t("radar.invalid"))}}>
|
||
========
|
||
${c.original?p`<button class="btn ghost" type="button" @click=${()=>v({...c,installationId:ka(),calibrationOverride:void 0,inspection:void 0,inspectError:void 0})}>
|
||
<ha-icon icon="mdi:restart"></ha-icon>${t.t("radar.change_installation")}
|
||
</button>`:d}
|
||
<button class="btn" type="button" ?disabled=${c.inspectBusy} @click=${async()=>{if(c.inspectBusy||!g)return;const e=Ra(c,g.cellCm||5);if(e){t.updateDialog({radar:{...c,inspectBusy:!0,inspectError:void 0}});try{const o=await t.hass.callWS({type:"houseplan/radar/setup/inspect",marker_id:i.marker?.id||i.id,draft_sources:{radar:e}});if(t.dialogDeviceId()!==s.devId)return;t.updateDialog({radar:{...c,inspectBusy:!1,inspection:o}})}catch(e){if(t.dialogDeviceId()!==s.devId)return;const i=`radar.error_${String(e&&"object"==typeof e&&"code"in e&&e.code||"invalid_radar")}`,o=t.t(i);t.updateDialog({radar:{...c,inspectBusy:!1,inspectError:o===i?t.t("radar.error_invalid_radar"):o}})}}else t.toast(t.t("radar.invalid"))}}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<ha-icon icon="mdi:radar"></ha-icon>
|
||
${c.inspectBusy?t.t("radar.checking"):t.t("radar.check_sources")}
|
||
</button>
|
||
</div>
|
||
${c.inspectError?p`<p class="error" role="alert">${c.inspectError}</p>`:d}
|
||
${c.inspection?.frame?p`<div class="radarinspection" aria-live="polite">
|
||
<strong>${t.t("radar.health")}</strong>
|
||
<span>${t.t(`radar.health_${c.inspection.frame.health||"unknown"}`)}</span>
|
||
<span>${t.t("radar.live_summary",{targets:c.inspection.frame.targets?.length||0,ranges:c.inspection.frame.ranges?.length||0})}</span>
|
||
${(c.inspection.sources||[]).map(e=>{const i="number"==typeof e.reported_at&&Number.isFinite(e.reported_at)?Math.max(0,Math.round(Date.now()/1e3-e.reported_at)):null;return p`<code>${e.entity_id}: ${e.state??"—"}${null==i?"":` · ${t.t("radar.report_age",{seconds:i})}`}</code>`})}
|
||
</div>`:d}
|
||
${t.setup.render()}
|
||
<div class="row">
|
||
<button class="btn danger" type="button" @click=${n}>
|
||
<ha-icon icon="mdi:radar-off"></ha-icon>${t.t("radar.remove")}
|
||
</button>
|
||
</div>
|
||
</fieldset>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</div>`}function dc(t,e,i,s,o){if(![...t,e,s,...o].every(Number.isFinite)||s<=0||Math.hypot(...o)>1e4)throw new Error("invalid_radar");const a=e*Math.PI/180,n=i?-1:1,r=240*s;return[t[0]+(n*o[0]*Math.cos(a)+o[1]*Math.sin(a))/r,t[1]+(n*o[0]*Math.sin(a)-o[1]*Math.cos(a))/r]}class pc{constructor(t){this.host=t,this.active=null,this.generation=0,this.timer=0}begin(t,e,i,s,o){return!!this.host.configFromDraft(e,s)&&(this.reset(),this.active={markerId:t,draft:e,room:i,cellCm:s,configRev:o,phase:"mount",mount:null,headingPoint:null,pendingPlan:null,refs:[],samples:[],ambiguous:!1,trail:[]},this.host.requestUpdate(),!0)}reset(){this.generation++,this.unsubscribe?.(),this.unsubscribe=void 0,clearInterval(this.timer),this.timer=0,this.active=null}async discardIfAllowed(){if(!this.active)return!0;return!!(null===this.active.mount&&"mount"===this.active.phase||await this.host.confirmDiscard())&&(this.reset(),this.host.requestUpdate(),!0)}cancel(){return this.discardIfAllowed()}isActive(){return null!==this.active}isDirty(){return!!this.active&&(null!==this.active.mount||"mount"!==this.active.phase)}syncMarker(t){this.active&&this.active.markerId!==t&&this.reset()}coordinateProfile(){return!!this.active&&["esphome_ld2450_v1","cartesian_v1","polar_v1"].includes(this.active.draft.profile)}choosePoint(t){const e=this.active,i=function(t){const e=t.currentTarget.getBoundingClientRect();return e.width>0&&e.height>0?[Math.max(0,Math.min(1,(t.clientX-e.left)/e.width)),Math.max(0,Math.min(1,(t.clientY-e.top)/e.height))]:null}(t);var s,o;e&&i&&!1!==t.isPrimary&&"capture"!==e.phase&&"checking"!==e.phase&&(e.error=void 0,"mount"===e.phase?(e.mount=i,e.phase="heading"):"heading"===e.phase&&e.mount?(e.headingPoint=i,e.draft={...e.draft,mountX:String(Number((1e3*e.mount[0]).toFixed(3))),mountY:String(Number((1e3*e.mount[1]).toFixed(3))),heading:String(Number((s=e.mount,o=i,(180*Math.atan2(o[0]-s[0],s[1]-o[1])/Math.PI%360+360)%360).toFixed(3)))},e.phase=this.coordinateProfile()?"reference_1":"solved",this.coordinateProfile()&&this.subscribe()):"reference_1"!==e.phase&&"reference_2"!==e.phase&&"check_reference"!==e.phase||(e.pendingPlan=i),this.host.requestUpdate())}async subscribe(){const t=this.active,e=this.host.hass()?.connection;if(!t||this.unsubscribe||"function"!=typeof e?.subscribeMessage)return;const i=this.host.configFromDraft(t.draft,t.cellCm);if(!i)return;const s=++this.generation;try{const o=await e.subscribeMessage(t=>{s===this.generation&&this.active&&this.receive(t)},{type:"houseplan/radar/setup/subscribe",marker_id:t.markerId,expected_config_rev:t.configRev,draft_sources:{radar:i}});s===this.generation&&this.active?"function"==typeof o&&(this.unsubscribe=o):"function"==typeof o&&o()}catch(t){if(s!==this.generation||!this.active)return;const e=`radar.error_${String(t&&"object"==typeof t&&"code"in t&&t.code||"not_ready")}`;this.active.error=this.host.t(e)===e?"radar.error_not_ready":e,this.host.requestUpdate()}}receive(t){const e=this.active;if(!e)return;const i=Date.now(),s=Array.isArray(t.local_targets)?t.local_targets.filter(t=>{return e=[t.x_cm,t.y_cm],Array.isArray(e)&&2===e.length&&e.every(t=>"number"==typeof t&&Number.isFinite(t));var e}):[],o=new Set(s.map(t=>String(t.slot||"target")));e.trail=e.trail.filter(t=>t.at>=i-8e3&&o.has(t.slot));for(const t of s){const s=[t.x_cm,t.y_cm],o=String(t.slot||"target"),a=e.solved?.headingDeg??Number(e.draft.heading),n=e.solved?.mirror??e.draft.mirror;if(e.mount)try{const t=dc(e.mount,a,n,e.cellCm,s),r=[...e.trail].reverse().find(t=>t.slot===o);r&&240*Math.hypot(t[0]-r.point[0],t[1]-r.point[1])*e.cellCm>100&&(e.trail=e.trail.filter(t=>t.slot!==o)),e.trail.push({at:i,slot:o,point:t})}catch{}}const a=[];for(const t of o)a.push(...e.trail.filter(e=>e.slot===t).slice(-32));if(e.trail=a.sort((t,e)=>t.at-e.at),("capture"===e.phase||"checking"===e.phase)&&i>=(e.countdownUntil||0)&&i<(e.captureUntil||0))if(1===s.length){const t=Number(s[0].reported_at);e.samples.push({at:Number.isFinite(t)?1e3*t:i,point:[s[0].x_cm,s[0].y_cm]})}else s.length>1&&(e.ambiguous=!0);this.host.requestUpdate()}startCapture(){const t=this.active;t?.pendingPlan&&this.coordinateProfile()&&(t.samples=[],t.ambiguous=!1,t.error=void 0,t.captureFor="reference_1"===t.phase?0:"reference_2"===t.phase?1:2,t.phase=2===t.captureFor?"checking":"capture",t.countdownUntil=Date.now()+1e4,t.captureUntil=t.countdownUntil+5e3,clearInterval(this.timer),this.timer=window.setInterval(()=>this.tick(),200),this.subscribe(),this.host.requestUpdate())}tick(){const t=this.active;if(!t||!t.captureUntil||Date.now()<t.captureUntil)return void this.host.requestUpdate();let e;clearInterval(this.timer),this.timer=0;try{if(t.ambiguous)throw new Error("ambiguous_target");if(t.samples.length<3||Math.max(...t.samples.map(t=>t.at))-Math.min(...t.samples.map(t=>t.at))<2e3)throw new Error("insufficient_samples");e=function(t){if(t.length<3)throw new Error("insufficient_samples");const e=t=>{const e=[...t].sort((t,e)=>t-e),i=Math.floor(e.length/2);return e.length%2?e[i]:(e[i-1]+e[i])/2},i=[e(t.map(t=>t[0])),e(t.map(t=>t[1]))];if(t.some(t=>Math.hypot(t[0]-i[0],t[1]-i[1])>15))throw new Error("bad_fit");return i}(t.samples.map(t=>t.point))}catch(e){return t.error="ambiguous_target"===String(e?.message)?"radar.ambiguous_target":"radar.insufficient_samples",t.phase=0===t.captureFor?"reference_1":1===t.captureFor?"reference_2":"check_reference",void this.host.requestUpdate()}if(2===t.captureFor&&t.solved&&t.mount&&t.pendingPlan){const i=dc(t.mount,t.solved.headingDeg,t.solved.mirror,t.cellCm,e);t.checkErrorCm=240*Math.hypot(i[0]-t.pendingPlan[0],i[1]-t.pendingPlan[1])*t.cellCm,t.phase="checked"}else t.pendingPlan&&(t.refs[t.captureFor||0]={plan:t.pendingPlan,local:e},t.pendingPlan=null,t.refs.length<2?t.phase="reference_2":this.solve());this.host.requestUpdate()}solve(){const t=this.active;if(t?.mount&&2===t.refs.length)try{t.solved=function(t,e,i,s){if(![...t,s,...e.flat(),...i.flat()].every(Number.isFinite)||s<=0)throw new Error("invalid_selection");if(e.some(t=>Math.hypot(...t)<50))throw new Error("bad_references");const o=Math.hypot(...e[0])*Math.hypot(...e[1]),a=(e[0][0]*e[1][0]+e[0][1]*e[1][1])/o,n=180*Math.acos(Math.max(-1,Math.min(1,a)))/Math.PI;if(n<20||n>160)throw new Error("bad_references");const r=240*s,l=i.map(e=>[(e[0]-t[0])*r,-(e[1]-t[1])*r]),h=[];for(const t of[!1,!0]){const i=e.map(([e,i])=>[t?-e:e,i]),s=i.reduce((t,e,i)=>t+e[0]*l[i][0]+e[1]*l[i][1],0),o=i.reduce((t,e,i)=>t+e[0]*l[i][1]-e[1]*l[i][0],0),a=Math.atan2(o,s),n=i.map(([t,e],i)=>{const s=t*Math.cos(a)-e*Math.sin(a),o=t*Math.sin(a)+e*Math.cos(a);return Math.hypot(s-l[i][0],o-l[i][1])}),r=e.every((t,e)=>{const i=Math.hypot(...t),s=Math.hypot(...l[e]);return Math.abs(i-s)<=Math.max(20,.15*s)}),c=Math.sqrt((n[0]**2+n[1]**2)/2);r&&c<=20&&Math.max(...n)<=30&&h.push({headingDeg:(180*-a/Math.PI%360+360)%360,mirror:t,rmsCm:c,errorsCm:n})}if(h.sort((t,e)=>t.rmsCm-e.rmsCm),!h.length)throw new Error("invalid_selection");if(h.length>1&&Math.abs(h[0].rmsCm-h[1].rmsCm)<10)throw new Error("ambiguous_sources");return h[0]}(t.mount,[t.refs[0].local,t.refs[1].local],[t.refs[0].plan,t.refs[1].plan],t.cellCm),t.draft={...t.draft,heading:String(Number(t.solved.headingDeg.toFixed(3))),mirror:t.solved.mirror},t.phase="solved",t.error=void 0}catch(e){const i=String(e?.message);t.error="ambiguous_sources"===i?"radar.ambiguous_sources":"bad_references"===i?"radar.bad_references":"radar.bad_fit",t.refs=[],t.phase="reference_1"}}beginCheck(){this.active?.solved&&(this.active.pendingPlan=null,this.active.phase="check_reference",this.host.requestUpdate())}interrupt(){this.active&&(this.reset(),this.host.requestUpdate())}apply(){const t=this.active;if(!t?.mount||!t.headingPoint)return;const e=t.solved?{method:"two_point",mirror:t.solved.mirror,cell_cm:t.cellCm,refs:t.refs.map(t=>({plan:{x:t.plan[0],y:t.plan[1]},local_cm:{x:t.local[0],y:t.local[1]}})),rms_cm:t.solved.rmsCm}:{method:this.coordinateProfile()?"manual":"not_required",mirror:t.draft.mirror,cell_cm:t.cellCm},i={...t.draft,calibrationOverride:e};this.reset(),this.host.apply(i),this.host.requestUpdate()}instruction(t){if("mount"===t.phase)return this.host.t("radar.step_place_mount");if("heading"===t.phase)return this.host.t("radar.step_place_heading");if("reference_1"===t.phase)return this.host.t("radar.step_reference",{n:1});if("reference_2"===t.phase)return this.host.t("radar.step_reference",{n:2});if("check_reference"===t.phase)return this.host.t("radar.step_check_reference");if("capture"===t.phase||"checking"===t.phase){const e=Math.max(0,Math.ceil(((t.countdownUntil||0)-Date.now())/1e3));return e>0?this.host.t("radar.countdown",{seconds:e}):this.host.t("radar.capturing")}return this.host.t("checked"===t.phase?"radar.check_complete":"radar.fit_ready")}render(){const t=this.active;if(!t)return d;const e=(t.room.poly||[]).map(t=>`${1e3*t[0]},${1e3*t[1]}`).join(" "),i=[...t.mount?[{point:t.mount,cls:"mount",label:"R"}]:[],...t.refs.map((t,e)=>({point:t.plan,cls:"reference",label:String(e+1)})),...t.pendingPlan?[{point:t.pendingPlan,cls:"pending",label:"+"}]:[]],s=!!t.pendingPlan&&["reference_1","reference_2","check_reference"].includes(t.phase),o=[...new Set(t.trail.map(t=>t.slot))].map(e=>t.trail.filter(t=>t.slot===e));return p`<div class="radarsetup" role="group" aria-label=${this.host.t("radar.configure")}>
|
||
========
|
||
</div>`}function lc(t,e,s,i,o){if(![...t,e,i,...o].every(Number.isFinite)||i<=0||Math.hypot(...o)>1e4)throw new Error("invalid_radar");const a=e*Math.PI/180,n=s?-1:1,r=240*i;return[t[0]+(n*o[0]*Math.cos(a)+o[1]*Math.sin(a))/r,t[1]+(n*o[0]*Math.sin(a)-o[1]*Math.cos(a))/r]}class hc{constructor(t){this.host=t,this.active=null,this.generation=0,this.timer=0}begin(t,e,s,i,o){return!!this.host.configFromDraft(e,i)&&(this.reset(),this.active={markerId:t,draft:e,room:s,cellCm:i,configRev:o,phase:"mount",mount:null,headingPoint:null,pendingPlan:null,refs:[],samples:[],ambiguous:!1,trail:[]},this.host.requestUpdate(),!0)}reset(){this.generation++,this.unsubscribe?.(),this.unsubscribe=void 0,clearInterval(this.timer),this.timer=0,this.active=null}async discardIfAllowed(){if(!this.active)return!0;return!!(null===this.active.mount&&"mount"===this.active.phase||await this.host.confirmDiscard())&&(this.reset(),this.host.requestUpdate(),!0)}cancel(){return this.discardIfAllowed()}isActive(){return null!==this.active}isDirty(){return!!this.active&&(null!==this.active.mount||"mount"!==this.active.phase)}syncMarker(t){this.active&&this.active.markerId!==t&&this.reset()}coordinateProfile(){return!!this.active&&["esphome_ld2450_v1","cartesian_v1","polar_v1"].includes(this.active.draft.profile)}choosePoint(t){const e=this.active,s=function(t){const e=t.currentTarget.getBoundingClientRect();return e.width>0&&e.height>0?[Math.max(0,Math.min(1,(t.clientX-e.left)/e.width)),Math.max(0,Math.min(1,(t.clientY-e.top)/e.height))]:null}(t);var i,o;e&&s&&!1!==t.isPrimary&&"capture"!==e.phase&&"checking"!==e.phase&&(e.error=void 0,"mount"===e.phase?(e.mount=s,e.phase="heading"):"heading"===e.phase&&e.mount?(e.headingPoint=s,e.draft={...e.draft,mountX:String(Number((1e3*e.mount[0]).toFixed(3))),mountY:String(Number((1e3*e.mount[1]).toFixed(3))),heading:String(Number((i=e.mount,o=s,(180*Math.atan2(o[0]-i[0],i[1]-o[1])/Math.PI%360+360)%360).toFixed(3)))},e.phase=this.coordinateProfile()?"reference_1":"solved",this.coordinateProfile()&&this.subscribe()):"reference_1"!==e.phase&&"reference_2"!==e.phase&&"check_reference"!==e.phase||(e.pendingPlan=s),this.host.requestUpdate())}async subscribe(){const t=this.active,e=this.host.hass()?.connection;if(!t||this.unsubscribe||"function"!=typeof e?.subscribeMessage)return;const s=this.host.configFromDraft(t.draft,t.cellCm);if(!s)return;const i=++this.generation;try{const o=await e.subscribeMessage(t=>{i===this.generation&&this.active&&this.receive(t)},{type:"houseplan/radar/setup/subscribe",marker_id:t.markerId,expected_config_rev:t.configRev,draft_sources:{radar:s}});i===this.generation&&this.active?"function"==typeof o&&(this.unsubscribe=o):"function"==typeof o&&o()}catch(t){if(i!==this.generation||!this.active)return;const e=`radar.error_${String(t&&"object"==typeof t&&"code"in t&&t.code||"not_ready")}`;this.active.error=this.host.t(e)===e?"radar.error_not_ready":e,this.host.requestUpdate()}}receive(t){const e=this.active;if(!e)return;const s=Date.now(),i=Array.isArray(t.local_targets)?t.local_targets.filter(t=>{return e=[t.x_cm,t.y_cm],Array.isArray(e)&&2===e.length&&e.every(t=>"number"==typeof t&&Number.isFinite(t));var e}):[],o=new Set(i.map(t=>String(t.slot||"target")));e.trail=e.trail.filter(t=>t.at>=s-8e3&&o.has(t.slot));for(const t of i){const i=[t.x_cm,t.y_cm],o=String(t.slot||"target"),a=e.solved?.headingDeg??Number(e.draft.heading),n=e.solved?.mirror??e.draft.mirror;if(e.mount)try{const t=lc(e.mount,a,n,e.cellCm,i),r=[...e.trail].reverse().find(t=>t.slot===o);r&&240*Math.hypot(t[0]-r.point[0],t[1]-r.point[1])*e.cellCm>100&&(e.trail=e.trail.filter(t=>t.slot!==o)),e.trail.push({at:s,slot:o,point:t})}catch{}}const a=[];for(const t of o)a.push(...e.trail.filter(e=>e.slot===t).slice(-32));if(e.trail=a.sort((t,e)=>t.at-e.at),("capture"===e.phase||"checking"===e.phase)&&s>=(e.countdownUntil||0)&&s<(e.captureUntil||0))if(1===i.length){const t=Number(i[0].reported_at);e.samples.push({at:Number.isFinite(t)?1e3*t:s,point:[i[0].x_cm,i[0].y_cm]})}else i.length>1&&(e.ambiguous=!0);this.host.requestUpdate()}startCapture(){const t=this.active;t?.pendingPlan&&this.coordinateProfile()&&(t.samples=[],t.ambiguous=!1,t.error=void 0,t.captureFor="reference_1"===t.phase?0:"reference_2"===t.phase?1:2,t.phase=2===t.captureFor?"checking":"capture",t.countdownUntil=Date.now()+1e4,t.captureUntil=t.countdownUntil+5e3,clearInterval(this.timer),this.timer=window.setInterval(()=>this.tick(),200),this.subscribe(),this.host.requestUpdate())}tick(){const t=this.active;if(!t||!t.captureUntil||Date.now()<t.captureUntil)return void this.host.requestUpdate();let e;clearInterval(this.timer),this.timer=0;try{if(t.ambiguous)throw new Error("ambiguous_target");if(t.samples.length<3||Math.max(...t.samples.map(t=>t.at))-Math.min(...t.samples.map(t=>t.at))<2e3)throw new Error("insufficient_samples");e=function(t){if(t.length<3)throw new Error("insufficient_samples");const e=t=>{const e=[...t].sort((t,e)=>t-e),s=Math.floor(e.length/2);return e.length%2?e[s]:(e[s-1]+e[s])/2},s=[e(t.map(t=>t[0])),e(t.map(t=>t[1]))];if(t.some(t=>Math.hypot(t[0]-s[0],t[1]-s[1])>15))throw new Error("bad_fit");return s}(t.samples.map(t=>t.point))}catch(e){return t.error="ambiguous_target"===String(e?.message)?"radar.ambiguous_target":"radar.insufficient_samples",t.phase=0===t.captureFor?"reference_1":1===t.captureFor?"reference_2":"check_reference",void this.host.requestUpdate()}if(2===t.captureFor&&t.solved&&t.mount&&t.pendingPlan){const s=lc(t.mount,t.solved.headingDeg,t.solved.mirror,t.cellCm,e);t.checkErrorCm=240*Math.hypot(s[0]-t.pendingPlan[0],s[1]-t.pendingPlan[1])*t.cellCm,t.phase="checked"}else t.pendingPlan&&(t.refs[t.captureFor||0]={plan:t.pendingPlan,local:e},t.pendingPlan=null,t.refs.length<2?t.phase="reference_2":this.solve());this.host.requestUpdate()}solve(){const t=this.active;if(t?.mount&&2===t.refs.length)try{t.solved=function(t,e,s,i){if(![...t,i,...e.flat(),...s.flat()].every(Number.isFinite)||i<=0)throw new Error("invalid_selection");if(e.some(t=>Math.hypot(...t)<50))throw new Error("bad_references");const o=Math.hypot(...e[0])*Math.hypot(...e[1]),a=(e[0][0]*e[1][0]+e[0][1]*e[1][1])/o,n=180*Math.acos(Math.max(-1,Math.min(1,a)))/Math.PI;if(n<20||n>160)throw new Error("bad_references");const r=240*i,l=s.map(e=>[(e[0]-t[0])*r,-(e[1]-t[1])*r]),h=[];for(const t of[!1,!0]){const s=e.map(([e,s])=>[t?-e:e,s]),i=s.reduce((t,e,s)=>t+e[0]*l[s][0]+e[1]*l[s][1],0),o=s.reduce((t,e,s)=>t+e[0]*l[s][1]-e[1]*l[s][0],0),a=Math.atan2(o,i),n=s.map(([t,e],s)=>{const i=t*Math.cos(a)-e*Math.sin(a),o=t*Math.sin(a)+e*Math.cos(a);return Math.hypot(i-l[s][0],o-l[s][1])}),r=e.every((t,e)=>{const s=Math.hypot(...t),i=Math.hypot(...l[e]);return Math.abs(s-i)<=Math.max(20,.15*i)}),c=Math.sqrt((n[0]**2+n[1]**2)/2);r&&c<=20&&Math.max(...n)<=30&&h.push({headingDeg:(180*-a/Math.PI%360+360)%360,mirror:t,rmsCm:c,errorsCm:n})}if(h.sort((t,e)=>t.rmsCm-e.rmsCm),!h.length)throw new Error("invalid_selection");if(h.length>1&&Math.abs(h[0].rmsCm-h[1].rmsCm)<10)throw new Error("ambiguous_sources");return h[0]}(t.mount,[t.refs[0].local,t.refs[1].local],[t.refs[0].plan,t.refs[1].plan],t.cellCm),t.draft={...t.draft,heading:String(Number(t.solved.headingDeg.toFixed(3))),mirror:t.solved.mirror},t.phase="solved",t.error=void 0}catch(e){const s=String(e?.message);t.error="ambiguous_sources"===s?"radar.ambiguous_sources":"bad_references"===s?"radar.bad_references":"radar.bad_fit",t.refs=[],t.phase="reference_1"}}beginCheck(){this.active?.solved&&(this.active.pendingPlan=null,this.active.phase="check_reference",this.host.requestUpdate())}interrupt(){this.active&&(this.reset(),this.host.requestUpdate())}apply(){const t=this.active;if(!t?.mount||!t.headingPoint)return;const e=t.solved?{method:"two_point",mirror:t.solved.mirror,cell_cm:t.cellCm,refs:t.refs.map(t=>({plan:{x:t.plan[0],y:t.plan[1]},local_cm:{x:t.local[0],y:t.local[1]}})),rms_cm:t.solved.rmsCm}:{method:this.coordinateProfile()?"manual":"not_required",mirror:t.draft.mirror,cell_cm:t.cellCm},s={...t.draft,calibrationOverride:e};this.reset(),this.host.apply(s),this.host.requestUpdate()}instruction(t){if("mount"===t.phase)return this.host.t("radar.step_place_mount");if("heading"===t.phase)return this.host.t("radar.step_place_heading");if("reference_1"===t.phase)return this.host.t("radar.step_reference",{n:1});if("reference_2"===t.phase)return this.host.t("radar.step_reference",{n:2});if("check_reference"===t.phase)return this.host.t("radar.step_check_reference");if("capture"===t.phase||"checking"===t.phase){const e=Math.max(0,Math.ceil(((t.countdownUntil||0)-Date.now())/1e3));return e>0?this.host.t("radar.countdown",{seconds:e}):this.host.t("radar.capturing")}return this.host.t("checked"===t.phase?"radar.check_complete":"radar.fit_ready")}render(){const t=this.active;if(!t)return d;const e=(t.room.poly||[]).map(t=>`${1e3*t[0]},${1e3*t[1]}`).join(" "),s=[...t.mount?[{point:t.mount,cls:"mount",label:"R"}]:[],...t.refs.map((t,e)=>({point:t.plan,cls:"reference",label:String(e+1)})),...t.pendingPlan?[{point:t.pendingPlan,cls:"pending",label:"+"}]:[]],i=!!t.pendingPlan&&["reference_1","reference_2","check_reference"].includes(t.phase),o=[...new Set(t.trail.map(t=>t.slot))].map(e=>t.trail.filter(t=>t.slot===e));return p`<div class="radarsetup" role="group" aria-label=${this.host.t("radar.configure")}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="radarsetup-head">
|
||
<strong>${this.instruction(t)}</strong>
|
||
<button class="iconbtn" type="button" title=${this.host.t("btn.cancel")}
|
||
@click=${()=>{this.cancel()}}><ha-icon icon="mdi:close"></ha-icon></button>
|
||
</div>
|
||
<svg viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMid meet"
|
||
@pointerdown=${t=>this.choosePoint(t)}
|
||
@pointercancel=${()=>this.interrupt()}>
|
||
<polygon class="room" points=${e}></polygon>
|
||
${o.map(t=>t.length>1?Tt`<polyline class="trail"
|
||
points=${t.map(t=>`${1e3*t.point[0]},${1e3*t.point[1]}`).join(" ")}></polyline>`:d)}
|
||
${t.mount&&t.headingPoint?Tt`<line class="heading"
|
||
x1=${1e3*t.mount[0]} y1=${1e3*t.mount[1]}
|
||
x2=${1e3*t.headingPoint[0]} y2=${1e3*t.headingPoint[1]}></line>`:d}
|
||
${i.map(t=>Tt`<g class=${t.cls}
|
||
transform="translate(${1e3*t.point[0]} ${1e3*t.point[1]})">
|
||
<circle r="18"></circle><text y="1">${t.label}</text></g>`)}
|
||
</svg>
|
||
<p class="muted">${this.host.t("radar.desktop_hint")}</p>
|
||
${t.error?p`<p class="error" role="alert">${this.host.t(t.error)}</p>`:d}
|
||
${null!=t.checkErrorCm?p`<p role="status">${this.host.t("radar.error_distance",{distance:pe(t.checkErrorCm,"mi"===this.host.hass()?.config?.unit_system?.length)})}</p>`:d}
|
||
<div class="row">
|
||
${s?p`<button class="btn" type="button" @click=${()=>this.startCapture()}>
|
||
${this.host.t("radar.start_measure")}</button>`:d}
|
||
${"solved"===t.phase?p`<button class="btn ghost" type="button"
|
||
@click=${()=>this.beginCheck()}>${this.host.t("radar.check_third")}</button>`:d}
|
||
${"solved"===t.phase||"checked"===t.phase?p`<button class="btn on" type="button" @click=${()=>this.apply()}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${this.host.t("btn.save")}</button>`:d}
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</div>`}}class uc{constructor(t){this.port=t,this.fallbacks=new WeakMap,this.reportedFingerprint=null}get clipboardFallback(){const t=this.port.dialog();return t?this.fallbacks.get(t)??null:null}diagnostics(t,e){return function(t,e,{cardVersion:i,now:s}){const o=new Map((e?.spaces||[]).map(t=>[String(t?.id||""),t]));return{kind:"houseplan-optimize-preflight",origin:"runtime",cardVersion:i,checkedAt:s.toISOString(),preflightFingerprint:t.fingerprint,failures:t.failures.map(t=>({spaceId:t.spaceId,displayName:t.displayName,reason:t.reason,detail:t.detail??null,spaceGeometryFingerprint:o.has(t.spaceId)?ee(o.get(t.spaceId)):null}))}}(t,e,{cardVersion:this.port.cardVersion(),now:new Date})}reportPreflightFailure(t,e){t.ok||t.fingerprint===this.reportedFingerprint||(this.reportedFingerprint=t.fingerprint,console.warn("[houseplan] optimize preflight failed",this.diagnostics(t,e)))}async copyDiagnostics(){const t=this.port.dialog(),e=t?.preflight;if(!t||!e||e.ok)return;const i=JSON.stringify(this.diagnostics(e,t.config??null),null,2);try{await navigator.clipboard.writeText(i),this.fallbacks.delete(t)&&this.port.requestUpdate(),this.port.showToast(this.port.t("gs.preflight_copied"))}catch{this.fallbacks.set(t,i),this.port.requestUpdate()}}preview(t){const e=this.port.config();if(!this.port.planReady()||!e)return;const i=e.spaces||[];let s;try{s=dr(e,this.port.layout()||{},this.port.referenceContext(t))}catch(t){return void this.port.showMigrationBlocked(t)}const o=s.changed?this.port.checkGeometry(s.config):null;o&&this.reportPreflightFailure(o,s.config);const a=Math.ceil(10*s.report.maxShiftCm)/10,n=i.find(t=>null!=t?.id&&String(t.id)===s.report.maxSpace),r=i.length>1&&n?String(n.title||n.id):"";this.port.setDialog({report:s.report,config:s.config,layout:s.layout,cm:a,where:r,preflight:o,changed:s.changed,busy:!1,removeLiveMissingPositions:t})}open(){this.preview(!1)}toggleLivePositions(){const t=this.port.dialog();t&&!t.busy&&t.report.liveMissingPositions.length&&this.preview(!t.removeLiveMissingPositions)}async run(){let t=this.port.dialog();if(!t||t.busy||!this.port.config()||!t.changed||!t.preflight?.ok)return;const e=xt(t.config);if(t.preflight.fingerprint!==e){const e=this.port.checkGeometry(t.config);if(this.reportPreflightFailure(e,t.config),t={...t,preflight:e},this.port.setDialog(t),!e.ok)return}this.port.clearGeometryGesture(),this.port.setDialog({...t,busy:!0});try{await this.port.commit(t.config,t.layout),this.port.setDialog(null),this.port.showToast(this.port.t("gs.align_done",{n:String(t.report.moved),m:String(t.report.migrated+t.report.canonicalized+t.report.coordsCanonicalized+t.report.latticeCoordinatesCanonicalized+t.report.wallsMerged+t.report.spansMerged+t.report.partitionsMerged+t.report.partitionsReconciled+t.report.openingsRehosted+t.report.wallsStraightened),r:String(t.report.spaceRefsRemapped+t.report.roomRefsRemapped+t.report.positionsRemapped+t.report.markersDetached+t.report.orphanRoomLabelsRemoved+t.report.orphanDevicePositionsRemoved+t.report.orphanGroupPositionsRemoved)}))}catch(t){const e=this.port.dialog();if(e&&this.port.setDialog({...e,busy:!1}),"wall_model_client_outdated"===t?.code)return void this.port.showToast(this.port.t("toast.wall_model_client_outdated"));"conflict"===t?.code&&await this.port.reloadAfterConflict(),this.port.showToast(this.port.t("toast.error",{err:this.port.errorText(t)}))}}render(){const t=this.port.dialog(),e=t.report,i=t.changed&&!t.preflight?.ok,s=t.preflight?.failures||[],o=s.slice(0,3).map(t=>t.displayName),a=o.length?o.join(", "):this.port.t("gs.align_preflight_space",{n:"1"}),n=Math.max(0,s.length-o.length),r=n?this.port.t("gs.align_preflight_more",{n:String(n)}):"",l=e.spaceRefsRemapped+e.roomRefsRemapped+e.positionsRemapped+e.markersDetached,h=e.migrated+e.canonicalized+e.coordsCanonicalized+e.wallSegmentsMigrated+e.roomDraftsMigrated+e.roomDraftSegmentsMigrated+e.wallsMerged+e.spansMerged+e.partitionsMerged+e.partitionsReconciled+e.openingsRehosted,c=e.moved+e.rotated+e.coordsCanonicalized+e.wallsStraightened,u=Math.ceil(10*e.maxStraightenShiftCm)/10,_=(this.port.config()?.spaces||[]).find(t=>String(t?.id||"")===e.maxStraightenSpace),m=(this.port.config()?.spaces||[]).length>1&&_?String(_.title||_.id):"",g=e.orphanRoomLabelsRemoved+e.orphanDevicePositionsRemoved+e.orphanGroupPositionsRemoved,f=e.liveMissingPositions.map(t=>t.name).filter(Boolean),b=f.slice(0,3).join(", "),v=Math.max(0,f.length-3),y=b?this.port.t("gs.optimize_live_names",{names:b,more:v?this.port.t("gs.optimize_reference_more",{n:String(v)}):""}):"",w=e.unverifiedPositions.some(t=>"registry_unavailable"===t.reason),$=t=>e.removedPositions.some(e=>e.id===t.id)?this.port.t("gs.optimize_detail_removed"):e.liveMissingPositions.some(e=>e.id===t.id)?this.port.t("gs.optimize_detail_live"):this.port.t("gs.optimize_detail_unverified"),k=t=>this.port.t("room_label"===t?"gs.optimize_detail_room_label":"group"===t?"gs.optimize_detail_group":"device"===t?"gs.optimize_detail_device":"gs.optimize_detail_unknown"),x=[...e.removedPositions,...e.liveMissingPositions.filter(t=>!e.removedPositions.some(e=>e.id===t.id)),...e.unverifiedPositions],M=x.slice(0,10),C=Math.max(0,x.length-M.length),S=this.clipboardFallback;return p`<hp-dialog .hass=${this.port.hass()} data-kind="settings" .title=${this.port.t("gs.align_title")} icon="mdi:broom"
|
||
dismiss-on-scrim @hp-close=${()=>this.port.setDialog(null)}>
|
||
<div class="body">
|
||
${i?p`
|
||
<p class="alignmsg">${this.port.t("gs.align_preflight_failed",{spaces:a,more:r})}</p>
|
||
${s.slice(0,10).map(t=>p`<p class="alignmsg">
|
||
${t.displayName}: ${this.port.t(`gs.preflight_reason_${t.reason}`)}
|
||
</p>`)}
|
||
${s.length>10?p`<p class="alignmsg">
|
||
${this.port.t("gs.align_preflight_more",{n:String(s.length-10)})}
|
||
</p>`:d}
|
||
<div class="rhint">${this.port.t("gs.align_preflight_hint")}</div>
|
||
${P=this.port.integrationVersion(),I=this.port.cardVersion(),"string"==typeof P&&P.length>0&&P!==I?p`
|
||
<div class="rhint">${this.port.t("gs.preflight_update_hint")}</div>`:d}
|
||
<div class="row">
|
||
<button class="btn ghost" @click=${()=>this.copyDiagnostics()}>
|
||
<ha-icon icon="mdi:content-copy"></ha-icon>
|
||
${this.port.t("gs.preflight_copy")}
|
||
</button>
|
||
</div>
|
||
${S?p`<details open>
|
||
<summary>${this.port.t("gs.preflight_copy")}</summary>
|
||
<pre style="user-select:text;white-space:pre-wrap">${S}</pre>
|
||
</details>`:d}`:t.changed?p`
|
||
${e.moved?p`<p class="alignmsg">${this.port.t("gs.align_count",{n:String(e.moved),total:String(e.total),cm:String(t.cm)})}</p>`:d}
|
||
${e.latticeCoordinatesCanonicalized?p`
|
||
<p class="alignmsg">${this.port.t("gs.optimize_lattice_summary",{n:String(e.latticeCoordinatesCanonicalized),cm:ue(e.latticeMaxShiftCm)})}</p>
|
||
${e.latticeSpaces.map(t=>p`<p class="alignmsg">${this.port.t("gs.optimize_lattice_space",{space:t.space,n:String(t.canonicalized),far:String(t.far)})}</p>`)}
|
||
`:d}
|
||
${t.where?p`<p class="alignmsg">${this.port.t("gs.align_where",{s:t.where})}</p>`:d}
|
||
${e.rotated?p`<p class="alignmsg">${this.port.t("gs.align_turned",{n:String(e.rotated)})}</p>`:d}
|
||
${e.wallSegmentsMigrated?p`<p class="alignmsg">${this.port.t("gs.wall_segments_migrated",{n:String(e.wallSegmentsMigrated)})}</p>`:d}
|
||
${e.roomDraftsMigrated||e.roomDraftSegmentsMigrated?p`
|
||
<p class="alignmsg">${this.port.t("gs.room_drafts_migrated",{drafts:String(e.roomDraftsMigrated),segments:String(e.roomDraftSegmentsMigrated)})}</p>`:d}
|
||
${e.legacyZeroWallsMigrated?p`<p class="alignmsg">${this.port.t("gs.zero_walls_migrated",{n:String(e.legacyZeroWallsMigrated)})}</p>`:d}
|
||
${h?p`<p class="alignmsg">${this.port.t("gs.optimize_changes",{m:String(e.migrated),c:String(e.canonicalized),p:String(e.coordsCanonicalized),w:String(e.wallsMerged),s:String(e.spansMerged),i:String(e.partitionsMerged)})}</p>`:d}
|
||
${e.partitionsReconciled?p`<p class="alignmsg">${this.port.t("gs.optimize_coincident_partitions",{n:String(e.partitionsReconciled)})}</p>`:d}
|
||
${e.openingsRehosted?p`<p class="alignmsg">${this.port.t("gs.optimize_openings_rehosted",{n:String(e.openingsRehosted)})}</p>`:d}
|
||
${e.wallsStraightened?p`<p class="alignmsg">${this.port.t("gs.optimize_walls_straightened",{n:String(e.wallsStraightened),cm:String(u)})}</p>`:d}
|
||
${m?p`<p class="alignmsg">${this.port.t("gs.optimize_walls_straightened_where",{s:m})}</p>`:d}
|
||
${e.glowSpacesMigrated||e.glowRoomsMigrated?p`<p class="alignmsg">${this.port.t("gs.optimize_glow_migration",{spaces:String(e.glowSpacesMigrated),rooms:String(e.glowRoomsMigrated)})}</p>`:d}
|
||
${c?p`<div class="rhint">${this.port.t("gs.align_warn")}</div>`:d}`:p`<p class="alignmsg">${this.port.t(e.liveMissingPositions.length||e.unverifiedPositions.length||e.nestedRefsUnresolved?"gs.optimize_no_automatic_changes":"gs.align_none")}</p>`}
|
||
${!i&&e.wallsStraightenSkipped?p`<p class="rhint">${this.port.t("gs.optimize_walls_straighten_skipped",{n:String(e.wallsStraightenSkipped)})}</p>`:d}
|
||
${l?p`<p class="alignmsg">${this.port.t("gs.optimize_references",{spaces:String(e.spaceRefsRemapped),rooms:String(e.roomRefsRemapped),positions:String(e.positionsRemapped),detached:String(e.markersDetached)})}</p>`:d}
|
||
${g?p`<p class="alignmsg">${this.port.t("gs.optimize_orphans_removed",{total:String(g),rooms:String(e.orphanRoomLabelsRemoved),devices:String(e.orphanDevicePositionsRemoved),groups:String(e.orphanGroupPositionsRemoved)})}</p>`:d}
|
||
${e.liveMissingPositions.length?p`<div class="optimize-live">
|
||
<p class="alignmsg">${this.port.t(t.removeLiveMissingPositions?"gs.optimize_live_positions_remove":"gs.optimize_live_positions",{n:String(e.liveMissingPositions.length),names:y})}</p>
|
||
<button class="btn ghost optimize-cleanup" type="button"
|
||
aria-pressed=${t.removeLiveMissingPositions?"true":"false"}
|
||
@click=${()=>this.toggleLivePositions()} ?disabled=${t.busy}>
|
||
<ha-icon icon=${t.removeLiveMissingPositions?"mdi:undo":"mdi:map-marker-remove-outline"}></ha-icon>
|
||
${this.port.t(t.removeLiveMissingPositions?"gs.optimize_live_keep":"gs.optimize_live_remove")}
|
||
</button>
|
||
${t.removeLiveMissingPositions?p`<div class="rhint optimize-selected" role="status">
|
||
${this.port.t("gs.optimize_live_selected")}
|
||
</div>`:d}
|
||
</div>`:d}
|
||
${e.unverifiedPositions.length?p`<div class="rhint" role="alert">
|
||
${this.port.t("gs.optimize_unverified",{n:String(e.unverifiedPositions.length)})}
|
||
${w?` ${this.port.t("gs.optimize_registry_limited")}`:""}
|
||
</div>`:d}
|
||
${e.nestedRefsUnresolved?p`<div class="rhint" role="alert">${this.port.t("gs.optimize_vacuum_warning",{n:String(e.nestedRefsUnresolved)})}</div>`:d}
|
||
${x.length?p`<details class="optimize-details">
|
||
<summary>${this.port.t("gs.optimize_details")}</summary>
|
||
<ul>
|
||
${M.map(t=>p`<li>${this.port.t("gs.optimize_detail_item",{status:$(t),kind:k(t.kind),id:t.id,space:t.spaceId})}</li>`)}
|
||
</ul>
|
||
${C?p`<div class="rhint">${this.port.t("gs.optimize_details_more",{n:String(C)})}</div>`:d}
|
||
</details>`:d}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.port.setDialog(null)}>${this.port.t("btn.cancel")}</button>
|
||
${t.changed&&t.preflight?.ok?p`
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>this.run()} ?disabled=${t.busy}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${t.busy?"…":this.port.t("gs.align_run")}
|
||
</button>`:d}
|
||
</div>
|
||
</hp-dialog>`;var P,I}}const _c=.001;function mc(t){return!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1])}function gc(t){return`${t[0].toFixed(6)},${t[1].toFixed(6)}`}function fc(t,e,i){return Math.abs(t[0]-e[0])<i&&Math.abs(t[1]-e[1])<i}function bc(t,e){const i=function(t,e){return t[0]-e[0]||t[1]-e[1]}(t,e)<=0?t:e,s=i===t?e:t;return[[i[0],i[1]],[s[0],s[1]]]}function vc(t){const[e,i]=bc(t.a,t.b);return`${t.kind}|${t.id}|${gc(e)}|${gc(i)}`}function yc(t,e,i){const[s,o]=bc(e,i);return`${vc(t)}|${gc(s)}|${gc(o)}`}function wc(t){return"room"===t?0:1}function $c(t,e,i){return fc(t,[e[0],e[1]],i)||fc(t,[e[2],e[3]],i)}function kc(t){const e=t.epsilon??_c,i=[];for(const[e,s]of _e(t.space.rooms).entries())s.length<4||i.push({a:[s[0],s[1]],b:[s[2],s[3]],kind:"room",id:`room-edge-${e}`,cuts:[]});for(const s of t.space.partitions||[])mc(s.a)&&mc(s.b)&&!fc(s.a,s.b,e)&&i.push({a:[s.a[0],s.a[1]],b:[s.b[0],s.b[1]],kind:"partition",id:s.id,cuts:[]});const s=i.filter(t=>"room"!==t.kind&&i.some(i=>i!==t&&function(t,e,i){const s=t.b[0]-t.a[0],o=t.b[1]-t.a[1],a=Math.hypot(s,o);if(!(a>i))return!1;const n=s/a,r=o/a,l=e=>Math.abs((e[0]-t.a[0])*r-(e[1]-t.a[1])*n);if(l(e.a)>i||l(e.b)>i)return!1;const h=(e.a[0]-t.a[0])*n+(e.a[1]-t.a[1])*r,c=(e.b[0]-t.a[0])*n+(e.b[1]-t.a[1])*r;return Math.min(a,Math.max(h,c))-Math.max(0,Math.min(h,c))>i}(t,i,e))),o=s.map(t=>{const[e,i]=bc(t.a,t.b);return{a:e,b:i,key:`hidden|${yc(t,e,i)}`,sourceKind:t.kind,sourceId:t.id}}).sort((t,e)=>t.key.localeCompare(e.key)),a=s.flatMap(t=>[t.a,t.b].map((e,i)=>({point:[e[0],e[1]],key:`hidden|${vc(t)}|endpoint-${i}`,sourceKind:"partition",sourceId:t.id}))).sort((t,e)=>t.key.localeCompare(e.key));return{segments:o,endpoints:a}}function xc(t){const e=t.epsilon??_c,i=t.roomCuts||[],s=new Map;for(const e of t.partitionCuts||[]){if("string"!=typeof e.hostId||!e.hostId||!mc(e.a)||!mc(e.b))continue;const t=s.get(e.hostId)||[];t.push([e.a[0],e.a[1],e.b[0],e.b[1]]),s.set(e.hostId,t)}const o=[];for(const[e,s]of _e(t.space.rooms).entries())s.length<4||o.push({a:[s[0],s[1]],b:[s[2],s[3]],kind:"room",id:`room-edge-${e}`,cuts:i});for(const e of t.space.partitions||[])mc(e.a)&&mc(e.b)&&o.push({a:[e.a[0],e.a[1]],b:[e.b[0],e.b[1]],kind:"partition",id:e.id,cuts:s.get(e.id)||[]});const a=new Map,n=new Map;for(const t of o){const i=[t.a[0],t.a[1],t.b[0],t.b[1]],s=me([i],t.cuts,e);if(s.length){for(const i of s){if(i.length<4)continue;const[s,o]=bc([i[0],i[1]],[i[2],i[3]]);if(fc(s,o,e))continue;const n=`${gc(s)}|${gc(o)}`,r={a:s,b:o,key:yc(t,s,o),sourceKind:t.kind,sourceId:t.id},l=a.get(n);(!l||wc(r.sourceKind)<wc(l.sourceKind)||wc(r.sourceKind)===wc(l.sourceKind)&&r.key.localeCompare(l.key)<0)&&a.set(n,r)}for(const i of[t.a,t.b]){if(!s.some(t=>$c(i,t,e)))continue;const t=gc(i);n.has(t)||n.set(t,{point:[i[0],i[1]],key:t})}}}return{segments:[...a.values()].sort((t,e)=>t.key.localeCompare(e.key)),endpoints:[...n.values()].sort((t,e)=>t.key.localeCompare(e.key))}}function Mc(t,e,i){return e.some(e=>mc(e)&&fc(t,e,i))}function Cc(t,e,i){if(!i)return!0;const s=t-i.distance;return s<-1e-9||Math.abs(s)<=1e-9&&e.localeCompare(i.key)<0}function Sc(t,e,i){const s=i.epsilon??_c,o=i.excludePoints||[],a=[...t.endpoints,...(i.extraEndpoints||[]).filter(t=>mc(t.point)).map(t=>({point:[t.point[0],t.point[1]],key:t.key}))],n=new Map;for(const t of a){if(Mc(t.point,o,s))continue;const e=gc(t.point),i=n.get(e);(!i||t.key.localeCompare(i.key)<0)&&n.set(e,t)}return[...n.values()].map(t=>({kind:"endpoint",point:[...t.point],key:t.key,distance:Math.hypot(e[0]-t.point[0],e[1]-t.point[1])})).filter(t=>t.distance<=i.tolerance).sort((t,e)=>t.distance-e.distance||t.key.localeCompare(e.key))}function Pc(t,e){if(!t.length)return null;if(e>0){const i=new Set;for(let s=0;s<t.length;s++)for(let o=s+1;o<t.length;o++)Math.hypot(t[s].point[0]-t[o].point[0],t[s].point[1]-t[o].point[1])<e&&(i.add(t[s].key),i.add(t[o].key));if(i.size>1)return{kind:"ambiguous",candidate:null,conflicts:t.filter(t=>i.has(t.key)).map(t=>({point:[...t.point],key:t.key}))}}return{kind:"resolved",candidate:t[0],conflicts:[]}}function Ic(t,e,i){const s=t.b[0]-t.a[0],o=t.b[1]-t.a[1],a=Math.hypot(s,o);if(!(a>0))return[...t.a];const n=s/a,r=o/a,l=Math.max(0,Math.min(a,(e[0]-t.a[0])*n+(e[1]-t.a[1])*r)),h=i>0?Math.max(0,Math.min(a,Math.round(l/i)*i)):l;return[t.a[0]+n*h,t.a[1]+r*h]}function Dc(t,e,i){if(!(mc(e)&&mc(i.anchor)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??_c,o=function(t,e){const i=e[0]-t[0],s=e[1]-t[1];if(!(Math.hypot(i,s)>Number.EPSILON))return null;const o=Math.round(Math.atan2(s,i)/(Math.PI/4))*(Math.PI/4);return[Math.cos(o),Math.sin(o)]}(i.anchor,e);if(!o)return{kind:"none",candidate:null,conflicts:[]};const a=Sc(t,e,i).filter(t=>function(t,e,i,s){const o=t[0]-e[0],a=t[1]-e[1];return o*i[0]+a*i[1]>s&&Math.abs(o*i[1]-a*i[0])<=s*Math.max(Math.hypot(o,a),1)}(t.point,i.anchor,o,s)),n=Pc(a,i.distinguishTolerance||0);if(n)return n;let r=null;for(const a of t.segments){const t=a.b[0]-a.a[0],n=a.b[1]-a.a[1],l=a.a[0]-i.anchor[0],h=a.a[1]-i.anchor[1],c=o[0]*n-o[1]*t;let d=null;if(Math.abs(c)<=s*Math.max(Math.hypot(t,n),1)){if(Math.abs(l*o[1]-h*o[0])>s*Math.max(Math.hypot(l,h),1))continue;const t=[a.a,a.b].map(t=>({point:t,along:(t[0]-i.anchor[0])*o[0]+(t[1]-i.anchor[1])*o[1]})).filter(t=>t.along>s).sort((t,e)=>t.along-e.along);t.length&&(d=[...t[0].point])}else{const e=(l*n-h*t)/c,a=(l*o[1]-h*o[0])/c;e>s&&a>=-s&&a<=1+s&&(d=[i.anchor[0]+o[0]*e,i.anchor[1]+o[1]*e])}if(!d)continue;const p=Math.hypot(e[0]-d[0],e[1]-d[1]);p>i.tolerance||Mc(d,i.excludePoints||[],s)||!Cc(p,a.key,r)||(r={kind:"line",point:d,key:a.key,distance:p,segment:a})}return r?{kind:"resolved",candidate:r,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}const Lc=.001;function Tc(t,e,i,s){const o=Number.isFinite(t)&&t>0?Math.floor(t):0,a=t=>"number"==typeof t&&Number.isFinite(t)&&t>=0?t:null,n=a(i),r=a(s)??0,l=[];let h=null;for(let t=0;t<o;t++){const i=a(e?.[t])??(t===o-1?n??h??r:h??n??r);l.push(i),h=i}return l}function Rc(t){return!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1])}function Fc(t,e,i,s){return t*s-e*i}function zc(t){let e=0;for(let i=0;i<t.length;i++){const s=t[i],o=t[(i+1)%t.length];e+=s[0]*o[1]-o[0]*s[1]}return e/2}function Nc(t,e){const i=Math.max(e,Number.EPSILON),s=Math.round(t[0]/i)*i,o=Math.round(t[1]/i)*i;return[Object.is(s,-0)?0:s,Object.is(o,-0)?0:o]}function Ec(t,e){const i=Nc(t,e);return`${Math.round(i[0]/e)},${Math.round(i[1]/e)}`}function Ac(t,e){return t.localeCompare(e)<=0?`${t}|${e}`:`${e}|${t}`}function Oc(t){if(!t.length)return"";const e=[];for(const i of[t,[...t].reverse()])for(let t=0;t<i.length;t++)e.push([...i.slice(t),...i.slice(0,t)].join(";"));return e.sort((t,e)=>t.localeCompare(e)),e[0]}function Bc(t,e,i){const s=[...t];for(let t=!0;t&&s.length>=3;){t=!1;for(let o=0;o<s.length;o++){const a=e.get(s[(o-1+s.length)%s.length]),n=e.get(s[o]),r=e.get(s[(o+1)%s.length]),l=n[0]-a[0],h=n[1]-a[1],c=r[0]-n[0],d=r[1]-n[1];if(Math.abs(Fc(l,h,c,d))<=i*Math.max(Math.hypot(l,h),Math.hypot(c,d),1)&&l*c+h*d>=0){s.splice(o,1),t=!0;break}}}return s}function Hc(t,e){const i=t.map(t=>Math.max(0,Math.min(1,t))).sort((t,e)=>t-e),s=[];for(const t of i)(!s.length||Math.abs(t-s[s.length-1])>e)&&s.push(t);return s}function Wc(t,e){return[t.a[0]+(t.b[0]-t.a[0])*e,t.a[1]+(t.b[1]-t.a[1])*e]}function Gc(t,e,i){const s=function(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],o=i*i+s*s;return o>0?((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/o:0}(t,e);if(s<-i||s>1+i)return null;const o=Wc(e,s);return Math.hypot(o[0]-t[0],o[1]-t[1])<=i?Math.max(0,Math.min(1,s)):null}function jc(t,e,i,s,o){const a=t.b[0]-t.a[0],n=t.b[1]-t.a[1],r=e.b[0]-e.a[0],l=e.b[1]-e.a[1],h=e.a[0]-t.a[0],c=e.a[1]-t.a[1],d=Fc(a,n,r,l),p=Math.max(Math.hypot(a,n),Math.hypot(r,l),1);if(Math.abs(d)>o*p){const t=Fc(h,c,r,l)/d,e=Fc(h,c,a,n)/d;return void(t>=-o&&t<=1+o&&e>=-o&&e<=1+o&&(i.push(Math.max(0,Math.min(1,t))),s.push(Math.max(0,Math.min(1,e)))))}if(!(Math.abs(Fc(h,c,a,n))>o*p)){for(const s of[e.a,e.b]){const e=Gc(s,t,o);null!=e&&i.push(e)}for(const i of[t.a,t.b]){const t=Gc(i,e,o);null!=t&&s.push(t)}}}function Uc(t){let e=t+1|0;return e^=e<<13,e^=e>>>17,e^=e<<5,e>>>0}function qc(t,e){return t.minY-e.minY||t.index-e.index}function Kc(t){return t.subtreeMaxY=Math.max(t.item.maxY,t.left?.subtreeMaxY??-1/0,t.right?.subtreeMaxY??-1/0),t}function Vc(t){const e=t.right;return t.right=e.left,e.left=Kc(t),Kc(e)}function Jc(t){const e=t.left;return t.left=e.right,e.right=Kc(t),Kc(e)}function Yc(t,e){return t?(qc(e,t.item)<0?(t.left=Yc(t.left,e),t.left.priority<t.priority&&(t=Jc(t))):(t.right=Yc(t.right,e),t.right.priority<t.priority&&(t=Vc(t))),Kc(t)):{item:e,priority:Uc(e.index),subtreeMaxY:e.maxY,left:null,right:null}}function Zc(t,e){if(!t)return null;const i=qc(e,t.item);if(i<0)t.left=Zc(t.left,e);else if(i>0)t.right=Zc(t.right,e);else{if(!t.left)return t.right;if(!t.right)return t.left;t.left.priority<t.right.priority?(t=Jc(t)).right=Zc(t.right,e):(t=Vc(t)).left=Zc(t.left,e)}return Kc(t)}function Xc(t,e,i,s){!t||t.subtreeMaxY<e||(null!=t.left?.subtreeMaxY&&t.left.subtreeMaxY>=e&&Xc(t.left,e,i,s),t.item.minY<=i&&t.item.maxY>=e&&s.push(t.item),t.item.minY<=i&&Xc(t.right,e,i,s))}function Qc(t,e=.001){const i=Number.isFinite(e)&&e>0?e:Lc,s=t.filter(t=>Rc(t.a)&&Rc(t.b)&&"string"==typeof t.key&&t.key.length>0&&Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])>i),o=s.map(()=>[0,1]);!function(t,e,i){const s=t.map((t,e)=>({index:e,minX:Math.min(t.a[0],t.b[0])-i,maxX:Math.max(t.a[0],t.b[0])+i,minY:Math.min(t.a[1],t.b[1])-i,maxY:Math.max(t.a[1],t.b[1])+i})),o=[...s].sort((t,e)=>t.minX-e.minX||t.minY-e.minY||t.index-e.index),a=[...s].sort((t,e)=>t.maxX-e.maxX||t.index-e.index),n=new Set;let r=null,l=0;for(const s of o){for(;l<a.length&&a[l].maxX<s.minX;){const t=a[l++];n.delete(t.index)&&(r=Zc(r,t))}const o=[];Xc(r,s.minY,s.maxY,o),o.sort((t,e)=>t.index-e.index);for(const a of o)jc(t[a.index],t[s.index],e[a.index],e[s.index],i);n.add(s.index),r=Yc(r,s)}}(s,o,i);const a=new Map;for(let t=0;t<s.length;t++){const e=s[t],n=Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1]),r=Hc(o[t],i/Math.max(n,1));for(let t=0;t+1<r.length;t++){const s=Nc(Wc(e,r[t]),i),o=Nc(Wc(e,r[t+1]),i);if(Math.hypot(o[0]-s[0],o[1]-s[1])<=i)continue;const n=Ec(s,i),l=Ec(o,i),h=Ac(n,l),c=a.get(h);c?c.sourceKeys.add(e.key):a.set(h,{a:n.localeCompare(l)<=0?s:o,b:n.localeCompare(l)<=0?o:s,sourceKeys:new Set([e.key])})}}return[...a.entries()].map(([t,e])=>({key:t,a:e.a,b:e.b,sourceKeys:[...e.sourceKeys].sort((t,e)=>t.localeCompare(e))})).sort((t,e)=>t.key.localeCompare(e.key))}function td(t,e=.001){const i=Number.isFinite(e)&&e>0?e:Lc,s=Qc(t,i),o=new Map,a=new Map,n=new Map(s.map(t=>[t.key,t]));for(const t of s){const e=Ec(t.a,i),s=Ec(t.b,i);o.set(e,t.a),o.set(s,t.b),a.has(e)||a.set(e,new Set),a.has(s)||a.set(s,new Set),a.get(e).add(s),a.get(s).add(e)}const r=new Map;for(const[t,e]of a){const i=o.get(t);r.set(t,[...e].sort((t,e)=>{const s=o.get(t),a=o.get(e);return Math.atan2(s[1]-i[1],s[0]-i[0])-Math.atan2(a[1]-i[1],a[0]-i[0])||t.localeCompare(e)}))}const l=new Set,h=new Map,c=(t,e)=>`${t}>${e}`;for(const t of s){const e=[Ec(t.a,i),Ec(t.b,i)];for(const[t,a]of[e,[e[1],e[0]]]){if(l.has(c(t,a)))continue;const e=[],d=[];let p=t,u=a,_=!1;for(let i=0;i<=2*s.length+2;i++){const i=c(p,u);if(l.has(i)){_=p===t&&u===a;break}l.add(i),e.push(p),d.push(Ac(p,u));const s=r.get(u)||[],o=s.indexOf(p);if(o<0||!s.length)break;if(p=u,u=s[(o-1+s.length)%s.length],p===t&&u===a){_=!0;break}}if(!_||new Set(e).size<3||new Set(e).size!==e.length)continue;const m=e.map(t=>o.get(t)),g=zc(m);if(!(g>i*i))continue;const f=Oc(Bc(e,o,i)),b=new Set;for(const t of d)for(const e of n.get(t)?.sourceKeys||[])b.add(e);const v={ring:m,key:f,area:g,atomKeys:[...d],sourceKeys:[...b].sort((t,e)=>t.localeCompare(e))};h.has(f)||h.set(f,v)}}return{atoms:s,faces:[...h.values()].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key))}}function ed(t,e,i=.001){if(!Rc(e))return null;const s=t.faces.filter(t=>{if(t.ring.some((s,o)=>function(t,e,i,s){const o=i[0]-e[0],a=i[1]-e[1],n=o*o+a*a;if(!(n>0))return Math.hypot(t[0]-e[0],t[1]-e[1])<=s;const r=((t[0]-e[0])*o+(t[1]-e[1])*a)/n;return!(r<0||r>1)&&Math.hypot(e[0]+o*r-t[0],e[1]+a*r-t[1])<=s}(e,s,t.ring[(o+1)%t.ring.length],i)))return!1;let s=!1;for(let i=0,o=t.ring.length-1;i<t.ring.length;o=i++){const a=t.ring[i],n=t.ring[o];a[1]>e[1]!=n[1]>e[1]&&e[0]<(n[0]-a[0])*(e[1]-a[1])/(n[1]-a[1])+a[0]&&(s=!s)}return s});return[...s].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key))[0]||null}function id(t,e,i){const s=i[0]-e[0],o=i[1]-e[1],a=s*s+o*o,n=a>0?Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*o)/a)):0;return Math.hypot(e[0]+s*n-t[0],e[1]+o*n-t[1])}function sd(t,e,i=.5){let s=Math.abs(t-e)%180;return s>90&&(s=180-s),s<=i}function od(t,e,i,s){const o=t.filter(t=>"outer"===t.kind&&!t.open&&t.cm>0).map(t=>({interval:t,reusePartitionId:e.find(e=>function(t,e,i){return!(Math.abs(t.cm-e.cm)>1e-6)&&(sd(180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI,180*Math.atan2(e.b[1]-e.a[1],e.b[0]-e.a[0])/Math.PI,.001)&&id(e.a,t.a,t.b)<=i&&id(e.b,t.a,t.b)<=i)}(e,t,s))?.id||null})),a=new Map;for(const e of i){if("partition"===e.host?.kind)continue;const i=t.map(t=>{const i=180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI;return{interval:t,distance:sd(e.angle,i)?id([e.x,e.y],t.a,t.b):1/0}}).filter(t=>t.distance<=s).sort((t,e)=>t.distance-e.distance||t.interval.key.localeCompare(e.interval.key)),o=i[0]?.interval;"outer"===o?.kind&&!o.open&&o.cm>0&&a.set(e.id,o.key)}return{materialize:o,openingIntervals:a,removeOpeningIds:[...a.keys()].sort((t,e)=>t.localeCompare(e))}}function ad(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],o=i*i+s*s;return o>0?Math.max(0,Math.min(1,((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/o)):0}const nd=t=>!t.key.startsWith("static:room|");function rd(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],o=i*i+s*s;if(!(o>0))return null;const a=((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/o,n=[e.a[0]+i*a,e.a[1]+s*a];return{point:n,t:a,distance:Math.hypot(n[0]-t[0],n[1]-t[1])}}function ld(t,e){return e>0?Math.hypot(t[0]-Math.round(t[0]/e)*e,t[1]-Math.round(t[1]/e)*e):0}function hd(t,e,i){if(nd(t.source)!==nd(e.source))return nd(t.source)?t:e;const s=ld(t.point,i),o=ld(e.point,i);return Math.abs(s-o)>1e-9?s>o?t:e:function(t,e){return t[0]-e[0]||t[1]-e[1]}(t.point,e.point)>0?t:e}function cd(t){return[t.from[0],t.from[1],t.to[0],t.to[1],t.targetKind].map(t=>"number"==typeof t?t.toFixed(6):t).join("|")}function dd(t,e){return t.map(t=>t.key!==e.sourceKey?t:{...t,[e.endpoint]:[...e.to]})}function pd(t,e){const i=e.epsilon??.001;if(!(e.maxDistance>=0)||!e.point&&!e.requiredSourceKey)return{kind:"none"};const s=new Map,o=t.flatMap(t=>[{source:t,endpoint:"a",point:t.a},{source:t,endpoint:"b",point:t.b}]);for(let t=0;t<o.length;t++)for(let a=t+1;a<o.length;a++){const n=o[t],r=o[a];if(n.source===r.source)continue;const l=Math.hypot(n.point[0]-r.point[0],n.point[1]-r.point[1]);if(!(l>i)||l>e.maxDistance)continue;const h=hd(n,r,e.gridStep||0),c=h===n?r:n;if(!nd(h.source))continue;const d={sourceKey:h.source.key,endpoint:h.endpoint,from:[h.point[0],h.point[1]],to:[c.point[0],c.point[1]],targetSourceKey:c.source.key,targetKind:"endpoint",distance:l};s.set(cd(d),d)}for(const a of o)if(nd(a.source))for(const o of t){if(o===a.source)continue;const t=rd(a.point,o);if(!t||t.t<=i||t.t>=1-i||!(t.distance>i)||t.distance>e.maxDistance)continue;const n={sourceKey:a.source.key,endpoint:a.endpoint,from:[a.point[0],a.point[1]],to:t.point,targetSourceKey:o.key,targetKind:"line",distance:t.distance};s.set(cd(n),n)}const a=[];for(const o of s.values()){const s=td(dd(t,o),i),n=e.point?ed(s,e.point,i):s.faces.find(t=>!e.requiredSourceKey||t.sourceKeys.includes(e.requiredSourceKey))||null;n&&a.push({proposal:o,face:n})}if(a.sort((t,e)=>t.proposal.distance-e.proposal.distance||cd(t.proposal).localeCompare(cd(e.proposal))),!a.length)return{kind:"none"};return new Set(a.map(t=>`${cd(t.proposal)}|${t.face.key}`)).size>1?{kind:"ambiguous",proposals:a.map(t=>t.proposal)}:{kind:"repair",...a[0]}}const ud=(t,e)=>(t.composedPath?.()||[t.target]).some(t=>(t=>!!t&&"function"==typeof t.matches)(t)&&e(t));class _d{constructor(t){this.host=t,this._openGroupId=null,this._groupGeneration=0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,this._globalDismissListening=!1,this._globalDismissGuard=t=>{this.handleOutsideDismiss(t)}}get hasOpenGroup(){return null!==this._openGroupId}get groupGeneration(){return this._groupGeneration}activeGroup(t){return this._openGroupId&&t.find(t=>t.id===this._openGroupId)||null}reset(){this._openGroupId=null,this._contentAnimation?.cancel(),this._contentAnimation=void 0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}closeForNavigation(){const t="palette"===this._currentModel?.kind?this._currentModel.dismiss:void 0,e=!!this._openGroupId||!!t;this._openGroupId=null,t?.(),t&&(this._currentModel=null),this._clearDismissClick(),e&&this.host.requestUpdate(),this._syncGlobalDismissListener()}openPalette(){this._openGroupId&&this.closeGroup(!1)}toggleGroup(t,e){this._openGroupId!==e?t.some(t=>t.id===e)&&("palette"===this._currentModel?.kind&&this._currentModel.dismiss?.(),this._groupGeneration+=1,this._openGroupId=e,this.host.clearTip(),this.host.requestUpdate(),this._syncGlobalDismissListener()):this.closeGroup(!1)}closeGroup(t){const e=this._openGroupId;this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener(),t&&e&&this.host.updateComplete().then(()=>{const t=this.host.root(),i=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===e&&null!==t.offsetParent);(i||t.querySelector(".editbar-tools"))?.focus?.()})}renderGroupLauncher(t,e,i){const s=this._openGroupId===t.id,o=t.items.find(e=>e.id===t.activeItemId&&!e.disabled);return p`<button class="btn editor-group-launcher ${s||o?"on":""}"
|
||
========
|
||
</div>`}}const cc=.001;function dc(t){return!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1])}function pc(t){return`${t[0].toFixed(6)},${t[1].toFixed(6)}`}function uc(t,e,s){return Math.abs(t[0]-e[0])<s&&Math.abs(t[1]-e[1])<s}function _c(t,e){const s=function(t,e){return t[0]-e[0]||t[1]-e[1]}(t,e)<=0?t:e,i=s===t?e:t;return[[s[0],s[1]],[i[0],i[1]]]}function mc(t){const[e,s]=_c(t.a,t.b);return`${t.kind}|${t.id}|${pc(e)}|${pc(s)}`}function gc(t,e,s){const[i,o]=_c(e,s);return`${mc(t)}|${pc(i)}|${pc(o)}`}function fc(t){return"room"===t?0:1}function bc(t,e,s){return uc(t,[e[0],e[1]],s)||uc(t,[e[2],e[3]],s)}function vc(t){const e=t.epsilon??cc,s=[];for(const[e,i]of ue(t.space.rooms).entries())i.length<4||s.push({a:[i[0],i[1]],b:[i[2],i[3]],kind:"room",id:`room-edge-${e}`,cuts:[]});for(const i of t.space.partitions||[])dc(i.a)&&dc(i.b)&&!uc(i.a,i.b,e)&&s.push({a:[i.a[0],i.a[1]],b:[i.b[0],i.b[1]],kind:"partition",id:i.id,cuts:[]});const i=s.filter(t=>"room"!==t.kind&&s.some(s=>s!==t&&function(t,e,s){const i=t.b[0]-t.a[0],o=t.b[1]-t.a[1],a=Math.hypot(i,o);if(!(a>s))return!1;const n=i/a,r=o/a,l=e=>Math.abs((e[0]-t.a[0])*r-(e[1]-t.a[1])*n);if(l(e.a)>s||l(e.b)>s)return!1;const h=(e.a[0]-t.a[0])*n+(e.a[1]-t.a[1])*r,c=(e.b[0]-t.a[0])*n+(e.b[1]-t.a[1])*r;return Math.min(a,Math.max(h,c))-Math.max(0,Math.min(h,c))>s}(t,s,e))),o=i.map(t=>{const[e,s]=_c(t.a,t.b);return{a:e,b:s,key:`hidden|${gc(t,e,s)}`,sourceKind:t.kind,sourceId:t.id}}).sort((t,e)=>t.key.localeCompare(e.key)),a=i.flatMap(t=>[t.a,t.b].map((e,s)=>({point:[e[0],e[1]],key:`hidden|${mc(t)}|endpoint-${s}`,sourceKind:"partition",sourceId:t.id}))).sort((t,e)=>t.key.localeCompare(e.key));return{segments:o,endpoints:a}}function yc(t){const e=t.epsilon??cc,s=t.roomCuts||[],i=new Map;for(const e of t.partitionCuts||[]){if("string"!=typeof e.hostId||!e.hostId||!dc(e.a)||!dc(e.b))continue;const t=i.get(e.hostId)||[];t.push([e.a[0],e.a[1],e.b[0],e.b[1]]),i.set(e.hostId,t)}const o=[];for(const[e,i]of ue(t.space.rooms).entries())i.length<4||o.push({a:[i[0],i[1]],b:[i[2],i[3]],kind:"room",id:`room-edge-${e}`,cuts:s});for(const e of t.space.partitions||[])dc(e.a)&&dc(e.b)&&o.push({a:[e.a[0],e.a[1]],b:[e.b[0],e.b[1]],kind:"partition",id:e.id,cuts:i.get(e.id)||[]});const a=new Map,n=new Map;for(const t of o){const s=[t.a[0],t.a[1],t.b[0],t.b[1]],i=_e([s],t.cuts,e);if(i.length){for(const s of i){if(s.length<4)continue;const[i,o]=_c([s[0],s[1]],[s[2],s[3]]);if(uc(i,o,e))continue;const n=`${pc(i)}|${pc(o)}`,r={a:i,b:o,key:gc(t,i,o),sourceKind:t.kind,sourceId:t.id},l=a.get(n);(!l||fc(r.sourceKind)<fc(l.sourceKind)||fc(r.sourceKind)===fc(l.sourceKind)&&r.key.localeCompare(l.key)<0)&&a.set(n,r)}for(const s of[t.a,t.b]){if(!i.some(t=>bc(s,t,e)))continue;const t=pc(s);n.has(t)||n.set(t,{point:[s[0],s[1]],key:t})}}}return{segments:[...a.values()].sort((t,e)=>t.key.localeCompare(e.key)),endpoints:[...n.values()].sort((t,e)=>t.key.localeCompare(e.key))}}function wc(t,e,s){return e.some(e=>dc(e)&&uc(t,e,s))}function $c(t,e,s){if(!s)return!0;const i=t-s.distance;return i<-1e-9||Math.abs(i)<=1e-9&&e.localeCompare(s.key)<0}function kc(t,e,s){const i=s.epsilon??cc,o=s.excludePoints||[],a=[...t.endpoints,...(s.extraEndpoints||[]).filter(t=>dc(t.point)).map(t=>({point:[t.point[0],t.point[1]],key:t.key}))],n=new Map;for(const t of a){if(wc(t.point,o,i))continue;const e=pc(t.point),s=n.get(e);(!s||t.key.localeCompare(s.key)<0)&&n.set(e,t)}return[...n.values()].map(t=>({kind:"endpoint",point:[...t.point],key:t.key,distance:Math.hypot(e[0]-t.point[0],e[1]-t.point[1])})).filter(t=>t.distance<=s.tolerance).sort((t,e)=>t.distance-e.distance||t.key.localeCompare(e.key))}function xc(t,e){if(!t.length)return null;if(e>0){const s=new Set;for(let i=0;i<t.length;i++)for(let o=i+1;o<t.length;o++)Math.hypot(t[i].point[0]-t[o].point[0],t[i].point[1]-t[o].point[1])<e&&(s.add(t[i].key),s.add(t[o].key));if(s.size>1)return{kind:"ambiguous",candidate:null,conflicts:t.filter(t=>s.has(t.key)).map(t=>({point:[...t.point],key:t.key}))}}return{kind:"resolved",candidate:t[0],conflicts:[]}}function Mc(t,e,s){const i=t.b[0]-t.a[0],o=t.b[1]-t.a[1],a=Math.hypot(i,o);if(!(a>0))return[...t.a];const n=i/a,r=o/a,l=Math.max(0,Math.min(a,(e[0]-t.a[0])*n+(e[1]-t.a[1])*r)),h=s>0?Math.max(0,Math.min(a,Math.round(l/s)*s)):l;return[t.a[0]+n*h,t.a[1]+r*h]}function Cc(t,e,s){if(!(dc(e)&&dc(s.anchor)&&s.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const i=s.epsilon??cc,o=function(t,e){const s=e[0]-t[0],i=e[1]-t[1];if(!(Math.hypot(s,i)>Number.EPSILON))return null;const o=Math.round(Math.atan2(i,s)/(Math.PI/4))*(Math.PI/4);return[Math.cos(o),Math.sin(o)]}(s.anchor,e);if(!o)return{kind:"none",candidate:null,conflicts:[]};const a=kc(t,e,s).filter(t=>function(t,e,s,i){const o=t[0]-e[0],a=t[1]-e[1];return o*s[0]+a*s[1]>i&&Math.abs(o*s[1]-a*s[0])<=i*Math.max(Math.hypot(o,a),1)}(t.point,s.anchor,o,i)),n=xc(a,s.distinguishTolerance||0);if(n)return n;let r=null;for(const a of t.segments){const t=a.b[0]-a.a[0],n=a.b[1]-a.a[1],l=a.a[0]-s.anchor[0],h=a.a[1]-s.anchor[1],c=o[0]*n-o[1]*t;let d=null;if(Math.abs(c)<=i*Math.max(Math.hypot(t,n),1)){if(Math.abs(l*o[1]-h*o[0])>i*Math.max(Math.hypot(l,h),1))continue;const t=[a.a,a.b].map(t=>({point:t,along:(t[0]-s.anchor[0])*o[0]+(t[1]-s.anchor[1])*o[1]})).filter(t=>t.along>i).sort((t,e)=>t.along-e.along);t.length&&(d=[...t[0].point])}else{const e=(l*n-h*t)/c,a=(l*o[1]-h*o[0])/c;e>i&&a>=-i&&a<=1+i&&(d=[s.anchor[0]+o[0]*e,s.anchor[1]+o[1]*e])}if(!d)continue;const p=Math.hypot(e[0]-d[0],e[1]-d[1]);p>s.tolerance||wc(d,s.excludePoints||[],i)||!$c(p,a.key,r)||(r={kind:"line",point:d,key:a.key,distance:p,segment:a})}return r?{kind:"resolved",candidate:r,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}const Sc=.001;function Pc(t,e,s,i){const o=Number.isFinite(t)&&t>0?Math.floor(t):0,a=t=>"number"==typeof t&&Number.isFinite(t)&&t>=0?t:null,n=a(s),r=a(i)??0,l=[];let h=null;for(let t=0;t<o;t++){const s=a(e?.[t])??(t===o-1?n??h??r:h??n??r);l.push(s),h=s}return l}function Ic(t){return!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1])}function Dc(t,e,s,i){return t*i-e*s}function Lc(t){let e=0;for(let s=0;s<t.length;s++){const i=t[s],o=t[(s+1)%t.length];e+=i[0]*o[1]-o[0]*i[1]}return e/2}function Tc(t,e){const s=Math.max(e,Number.EPSILON),i=Math.round(t[0]/s)*s,o=Math.round(t[1]/s)*s;return[Object.is(i,-0)?0:i,Object.is(o,-0)?0:o]}function Rc(t,e){const s=Tc(t,e);return`${Math.round(s[0]/e)},${Math.round(s[1]/e)}`}function zc(t,e){return t.localeCompare(e)<=0?`${t}|${e}`:`${e}|${t}`}function Fc(t){if(!t.length)return"";const e=[];for(const s of[t,[...t].reverse()])for(let t=0;t<s.length;t++)e.push([...s.slice(t),...s.slice(0,t)].join(";"));return e.sort((t,e)=>t.localeCompare(e)),e[0]}function Nc(t,e,s){const i=[...t];for(let t=!0;t&&i.length>=3;){t=!1;for(let o=0;o<i.length;o++){const a=e.get(i[(o-1+i.length)%i.length]),n=e.get(i[o]),r=e.get(i[(o+1)%i.length]),l=n[0]-a[0],h=n[1]-a[1],c=r[0]-n[0],d=r[1]-n[1];if(Math.abs(Dc(l,h,c,d))<=s*Math.max(Math.hypot(l,h),Math.hypot(c,d),1)&&l*c+h*d>=0){i.splice(o,1),t=!0;break}}}return i}function Ac(t,e){const s=t.map(t=>Math.max(0,Math.min(1,t))).sort((t,e)=>t-e),i=[];for(const t of s)(!i.length||Math.abs(t-i[i.length-1])>e)&&i.push(t);return i}function Ec(t,e){return[t.a[0]+(t.b[0]-t.a[0])*e,t.a[1]+(t.b[1]-t.a[1])*e]}function Oc(t,e,s){const i=function(t,e){const s=e.b[0]-e.a[0],i=e.b[1]-e.a[1],o=s*s+i*i;return o>0?((t[0]-e.a[0])*s+(t[1]-e.a[1])*i)/o:0}(t,e);if(i<-s||i>1+s)return null;const o=Ec(e,i);return Math.hypot(o[0]-t[0],o[1]-t[1])<=s?Math.max(0,Math.min(1,i)):null}function Bc(t,e,s,i,o){const a=t.b[0]-t.a[0],n=t.b[1]-t.a[1],r=e.b[0]-e.a[0],l=e.b[1]-e.a[1],h=e.a[0]-t.a[0],c=e.a[1]-t.a[1],d=Dc(a,n,r,l),p=Math.max(Math.hypot(a,n),Math.hypot(r,l),1);if(Math.abs(d)>o*p){const t=Dc(h,c,r,l)/d,e=Dc(h,c,a,n)/d;return void(t>=-o&&t<=1+o&&e>=-o&&e<=1+o&&(s.push(Math.max(0,Math.min(1,t))),i.push(Math.max(0,Math.min(1,e)))))}if(!(Math.abs(Dc(h,c,a,n))>o*p)){for(const i of[e.a,e.b]){const e=Oc(i,t,o);null!=e&&s.push(e)}for(const s of[t.a,t.b]){const t=Oc(s,e,o);null!=t&&i.push(t)}}}function Hc(t){let e=t+1|0;return e^=e<<13,e^=e>>>17,e^=e<<5,e>>>0}function Wc(t,e){return t.minY-e.minY||t.index-e.index}function jc(t){return t.subtreeMaxY=Math.max(t.item.maxY,t.left?.subtreeMaxY??-1/0,t.right?.subtreeMaxY??-1/0),t}function Gc(t){const e=t.right;return t.right=e.left,e.left=jc(t),jc(e)}function qc(t){const e=t.left;return t.left=e.right,e.right=jc(t),jc(e)}function Uc(t,e){return t?(Wc(e,t.item)<0?(t.left=Uc(t.left,e),t.left.priority<t.priority&&(t=qc(t))):(t.right=Uc(t.right,e),t.right.priority<t.priority&&(t=Gc(t))),jc(t)):{item:e,priority:Hc(e.index),subtreeMaxY:e.maxY,left:null,right:null}}function Kc(t,e){if(!t)return null;const s=Wc(e,t.item);if(s<0)t.left=Kc(t.left,e);else if(s>0)t.right=Kc(t.right,e);else{if(!t.left)return t.right;if(!t.right)return t.left;t.left.priority<t.right.priority?(t=qc(t)).right=Kc(t.right,e):(t=Gc(t)).left=Kc(t.left,e)}return jc(t)}function Vc(t,e,s,i){!t||t.subtreeMaxY<e||(null!=t.left?.subtreeMaxY&&t.left.subtreeMaxY>=e&&Vc(t.left,e,s,i),t.item.minY<=s&&t.item.maxY>=e&&i.push(t.item),t.item.minY<=s&&Vc(t.right,e,s,i))}function Jc(t,e=.001){const s=Number.isFinite(e)&&e>0?e:Sc,i=t.filter(t=>Ic(t.a)&&Ic(t.b)&&"string"==typeof t.key&&t.key.length>0&&Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])>s),o=i.map(()=>[0,1]);!function(t,e,s){const i=t.map((t,e)=>({index:e,minX:Math.min(t.a[0],t.b[0])-s,maxX:Math.max(t.a[0],t.b[0])+s,minY:Math.min(t.a[1],t.b[1])-s,maxY:Math.max(t.a[1],t.b[1])+s})),o=[...i].sort((t,e)=>t.minX-e.minX||t.minY-e.minY||t.index-e.index),a=[...i].sort((t,e)=>t.maxX-e.maxX||t.index-e.index),n=new Set;let r=null,l=0;for(const i of o){for(;l<a.length&&a[l].maxX<i.minX;){const t=a[l++];n.delete(t.index)&&(r=Kc(r,t))}const o=[];Vc(r,i.minY,i.maxY,o),o.sort((t,e)=>t.index-e.index);for(const a of o)Bc(t[a.index],t[i.index],e[a.index],e[i.index],s);n.add(i.index),r=Uc(r,i)}}(i,o,s);const a=new Map;for(let t=0;t<i.length;t++){const e=i[t],n=Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1]),r=Ac(o[t],s/Math.max(n,1));for(let t=0;t+1<r.length;t++){const i=Tc(Ec(e,r[t]),s),o=Tc(Ec(e,r[t+1]),s);if(Math.hypot(o[0]-i[0],o[1]-i[1])<=s)continue;const n=Rc(i,s),l=Rc(o,s),h=zc(n,l),c=a.get(h);c?c.sourceKeys.add(e.key):a.set(h,{a:n.localeCompare(l)<=0?i:o,b:n.localeCompare(l)<=0?o:i,sourceKeys:new Set([e.key])})}}return[...a.entries()].map(([t,e])=>({key:t,a:e.a,b:e.b,sourceKeys:[...e.sourceKeys].sort((t,e)=>t.localeCompare(e))})).sort((t,e)=>t.key.localeCompare(e.key))}function Zc(t,e=.001){const s=Number.isFinite(e)&&e>0?e:Sc,i=Jc(t,s),o=new Map,a=new Map,n=new Map(i.map(t=>[t.key,t]));for(const t of i){const e=Rc(t.a,s),i=Rc(t.b,s);o.set(e,t.a),o.set(i,t.b),a.has(e)||a.set(e,new Set),a.has(i)||a.set(i,new Set),a.get(e).add(i),a.get(i).add(e)}const r=new Map;for(const[t,e]of a){const s=o.get(t);r.set(t,[...e].sort((t,e)=>{const i=o.get(t),a=o.get(e);return Math.atan2(i[1]-s[1],i[0]-s[0])-Math.atan2(a[1]-s[1],a[0]-s[0])||t.localeCompare(e)}))}const l=new Set,h=new Map,c=(t,e)=>`${t}>${e}`;for(const t of i){const e=[Rc(t.a,s),Rc(t.b,s)];for(const[t,a]of[e,[e[1],e[0]]]){if(l.has(c(t,a)))continue;const e=[],d=[];let p=t,u=a,_=!1;for(let s=0;s<=2*i.length+2;s++){const s=c(p,u);if(l.has(s)){_=p===t&&u===a;break}l.add(s),e.push(p),d.push(zc(p,u));const i=r.get(u)||[],o=i.indexOf(p);if(o<0||!i.length)break;if(p=u,u=i[(o-1+i.length)%i.length],p===t&&u===a){_=!0;break}}if(!_||new Set(e).size<3||new Set(e).size!==e.length)continue;const m=e.map(t=>o.get(t)),g=Lc(m);if(!(g>s*s))continue;const f=Fc(Nc(e,o,s)),b=new Set;for(const t of d)for(const e of n.get(t)?.sourceKeys||[])b.add(e);const v={ring:m,key:f,area:g,atomKeys:[...d],sourceKeys:[...b].sort((t,e)=>t.localeCompare(e))};h.has(f)||h.set(f,v)}}return{atoms:i,faces:[...h.values()].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key))}}function Yc(t,e,s=.001){if(!Ic(e))return null;const i=t.faces.filter(t=>{if(t.ring.some((i,o)=>function(t,e,s,i){const o=s[0]-e[0],a=s[1]-e[1],n=o*o+a*a;if(!(n>0))return Math.hypot(t[0]-e[0],t[1]-e[1])<=i;const r=((t[0]-e[0])*o+(t[1]-e[1])*a)/n;return!(r<0||r>1)&&Math.hypot(e[0]+o*r-t[0],e[1]+a*r-t[1])<=i}(e,i,t.ring[(o+1)%t.ring.length],s)))return!1;let i=!1;for(let s=0,o=t.ring.length-1;s<t.ring.length;o=s++){const a=t.ring[s],n=t.ring[o];a[1]>e[1]!=n[1]>e[1]&&e[0]<(n[0]-a[0])*(e[1]-a[1])/(n[1]-a[1])+a[0]&&(i=!i)}return i});return[...i].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key))[0]||null}function Xc(t,e,s){const i=s[0]-e[0],o=s[1]-e[1],a=i*i+o*o,n=a>0?Math.max(0,Math.min(1,((t[0]-e[0])*i+(t[1]-e[1])*o)/a)):0;return Math.hypot(e[0]+i*n-t[0],e[1]+o*n-t[1])}function Qc(t,e,s=.5){let i=Math.abs(t-e)%180;return i>90&&(i=180-i),i<=s}function td(t,e,s,i){const o=t.filter(t=>"outer"===t.kind&&!t.open&&t.cm>0).map(t=>({interval:t,reusePartitionId:e.find(e=>function(t,e,s){return!(Math.abs(t.cm-e.cm)>1e-6)&&(Qc(180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI,180*Math.atan2(e.b[1]-e.a[1],e.b[0]-e.a[0])/Math.PI,.001)&&Xc(e.a,t.a,t.b)<=s&&Xc(e.b,t.a,t.b)<=s)}(e,t,i))?.id||null})),a=new Map;for(const e of s){if("partition"===e.host?.kind)continue;const s=t.map(t=>{const s=180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI;return{interval:t,distance:Qc(e.angle,s)?Xc([e.x,e.y],t.a,t.b):1/0}}).filter(t=>t.distance<=i).sort((t,e)=>t.distance-e.distance||t.interval.key.localeCompare(e.interval.key)),o=s[0]?.interval;"outer"===o?.kind&&!o.open&&o.cm>0&&a.set(e.id,o.key)}return{materialize:o,openingIntervals:a,removeOpeningIds:[...a.keys()].sort((t,e)=>t.localeCompare(e))}}function ed(t,e){const s=e.b[0]-e.a[0],i=e.b[1]-e.a[1],o=s*s+i*i;return o>0?Math.max(0,Math.min(1,((t[0]-e.a[0])*s+(t[1]-e.a[1])*i)/o)):0}const sd=t=>!t.key.startsWith("static:room|");function id(t,e){const s=e.b[0]-e.a[0],i=e.b[1]-e.a[1],o=s*s+i*i;if(!(o>0))return null;const a=((t[0]-e.a[0])*s+(t[1]-e.a[1])*i)/o,n=[e.a[0]+s*a,e.a[1]+i*a];return{point:n,t:a,distance:Math.hypot(n[0]-t[0],n[1]-t[1])}}function od(t,e){return e>0?Math.hypot(t[0]-Math.round(t[0]/e)*e,t[1]-Math.round(t[1]/e)*e):0}function ad(t,e,s){if(sd(t.source)!==sd(e.source))return sd(t.source)?t:e;const i=od(t.point,s),o=od(e.point,s);return Math.abs(i-o)>1e-9?i>o?t:e:function(t,e){return t[0]-e[0]||t[1]-e[1]}(t.point,e.point)>0?t:e}function nd(t){return[t.from[0],t.from[1],t.to[0],t.to[1],t.targetKind].map(t=>"number"==typeof t?t.toFixed(6):t).join("|")}function rd(t,e){return t.map(t=>t.key!==e.sourceKey?t:{...t,[e.endpoint]:[...e.to]})}function ld(t,e){const s=e.epsilon??.001;if(!(e.maxDistance>=0)||!e.point&&!e.requiredSourceKey)return{kind:"none"};const i=new Map,o=t.flatMap(t=>[{source:t,endpoint:"a",point:t.a},{source:t,endpoint:"b",point:t.b}]);for(let t=0;t<o.length;t++)for(let a=t+1;a<o.length;a++){const n=o[t],r=o[a];if(n.source===r.source)continue;const l=Math.hypot(n.point[0]-r.point[0],n.point[1]-r.point[1]);if(!(l>s)||l>e.maxDistance)continue;const h=ad(n,r,e.gridStep||0),c=h===n?r:n;if(!sd(h.source))continue;const d={sourceKey:h.source.key,endpoint:h.endpoint,from:[h.point[0],h.point[1]],to:[c.point[0],c.point[1]],targetSourceKey:c.source.key,targetKind:"endpoint",distance:l};i.set(nd(d),d)}for(const a of o)if(sd(a.source))for(const o of t){if(o===a.source)continue;const t=id(a.point,o);if(!t||t.t<=s||t.t>=1-s||!(t.distance>s)||t.distance>e.maxDistance)continue;const n={sourceKey:a.source.key,endpoint:a.endpoint,from:[a.point[0],a.point[1]],to:t.point,targetSourceKey:o.key,targetKind:"line",distance:t.distance};i.set(nd(n),n)}const a=[];for(const o of i.values()){const i=Zc(rd(t,o),s),n=e.point?Yc(i,e.point,s):i.faces.find(t=>!e.requiredSourceKey||t.sourceKeys.includes(e.requiredSourceKey))||null;n&&a.push({proposal:o,face:n})}if(a.sort((t,e)=>t.proposal.distance-e.proposal.distance||nd(t.proposal).localeCompare(nd(e.proposal))),!a.length)return{kind:"none"};return new Set(a.map(t=>`${nd(t.proposal)}|${t.face.key}`)).size>1?{kind:"ambiguous",proposals:a.map(t=>t.proposal)}:{kind:"repair",...a[0]}}const hd=(t,e)=>(t.composedPath?.()||[t.target]).some(t=>(t=>!!t&&"function"==typeof t.matches)(t)&&e(t));class cd{constructor(t){this.host=t,this._openGroupId=null,this._groupGeneration=0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,this._globalDismissListening=!1,this._globalDismissGuard=t=>{this.handleOutsideDismiss(t)}}get hasOpenGroup(){return null!==this._openGroupId}get groupGeneration(){return this._groupGeneration}activeGroup(t){return this._openGroupId&&t.find(t=>t.id===this._openGroupId)||null}reset(){this._openGroupId=null,this._contentAnimation?.cancel(),this._contentAnimation=void 0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}closeForNavigation(){const t="palette"===this._currentModel?.kind?this._currentModel.dismiss:void 0,e=!!this._openGroupId||!!t;this._openGroupId=null,t?.(),t&&(this._currentModel=null),this._clearDismissClick(),e&&this.host.requestUpdate(),this._syncGlobalDismissListener()}openPalette(){this._openGroupId&&this.closeGroup(!1)}toggleGroup(t,e){this._openGroupId!==e?t.some(t=>t.id===e)&&("palette"===this._currentModel?.kind&&this._currentModel.dismiss?.(),this._groupGeneration+=1,this._openGroupId=e,this.host.clearTip(),this.host.requestUpdate(),this._syncGlobalDismissListener()):this.closeGroup(!1)}closeGroup(t){const e=this._openGroupId;this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener(),t&&e&&this.host.updateComplete().then(()=>{const t=this.host.root(),s=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===e&&null!==t.offsetParent);(s||t.querySelector(".editbar-tools"))?.focus?.()})}renderGroupLauncher(t,e,s){const i=this._openGroupId===t.id,o=t.items.find(e=>e.id===t.activeItemId&&!e.disabled);return p`<button class="btn editor-group-launcher ${i||o?"on":""}"
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
data-hp="tool" data-tool=${t.id}
|
||
data-editor-group=${t.id} aria-expanded=${s?"true":"false"}
|
||
aria-pressed=${o?"true":"false"}
|
||
aria-controls="hp-editor-secondary" @click=${()=>this.toggleGroup(e,t.id)}
|
||
@keydown=${i=>{"ArrowDown"===i.key&&(i.preventDefault(),s||this.toggleGroup(e,t.id),this.host.updateComplete().then(()=>this.host.root().querySelector(".editor-group-item:not([disabled])")?.focus()))}}
|
||
title=${o?i.groupActive(t.label,o.label):t.label}>
|
||
<ha-icon icon=${t.icon}></ha-icon><span class="ml">${t.label}</span>
|
||
<ha-icon class="group-chevron" icon="mdi:chevron-down"></ha-icon>
|
||
</button>`}renderGroupModel(t,e,i){const s=t.items.find(t=>!t.disabled)?.id,o=t.items.some(e=>e.id===t.activeItemId&&!e.disabled)?t.activeItemId:void 0;return{contextId:e,kind:"group",launcherId:t.id,ariaLabel:i.openGroup(t.label),visibleLabel:t.label,content:p`<div class="editor-group-items"
|
||
@keydown=${t=>this._groupKeydown(t)}>
|
||
${t.items.map(e=>p`<button
|
||
class="btn editor-group-item ${o===e.id?"on":""}"
|
||
data-group-item=${e.id} ?disabled=${!!e.disabled}
|
||
tabindex=${e.id===(o||s)?"0":"-1"}
|
||
aria-label=${e.disabled&&e.disabledReason?i.disabledAction(e.label,e.disabledReason):e.label}
|
||
aria-pressed=${"tool"===e.role||"toggle"===e.role?o===e.id?"true":"false":d}
|
||
title=${e.disabled&&e.disabledReason||e.label}
|
||
@click=${i=>this._activateGroupItem(t,e.id,i)}>
|
||
<ha-icon icon=${e.icon}></ha-icon><span>${e.label}</span>
|
||
</button>`)}
|
||
</div>`}}runContext(t,e,i){if(t===e)return i()}render(t,e){this._currentModel=t,this._blocked=e;const i=t?.kind||"hidden";return p`<div
|
||
class="editor-secondary-host kind-${i} ${t?"open":"closed"} ${e?"blocked":""}"
|
||
aria-hidden=${t?"false":"true"}>
|
||
<div id="hp-editor-secondary" class="editor-secondary kind-${i}"
|
||
data-hp=${t?"tray":d}
|
||
data-kind=${t?.launcherId||("group"===t?.kind?t.contextId:t?.kind)||d}
|
||
data-context-id=${t?.contextId||""} role="toolbar"
|
||
aria-label=${t?.ariaLabel||""} ?inert=${!t||e}
|
||
@focusin=${()=>this._focusOwned=!0}
|
||
@focusout=${t=>{const e=t.relatedTarget;e&&t.currentTarget.contains(e)||(this._focusOwned=!1)}}
|
||
@pointerenter=${()=>this.host.clearTip()}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
@pointerdown=${md}
|
||
@pointerup=${md}
|
||
@pointercancel=${md}
|
||
@click=${md}
|
||
@dblclick=${md}
|
||
@wheel=${md}>
|
||
${t?.visibleLabel?p`<span class="editor-context-label">${t.visibleLabel}</span>`:d}
|
||
<div class="editor-secondary-content">${t?.content||d}</div>
|
||
</div>
|
||
</div>`}afterRender(){const t=this.host.root();this._blocked&&(this._openGroupId?this.closeGroup(!1):"palette"===this._currentModel?.kind&&this._currentModel.dismiss?.()),this._syncGlobalDismissListener();const e=t.querySelector(".editor-secondary"),i=this._renderedContext,s=e?.dataset.contextId||"";if(s&&i&&s!==i&&!window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches&&(this._contentAnimation?.cancel(),this._contentAnimation=e?.querySelector(".editor-secondary-content")?.animate([{opacity:.35,transform:"translateY(-4px)"},{opacity:1,transform:"translateY(0)"}],{duration:100,easing:"ease-out"})),this._renderedContext=s,i&&s!==i&&this._focusOwned){const i=s?e?.querySelector('[tabindex="0"], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled])'):t.querySelector(".editbar-tools");i?.focus?.(),this._focusOwned=!!s}if("palette"===this._currentModel?.kind&&this._currentModel.launcherId){const e=[...t.querySelectorAll("[data-editor-palette]")].find(t=>t.dataset.editorPalette===this._currentModel?.launcherId);e&&null!==e.offsetParent||this._currentModel.dismiss?.()}if(!this._openGroupId)return;const o=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===this._openGroupId);o&&null!==o.offsetParent||this.closeGroup(!0)}handleOutsideDismiss(t){if(ud(t,t=>t.hasAttribute("data-editor-navigation")))return"pointerdown"===t.type?this.closeForNavigation():"click"===t.type&&this._dismissPointerTarget&&this._clearDismissClick(),!1;if("click"===t.type&&this._dismissPointerTarget){return!!(t.composedPath?.()||[t.target]).includes(this._dismissPointerTarget)&&(this._clearDismissClick(),t.preventDefault(),t.stopImmediatePropagation(),!0)}const e=this._openGroupId||this._blocked||"palette"!==this._currentModel?.kind?null:this._currentModel;if("pointerdown"===t.type&&(this._openGroupId||e)){const i=ud(t,t=>t.classList.contains("editor-secondary")),s=ud(t,t=>!!t.dataset.editorGroup),o=ud(t,t=>!!t.dataset.editorPalette),a=ud(t,t=>t.classList.contains("stage"));if(!(i||s||o||"stay-open-on-canvas"===e?.dismissPolicy&&a))return t.preventDefault(),t.stopImmediatePropagation(),this._dismissPointerTarget=t.target,clearTimeout(this._dismissTimer),this._dismissTimer=window.setTimeout(()=>{this._clearDismissClick()},800),this._openGroupId?this.closeGroup(!1):e?.dismiss?.(),this._syncGlobalDismissListener(),!0}return!1}_activateGroupItem(t,e,i){if(t.id!==this._openGroupId)return;const s=t.items.find(t=>t.id===e);if(!s||s.disabled)return;const o="toggle"===s.role&&"stay-open"===s.closePolicy,a=0===i.detail;o||(this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener()),s.invoke(),!o&&a&&this.host.updateComplete().then(()=>{const e=[...this.host.root().querySelectorAll("[data-editor-group]")].find(e=>e.dataset.editorGroup===t.id&&null!==e.offsetParent);e?.focus()})}_groupKeydown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;const e=[...t.currentTarget.querySelectorAll(".editor-group-item:not([disabled])")];if(!e.length)return;t.preventDefault();const i=e.indexOf(this.host.root().activeElement),s="Home"===t.key?0:"End"===t.key?e.length-1:"ArrowLeft"===t.key?i<=0?e.length-1:i-1:(i+1)%e.length;e[s]?.focus()}_clearDismissClick(){this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}_syncGlobalDismissListener(){const t=!this._blocked&&"palette"===this._currentModel?.kind,e=!!this._openGroupId||t||!!this._dismissPointerTarget;e!==this._globalDismissListening&&(this._globalDismissListening=e,e?(window.addEventListener("pointerdown",this._globalDismissGuard,!0),window.addEventListener("click",this._globalDismissGuard,!0)):(window.removeEventListener("pointerdown",this._globalDismissGuard,!0),window.removeEventListener("click",this._globalDismissGuard,!0)))}}const md=t=>t.stopPropagation(),gd=new WeakSet,fd=t=>{t._regSignature="",t._maybeRebuildDevices(),t.requestUpdate()};async function bd(t,e,i,s,o,a=""){const n=t.host,r=n._serverCfg;if(!r)return!1;let l=JSON.parse(JSON.stringify(r));l.markers=l.markers||[];let h=l.markers.find(t=>t.id===e);if(!h){const t=n._devices.find(t=>t.id===e);if(!t||"device"!==t.bindingKind&&"entity"!==t.bindingKind||!t.bindingRef)return!1;h={id:t.id,binding:`${t.bindingKind}:${t.bindingRef}`,space:t.space||null,area:t.area||null,hidden:!!t.hidden},l.markers.push(h)}h.vacuum=function(t,e){const i=e.matrix.map(t=>Number(t.toFixed(6))),s=t?.map_routes;if(Array.isArray(s)&&s.length){const o=s.find(t=>t.id===e.routeId)||s.find(t=>t.source===e.source&&t.map_id===e.mapId);if(o)return{...t,map_routes:ba(s,o.id,i)}}return{...t,source:e.source,calibration:{...t?.calibration||{},[e.mapId]:i}}}(h.vacuum||{},{source:i,mapId:s,routeId:a,matrix:o}),l=t._prepareConfigCandidate(l);const c=n._adoption.beginOptimistic(r,l);n._adoption.stageLocalConfig(l),fd(n),n._saveConfigDebounced.pending()&&n._saveConfigDebounced.cancel();try{return await t._saveConfigNow(c),!0}catch(t){return n._rollbackOptimistic(c),fd(n),n._showToast(n._t("toast.cfg_save_failed",{err:n._errText(t)})),!1}}const vd=yo([qo,ua,na]);function yd(t){return 1===t}function wd(t){return`${t}-${globalThis.crypto?.randomUUID?.()??`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}`}function $d(t){const e=function(t){return JSON.stringify({message:t.message.trim(),contact:t.contact.trim(),previewToken:t.attach&&t.preview?t.preview.token:""})}(t);return{idempotencyKey:t.submissionFingerprint&&t.submissionFingerprint!==e?wd("report"):t.idempotencyKey,fingerprint:e}}function kd(t){return[...t].length}function xd(t,e=Date.now()){const i=t.message.trim();return i?kd(i)>1e4?"message_too_long":kd(t.contact.trim())>320?"contact_too_long":t.attach&&!t.preview?"preview_missing":t.attach&&t.preview.expiresAt<=e?"preview_expired":null:"message_required"}function Md(t,e=Date.now()){return"building"!==t.status&&"sending"!==t.status&&"success"!==t.status&&null===xd(t,e)}function Cd(t){const e=function(t){const e=/Firefox\/(\d+)/i.exec(t);if(e)return{family:"firefox",major:Number(e[1])||0};const i=/(?:Chrome|Chromium|Edg)\/(\d+)/i.exec(t);if(i)return{family:"chromium",major:Number(i[1])||0};const s=/Version\/(\d+).+Safari\//i.exec(t);return s?{family:"webkit",major:Number(s[1])||0}:{family:"unknown",major:0}}(t.userAgent??globalThis.navigator?.userAgent??""),i=t.now??Date.now(),s=Number(t.registryLastSuccess||0),o=s<=0?"unknown":i-s<=6e5?"fresh":"stale",a=["en","ru","de","fr"].includes(t.language)?t.language:"en",n=globalThis.matchMedia?.bind(globalThis);return{browser_family:e.family,browser_major:Math.max(0,Math.min(999,e.major)),language:a,coarse_pointer:t.coarsePointer??!!n?.("(pointer: coarse)").matches,hover_capable:t.hoverCapable??!!n?.("(hover: hover)").matches,registry_access:"full"===t.registryAccess?"full":"limited"===t.registryAccess?"partial":"unavailable",registry_age_bucket:o}}function Sd(t){const e=t&&"object"==typeof t&&"code"in t?String(t.code||""):"";return new Set(["support_invalid_message","support_preview_expired","support_package_too_large","support_rate_limited","support_unavailable","support_rejected","unauthorized"]).has(e)?e:"support_unavailable"}const Pd=[{id:"air_conditioner",group:"appliance",art:{d:"M85 71.5 L85 63 M25 71.5 L25 63 M25 71.5 L89.5 71.5 C90.8807 71.5 92 70.3807 92 69 L92 41.5 C92 40.1193 90.8807 39 89.5 39 L20.5 39 C19.1193 39 18 40.1193 18 41.5 L18 69 C18 70.3807 19.1193 71.5 20.5 71.5 L25 71.5 Z M85 63 C85 61.6193 83.8807 60.5 82.5 60.5 L27.5 60.5 C26.1193 60.5 25 61.6193 25 63 M85 63 L85 66.5 L25 66.5 L25 63",viewW:110,viewH:110}},{id:"armchair",group:"furniture",art:{d:"M77.5 48.5 L77.5 39 C77.5 33.4772 73.0228 29 67.5 29 L42.5 29 C36.9772 29 32.5 33.4772 32.5 39 L32.5 48.5205 M77.5 48.5 C80.8137 48.5 83.5 51.1863 83.5 54.5 C83.5 57.1123 81.8302 59.3334 79.5 60.1572 L79.5 71.5 C79.5 73.7091 77.7091 75.5 75.5 75.5 M77.5 48.5 C74.2576 48.5 71.617 51.072 71.5049 54.2871 C71.5012 54.3576 71.5 54.4286 71.5 54.5 L71.5 61.75 M38 61.75 L38 54 C38 53.2396 37.7873 52.5291 37.4189 51.9238 C36.5228 50.0421 34.6765 48.7002 32.5 48.5205 M32.5 48.5205 C32.3351 48.5069 32.1684 48.5 32 48.5 M75.5 75.5 L34 75.5 M75.5 75.5 L72.5 75.5 M34 75.5 C31.7909 75.5 30 73.7091 30 71.5 L30 60.1572 C27.6698 59.3334 26 57.1123 26 54.5 C26 51.1863 28.6863 48.5 32 48.5 M34 75.5 L36.5 75.5 M32 48.5 C34.3914 48.5 36.4549 49.8996 37.4189 51.9238 M38 61.75 C38 64.3734 40.1266 66.5 42.75 66.5 L66.75 66.5 C69.3734 66.5 71.5 64.3734 71.5 61.75 M38 61.75 C38 59.1266 40.1266 57 42.75 57 L66.75 57 C69.3734 57 71.5 59.1266 71.5 61.75 M36.5 75.5 L44.5 75.5 M36.5 75.5 L36.5 80.5 C36.5 81.3284 37.1716 82 38 82 L41.3921 82 C42.0506 82 42.6321 81.5705 42.8258 80.9411 L44.5 75.5 M44.5 75.5 L64.5 75.5 M72.5 75.5 L64.5 75.5 M72.5 75.5 L72.5 80.5 C72.5 81.3284 71.8284 82 71 82 L67.6079 82 C66.9494 82 66.3679 81.5705 66.1742 80.9411 L64.5 75.5",viewW:110,viewH:110}},{id:"bathtub",group:"sanitary",art:{d:"M28 74.8457 L28 80 C28 80.8284 28.6716 81.5 29.5 81.5 L32.8921 81.5 C33.5506 81.5 34.1321 81.0705 34.3258 80.4411 L35.6923 76 M28.0191 74.8558 C28.0127 74.8524 28.0063 74.8491 28 74.8457 C25.4198 73.4833 23.483 71.0169 22.8673 67.9996 M19.5 51.5 L90 51.5 M19.5 51.5 C18.1193 51.5 17 50.3807 17 49 C17 47.6193 18.1193 46.5 19.5 46.5 M19.5 51.5 L22.8673 67.9996 M90 51.5 C91.3807 51.5 92.5 50.3807 92.5 49 C92.5 47.6193 91.3807 46.5 90 46.5 M90 51.5 L86.6327 67.9996 C85.9778 71.2088 83.8285 73.7948 81 75.0922 M90 46.5 L19.5 46.5 M90 46.5 L20 46.5 M19.5 46.5 L20 46.5 M22.8673 67.9996 C23.4846 71.0243 25.4293 73.4954 28.0191 74.8558 M30 36 L30 34 C30 32.6739 29.4732 31.4021 28.5355 30.4645 C27.5979 29.5268 26.3261 29 25 29 C23.6739 29 22.4021 29.5268 21.4645 30.4645 C20.5268 31.4021 20 32.6739 20 34 L20 46.5 M81 75.0922 C79.7247 75.6771 78.3114 76 76.8347 76 L73.3077 76 M81 75.0922 L81 80 C81 80.8284 80.3284 81.5 79.5 81.5 L76.1079 81.5 C75.4494 81.5 74.8679 81.0705 74.6742 80.4411 L73.3077 76 M73.3077 76 L35.6923 76 M35.6923 76 L32.6653 76 C31.1128 76 29.6303 75.643 28.3047 75 C28.2086 74.9534 28.1134 74.9053 28.0191 74.8558",viewW:110,viewH:110}},{id:"bed",group:"furniture",art:{d:"M16 75.5 L24 75.5 M16 75.5 L16 80.5 C16 81.3284 16.6716 82 17.5 82 L20.8921 82 C21.5506 82 22.1321 81.5705 22.3258 80.9411 L24 75.5 M16 75.5 L15 75.5 M24 75.5 L86.5 75.5 M94.5 75.5 L86.5 75.5 M94.5 75.5 L94.5 80.5 C94.5 81.3284 93.8284 82 93 82 L89.6079 82 C88.9494 82 88.3679 81.5705 88.1742 80.9411 L86.5 75.5 M94.5 75.5 L95.5 75.5 M88 50.1296 L88 31.5 C88 30.1193 86.8807 29 85.5 29 L25 29 C23.6193 29 22.5 30.1193 22.5 31.5 L22.5 50.1296 M87.9383 50.1068 C87.9589 50.1143 87.9795 50.1219 88 50.1296 C91.7967 51.5483 94.5 55.2085 94.5 59.5 M22.5617 50.1068 C22.5411 50.1143 22.5205 50.1219 22.5 50.1296 C18.7033 51.5483 16 55.2085 16 59.5 M94.5 65.5 L94.5 59.5 M94.5 65.5 L16 65.5 M94.5 65.5 L95.5 65.5 M16 65.5 L16 59.5 M16 65.5 L15 65.5 M84.5 49.5 L26 49.5 M84.5 49.5 L80 49.5 M94.5 59.5 C94.5 55.1853 91.7674 51.5088 87.9383 50.1068 C86.8662 49.7142 85.7081 49.5 84.5 49.5 M26 49.5 L30.5 49.5 M16 59.5 C16 55.1853 18.7326 51.5088 22.5617 50.1068 C23.6338 49.7142 24.7919 49.5 26 49.5 M15 75.5 L95.5 75.5 M15 75.5 C14.4477 75.5 14 75.0523 14 74.5 L14 66.5 C14 65.9477 14.4477 65.5 15 65.5 M95.5 75.5 C96.0523 75.5 96.5 75.0523 96.5 74.5 L96.5 66.5 C96.5 65.9477 96.0523 65.5 95.5 65.5 M95.5 65.5 L15 65.5 M51.5 49.5 L51.5 45.5 C51.5 42.7386 49.2614 40.5 46.5 40.5 L35.5 40.5 C32.7386 40.5 30.5 42.7386 30.5 45.5 L30.5 49.5 M51.5 49.5 L30.5 49.5 M51.5 49.5 L59 49.5 M80 49.5 L80 45.5 C80 42.7386 77.7614 40.5 75 40.5 L64 40.5 C61.2386 40.5 59 42.7386 59 45.5 L59 49.5 M80 49.5 L59 49.5",viewW:110,viewH:110}},{id:"bidet",group:"sanitary",art:{d:"M46 67.5 L64.5 67.5 M46 67.5 C40.4772 67.5 36 63.0228 36 57.5 L36 53 M46 67.5 C45.4902 67.5 44.9893 67.4618 44.5 67.3882 L44.5 79.5 C44.5 80.0523 44.9477 80.5 45.5 80.5 L65 80.5 C65.5523 80.5 66 80.0523 66 79.5 L66 67.3882 C65.5107 67.4618 65.0098 67.5 64.5 67.5 M64.5 67.5 C70.0229 67.5 74.5 63.0228 74.5 57.5 L74.5 53 M74.5 53 L74.5 47.5 C74.5 46.9477 74.0523 46.5 73.5 46.5 M74.5 53 L36 53 M36 53 L36 47.5 C36 46.9477 36.4477 46.5 37 46.5 M73.5 46.5 L37 46.5 M73.5 46.5 L60 46.5 M37 46.5 L50.5 46.5 M51.5 40 L59 40 M51.5 40 C50.9477 40 50.5 40.4477 50.5 41 L50.5 46.5 M51.5 40 L53 40 M59 40 C59.5523 40 60 40.4477 60 41 L60 46.5 M59 40 L57.5 40 M60 46.5 L50.5 46.5 M57.5 40 L57.5 30 C57.5 29.4477 57.0523 29 56.5 29 L54 29 C53.4477 29 53 29.4477 53 30 M57.5 40 L53 40 M53 40 L53 30 M53 40 L53 36 M53 30 L53 31.5 M53 31.5 L49 31.5 C48.4477 31.5 48 31.9477 48 32.5 L48 35 C48 35.5523 48.4477 36 49 36 L53 36 M53 31.5 L53 36",viewW:110,viewH:110}},{id:"boiler",group:"appliance",art:{d:"M51.5 81.5 L51.5 86 C51.5 86.5523 51.0523 87 50.5 87 L47.5 87 C46.9477 87 46.5 86.5523 46.5 86 L46.5 81.5 M51.5 81.5 L46.5 81.5 M51.5 81.5 L59 81.5 M46.5 81.5 L44 81.5 M64 81.5 L64 86 C64 86.5523 63.5523 87 63 87 L60 87 C59.4477 87 59 86.5523 59 86 L59 81.5 M64 81.5 L59 81.5 M64 81.5 L66.5 81.5 M74.5 73 L74.5 73.5 C74.5 77.9183 70.9183 81.5 66.5 81.5 M44 81.5 C39.5817 81.5 36 77.9183 36 73.5 L36 73 L36 31 C36 26.5817 39.5817 23 44 23 L66.5 23 C70.9183 23 74.5 26.5817 74.5 31 L74.5 73 M74.5 73 L36 73 M66.5 81.5 L44 81.5 M55 42.5 L58.5 39 M62.5 42.5 C62.5 46.366 59.366 49.5 55.5 49.5 C51.634 49.5 48.5 46.366 48.5 42.5 C48.5 38.634 51.634 35.5 55.5 35.5 C59.366 35.5 62.5 38.634 62.5 42.5 Z",viewW:110,viewH:110}},{id:"chair",group:"furniture",art:{d:"M41.25 60.5 L68.75 60.5 M68.75 60.5 C70.5449 60.5 72 59.0449 72 57.25 C72 55.6281 70.8119 54.2836 69.2585 54.0395 C69.0928 54.0135 68.923 54 68.75 54 L41.25 54 C41.077 54 40.9072 54.0135 40.7415 54.0395 C39.1881 54.2836 38 55.6281 38 57.25 C38 59.0449 39.4551 60.5 41.25 60.5 M41.25 60.5 L46 60.5 M68.75 60.5 L64 60.5 M64 60.5 L69.5 60.5 L69.5 82 C69.5 82.8284 68.8284 83.5 68 83.5 L67.3752 83.5 C66.5972 83.5 65.9483 82.9051 65.8809 82.1299 L64 60.5 Z M64 60.5 L46 60.5 M46 60.5 L40.5 60.5 L40.5 82 C40.5 82.8284 41.1716 83.5 42 83.5 L42.6248 83.5 C43.4028 83.5 44.0517 82.9051 44.1191 82.1299 L46 60.5 Z M40.7415 54.0395 C40.5847 53.5546 40.5 53.0372 40.5 52.5 L40.5 39.5 C40.5 32.5964 46.0964 27 53 27 L57 27 C63.9036 27 69.5 32.5964 69.5 39.5 L69.5 52.5 C69.5 53.0372 69.4153 53.5546 69.2585 54.0395",viewW:110,viewH:110}},{id:"coffee_table",group:"furniture",art:{d:"M85.2381 55 L86.5 55 C87.0523 55 87.5 54.5523 87.5 54 L87.5 51 L84.6598 43.4847 C84.2586 42.5818 83.3633 42 82.3753 42 L26.6247 42 C25.6367 42 24.7414 42.5818 24.3402 43.4847 L21.5 51 L21.5 54 C21.5 54.5523 21.9477 55 22.5 55 L25 55 M87.5 51 L21.5 51 M25 55 L25 66.5 C25 67.3284 25.6716 68 26.5 68 L27.2113 68 C27.983 68 28.6288 67.4144 28.7041 66.6464 L29.8459 55 M25 55 L29.8459 55 M29.8459 55 L80.3922 55 M80.3922 55 L81.534 66.6464 C81.6093 67.4144 82.2551 68 83.0268 68 L83.7381 68 C84.5665 68 85.2381 67.3284 85.2381 66.5 L85.2381 55 M80.3922 55 L85.2381 55",viewW:110,viewH:110}},{id:"computer",group:"appliance",art:{d:"M43 65 L48 65 M43 65 L24.5 65 C23.1193 65 22 63.8807 22 62.5 L22 40.5 C22 39.1193 23.1193 38 24.5 38 L64.5 38 C65.8807 38 67 39.1193 67 40.5 L67 62.5 C67 63.8807 65.8807 65 64.5 65 L48 65 M43 65 L43 72 M48 65 L48 72 M37 72 L43 72 M54.0711 72 L48 72 M76 60 L84 60 M76 43 L84 43 M35 53 L35 46 L39.5 46 C40.4283 46 41.3185 46.3687 41.9749 47.0251 C42.6313 47.6815 43 48.5717 43 49.5 C43 50.4283 42.6312 51.3185 41.9749 51.9749 C41.3185 52.6313 40.4283 53 39.5 53 L35 53 Z M35 53 L35 56 M54.5355 54.5355 C53.8363 55.2348 52.9454 55.711 51.9755 55.9039 C51.0055 56.0969 50.0002 55.9978 49.0866 55.6194 C48.173 55.241 47.3921 54.6001 46.8427 53.7779 C46.2932 52.9556 46 51.9889 46 51 C46 50.0111 46.2932 49.0444 46.8427 48.2221 C47.3921 47.3999 48.173 46.759 49.0866 46.3806 C50.0002 46.0022 51.0055 45.9031 51.9755 46.0961 C52.9454 46.289 53.8363 46.7652 54.5355 47.4645 M48 72 L43 72 M74.5 72 L85.5 72 C86.8807 72 88 70.8807 88 69.5 L88 40.5 C88 39.1193 86.8807 38 85.5 38 L74.5 38 C73.1193 38 72 39.1193 72 40.5 L72 69.5 C72 70.8807 73.1193 72 74.5 72 Z",viewW:110,viewH:110}},{id:"cooktop",group:"appliance",art:{d:"M25 31.5 C25 30.1193 26.1193 29 27.5 29 L82.5 29 C83.8807 29 85 30.1193 85 31.5 L85 78.5 C85 79.8807 83.8807 81 82.5 81 L27.5 81 C26.1193 81 25 79.8807 25 78.5 L25 31.5 Z M49.5 66.5 C49.5 70.9183 45.9183 74.5 41.5 74.5 C37.0817 74.5 33.5 70.9183 33.5 66.5 C33.5 62.0817 37.0817 58.5 41.5 58.5 C45.9183 58.5 49.5 62.0817 49.5 66.5 Z M76 43.5 C76 47.9183 72.4183 51.5 68 51.5 C63.5817 51.5 60 47.9183 60 43.5 C60 39.0817 63.5817 35.5 68 35.5 C72.4183 35.5 76 39.0817 76 43.5 Z M73 66.5 C73 69.2614 70.7614 71.5 68 71.5 C65.2386 71.5 63 69.2614 63 66.5 C63 63.7386 65.2386 61.5 68 61.5 C70.7614 61.5 73 63.7386 73 66.5 Z M49.5 43.5 C49.5 47.9183 45.9183 51.5 41.5 51.5 C37.0817 51.5 33.5 47.9183 33.5 43.5 C33.5 39.0817 37.0817 35.5 41.5 35.5 C45.9183 35.5 49.5 39.0817 49.5 43.5 Z",viewW:110,viewH:110}},{id:"dining_table",group:"furniture",art:{d:"M26.875 47 L23.5 47 C22.9477 47 22.5 46.5523 22.5 46 L22.5 43 L24.8802 35.5939 C25.2539 34.633 26.1791 34 27.2102 34 L83.7898 34 C84.8209 34 85.7462 34.633 86.1198 35.5939 L88.5 43 L88.5 46 C88.5 46.5523 88.0523 47 87.5 47 L84.125 47 M22.5 43 L88.5 43 M78.875 47 L84.742 73.8205 C84.8926 74.5092 85.5024 75 86.2073 75 L86.7474 75 C87.6682 75 88.3716 74.1781 88.2294 73.2684 L84.125 47 M78.875 47 L84.125 47 M78.875 47 L32.125 47 M32.125 47 L26.258 73.8205 C26.1074 74.5092 25.4976 75 24.7927 75 L24.2526 75 C23.3318 75 22.6284 74.1781 22.7706 73.2684 L26.875 47 M32.125 47 L26.875 47",viewW:110,viewH:110}},{id:"dishwasher",group:"appliance",art:{d:"M29 76C29 77.3807 30.1193 78.5 31.5 78.5H78.5C79.8807 78.5 81 77.3807 81 76M29 76V82.5C29 83.8807 30.1193 85 31.5 85H78.5C79.8807 85 81 83.8807 81 82.5V76M29 76V40M81 76V40M81 40C81 38.6193 79.8807 37.5 78.5 37.5H31.5C30.1193 37.5 29 38.6193 29 40M81 40V27.5C81 26.1193 79.8807 25 78.5 25H31.5C30.1193 25 29 26.1193 29 27.5V40M43 42H67M35.75 31H45.25M69.5 31C69.5 32.1046 68.6046 33 67.5 33C66.3954 33 65.5 32.1046 65.5 31C65.5 29.8954 66.3954 29 67.5 29C68.6046 29 69.5 29.8954 69.5 31ZM77 31C77 32.1046 76.1046 33 75 33C73.8954 33 73 32.1046 73 31C73 29.8954 73.8954 29 75 29C76.1046 29 77 29.8954 77 31Z",viewW:110,viewH:110}},{id:"dryer",group:"appliance",art:{d:"M81 82.5 L81 27.5 M81 82.5 C81 83.8807 79.8807 85 78.5 85 L31.5 85 C30.1193 85 29 83.8807 29 82.5 L29 55.5 M81 82.5 L81 40 M81 27.5 C81 26.1193 79.8807 25 78.5 25 L31.5 25 C30.1193 25 29 26.1193 29 27.5 M81 27.5 L81 40 M29 27.5 L29 55.5 M29 27.5 L29 40 M81 40 C81 38.6193 79.8807 37.5 78.5 37.5 L31.5 37.5 C30.1193 37.5 29 38.6193 29 40 M29 40 L29 55.5 M35.75 31 L45.25 31 M55.9943 55 C55.9943 55 54.6654 56.8105 54.5153 58.1429 C54.3169 59.9042 56.1139 60.6968 55.9943 62.4643 C55.8942 63.9429 54.5153 66 54.5153 66 M60.4943 55 C60.4943 55 59.1654 56.8105 59.0153 58.1429 C58.8169 59.9042 60.6139 60.6968 60.4943 62.4643 C60.3942 63.9429 59.0153 66 59.0153 66 M50.9943 55 C50.9943 55 49.6654 56.8105 49.5153 58.1429 C49.3169 59.9042 51.1139 60.6968 50.9943 62.4643 C50.8942 63.9429 49.5153 66 49.5153 66 M72 60.5 C72 69.8888 64.3888 77.5 55 77.5 C45.6112 77.5 38 69.8888 38 60.5 C38 51.1112 45.6112 43.5 55 43.5 C64.3888 43.5 72 51.1112 72 60.5 Z M66.5 60.5 C66.5 66.8513 61.3513 72 55 72 C48.6487 72 43.5 66.8513 43.5 60.5 C43.5 54.1487 48.6487 49 55 49 C61.3513 49 66.5 54.1487 66.5 60.5 Z M69.5 31 C69.5 32.1046 68.6046 33 67.5 33 C66.3954 33 65.5 32.1046 65.5 31 C65.5 29.8954 66.3954 29 67.5 29 C68.6046 29 69.5 29.8954 69.5 31 Z M77 31 C77 32.1046 76.1046 33 75 33 C73.8954 33 73 32.1046 73 31 C73 29.8954 73.8954 29 75 29 C76.1046 29 77 29.8954 77 31 Z",viewW:110,viewH:110}},{id:"exercise",group:"other",art:{d:"M55.091 60.072 L65.7741 35.5156 M42.2119 56.2083 L55.091 60.072 L60.8511 61.8001 L66.5032 63.4957 C70.733 64.7646 73.6297 68.6579 73.6297 73.074 L73.6297 76.2635 L29.3385 76.2635 L29.3385 65.7866 C29.3385 60.9371 32.7227 57.0804 37.0256 56.051 C38.5108 55.6956 40.1055 55.6771 41.7081 56.0709 M41.7081 56.0709 C41.876 56.1122 42.044 56.1579 42.2119 56.2083 L60.8511 61.8001 M71.9311 35.5156 L76.4108 35.5156 C78.2451 35.5156 79.9321 34.5112 80.8064 32.8987 L83.8375 27.308 C84.3011 26.4529 83.9993 25.384 83.1569 24.8976 C82.2982 24.4018 81.2002 24.696 80.7045 25.5547 L77.8652 30.4723 C77.3293 31.4005 76.3389 31.9723 75.2671 31.9723 L65.6573 31.9723 C64.6788 31.9723 63.8856 32.7655 63.8856 33.744 C63.8856 34.7224 64.6788 35.5156 65.6573 35.5156 L65.7741 35.5156 M71.9311 35.5156 C71.9603 35.7673 71.9261 36.0298 71.8188 36.2793 L60.8511 61.8001 M71.9311 35.5156 L65.7741 35.5156 M41.7081 56.0709 L38.03 42.6022 M37.0256 56.051 L33.3529 42.6022 M38.03 42.6022 L33.3529 42.6022 L29.7814 42.6022 C28.5583 42.6022 27.5668 41.6107 27.5668 40.3876 C27.5668 39.1646 28.5583 38.1731 29.7814 38.1731 L41.2971 38.1731 C42.5202 38.1731 43.5117 39.1646 43.5117 40.3876 C43.5117 41.6107 42.5202 42.6022 41.2971 42.6022 L38.03 42.6022 Z M25.7952 78.921 C25.7952 77.4533 26.985 76.2635 28.4526 76.2635 L74.5155 76.2636 C75.9832 76.2636 77.173 77.4533 77.173 78.921 C77.173 80.3887 75.9832 81.5785 74.5155 81.5785 L28.4526 81.5785 C26.985 81.5785 25.7952 80.3887 25.7952 78.921 Z M29.3385 81.5785 L29.3385 84.5677 C29.3385 85.3962 30.01 86.0677 30.8385 86.0677 L33.6379 86.0677 C34.2512 86.0677 34.8028 85.6943 35.0306 85.1248 L36.5002 81.5785 L29.3385 81.5785 Z M73.6297 81.5785 L73.6297 84.5677 C73.6297 85.3962 72.9581 86.0677 72.1297 86.0677 L69.3303 86.0677 C68.717 86.0677 68.1654 85.6943 67.9376 85.1248 L66.5002 81.5785 L73.6297 81.5785 Z M45.2833 66.0766 C45.2833 68.7673 43.102 70.9486 40.4113 70.9486 C37.7205 70.9486 35.5392 68.7673 35.5392 66.0766 C35.5392 63.3858 37.7205 61.2045 40.4113 61.2045 C43.102 61.2045 45.2833 63.3858 45.2833 66.0766 Z",viewW:110,viewH:110}},{id:"fireplace",group:"other",art:{d:"M71.1884 73.8943 L71.1884 50.4399 C71.1884 47.6784 68.9498 45.4399 66.1884 45.4399 L43.1445 45.4399 C40.3831 45.4399 38.1445 47.6784 38.1445 50.4399 L38.1445 73.8942 M38.1445 73.8942 L26.7031 73.8942 L26.7031 34.4252 L82.6629 34.4252 L82.6629 73.8942 L71.1884 73.8943 L38.1445 73.8942 Z M62.0101 62.8795 L47.3239 62.8795 C45.8031 62.8795 44.5703 64.1124 44.5703 65.6332 C44.5703 67.154 45.8031 68.3868 47.3239 68.3868 M47.3239 68.3868 C45.8031 68.3868 44.5703 69.6195 44.5703 71.1403 C44.5703 72.6611 45.8031 73.894 47.3239 73.894 M47.3239 68.3868 C48.8447 68.3868 50.0776 69.6195 50.0776 71.1403 C50.0776 72.6611 48.8447 73.894 47.3239 73.894 M47.3239 68.3868 L61.9918 68.3868 M47.3239 73.894 L62.0101 73.894 C63.5309 73.894 64.7637 72.6611 64.7637 71.1403 C64.7637 69.6242 63.5385 68.3945 62.0243 68.3869 M62.0114 68.3869 C62.0049 68.3869 61.9983 68.3869 61.9918 68.3868 M62.0114 68.3869 C62.0157 68.3869 62.02 68.3869 62.0243 68.3869 M62.0114 68.3869 L62.0243 68.3869 M62.0114 68.3869 L61.9918 68.3868 M61.9918 68.3868 C60.48 68.3763 59.2578 67.1475 59.2578 65.6332 C59.2578 64.1124 60.4906 62.8796 62.0114 62.8796 C63.5322 62.8796 64.7651 64.1124 64.7651 65.6332 C64.7651 67.1498 63.5392 68.3799 62.0243 68.3869 M61.9918 68.3868 L62.0101 68.3868 C62.0148 68.3868 62.0195 68.3868 62.0243 68.3869 M24 81.6962 L85.3341 81.6962 C85.8864 81.6962 86.3341 81.2485 86.3341 80.6962 L86.3341 74.8942 C86.3341 74.3419 85.8864 73.8942 85.3341 73.8942 L24 73.8942 C23.4477 73.8942 23 74.3419 23 74.8942 L23 80.6962 C23 81.2485 23.4477 81.6962 24 81.6962 Z M24 34.4252 L85.3341 34.4252 C85.8864 34.4252 86.3341 33.9775 86.3341 33.4252 L86.3341 29 C86.3341 28.4477 85.8864 28 85.3341 28 L24 28 C23.4477 28 23 28.4477 23 29 L23 33.4252 C23 33.9775 23.4477 34.4252 24 34.4252 Z",viewW:110,viewH:110}},{id:"fridge",group:"appliance",art:{d:"M35.5 87 C34.1193 87 33 85.8807 33 84.5 M35.5 87 L74.5 87 M35.5 87 L35.5 90.5 C35.5 91.0523 35.9477 91.5 36.5 91.5 L73.5 91.5 C74.0523 91.5 74.5 91.0523 74.5 90.5 L74.5 87 M33 84.5 L33 20.5 M33 84.5 L33 46.5 M77.5 84.5 L77.5 20.5 M77.5 84.5 C77.5 85.8807 76.3807 87 75 87 L74.5 87 M77.5 84.5 L77.5 46.5 M77.5 20.5 C77.5 19.1193 76.3807 18 75 18 L35.5 18 C34.1193 18 33 19.1193 33 20.5 M77.5 20.5 L77.5 46.5 M33 20.5 L33 46.5 M33 46.5 L77.5 46.5 M38.5 41 L38.5 31.5 M38.5 62 L38.5 52.5",viewW:110,viewH:110}},{id:"hood",group:"appliance",art:{d:"M66 57 L83 69 L83 71.5 C83 72.8807 81.8807 74 80.5 74 L29.5 74 C28.1193 74 27 72.8807 27 71.5 L27 69 L44 57 M44 57 L66 57 M44 57 L44 37.5 C44 36.1193 45.1193 35 46.5 35 L63.5 35 C64.8807 35 66 36.1193 66 37.5 L66 57 M83 69 L27 69",viewW:110,viewH:110}},{id:"kitchen_cabinet",group:"furniture",art:{d:"M72 84.95 L72 88 C72 88.5523 71.5523 89 71 89 L39 89 C38.4477 89 38 88.5523 38 88 L38 84.95 M55 20 L71.5 20 C72.8807 20 74 21.1193 74 22.5 L74 39.5 C74 40.8807 72.8807 42 71.5 42 L55 42 M55 20 L55 42 M55 20 L38.5 20 C37.1193 20 36 21.1193 36 22.5 L36 39.5 C36 40.8807 37.1193 42 38.5 42 L55 42 M59 33 L59 38 M51 33 L51 38 M55 85 L71.5 85 C72.8807 85 74 83.8807 74 82.5 L74 65.5 C74 64.1193 72.8807 63 71.5 63 L55 63 M55 85 L55 63 M55 85 L38.5 85 C37.1193 85 36 83.8807 36 82.5 L36 65.5 C36 64.1193 37.1193 63 38.5 63 L55 63 M67 67 L62 67 M48 67 L43 67",viewW:110,viewH:110}},{id:"kitchen_sink",group:"sanitary",art:{d:"M49 54 L49 59 M51.5 37.5 L44 37.5 M51.5 37.5 C52.0523 37.5 52.5 37.9477 52.5 38.5 L52.5 44 M51.5 37.5 L48 37.5 M44 37.5 C43.4477 37.5 43 37.9477 43 38.5 L43 44 M44 37.5 L48 37.5 M43 44 L21.5 44 C20.1193 44 19 45.1193 19 46.5 L19 81.5 C19 82.8807 20.1193 84 21.5 84 L89.5 84 C90.8807 84 92 82.8807 92 81.5 L92 46.5 C92 45.1193 90.8807 44 89.5 44 L52.5 44 M43 44 L52.5 44 M58 33 L58 31 C58 29.6739 57.4732 28.4021 56.5355 27.4645 C55.5979 26.5268 54.3261 26 53 26 C51.6739 26 50.4021 26.5268 49.4645 27.4645 C48.5268 28.4021 48 29.6739 48 31 L48 37.5 M62 54 L62 59 M26 50 L52.5 50 C53.0523 50 53.5 50.4477 53.5 51 L53.5 77 C53.5 77.5523 53.0523 78 52.5 78 L26 78 C25.4477 78 25 77.5523 25 77 L25 51 C25 50.4477 25.4477 50 26 50 Z M58.5 50 L85 50 C85.5523 50 86 50.4477 86 51 L86 77 C86 77.5523 85.5523 78 85 78 L58.5 78 C57.9477 78 57.5 77.5523 57.5 77 L57.5 51 C57.5 50.4477 57.9477 50 58.5 50 Z",viewW:110,viewH:110}},{id:"nightstand",group:"furniture",art:{d:"M34.5 76 C33.1193 76 32 74.8807 32 73.5 M34.5 76 L41.2308 76 M34.5 76 C34.3288 76 34.1616 75.9828 34 75.95 L34 78.5 C34 79.3284 34.6716 80 35.5 80 L38.8921 80 C39.5506 80 40.1321 79.5705 40.3258 78.9411 L41.2308 76 M32 73.5 L32 33 M32 73.5 L32 57.5 M78 73.5 L78 33 M69.2692 76 L75.5 76 C75.8556 76 76.1938 75.9258 76.5 75.792 C77.383 75.4062 78 74.5252 78 73.5 M78 73.5 L78 57.5 M78 33 C78 31.6193 76.8807 30.5 75.5 30.5 L34.5 30.5 C33.1193 30.5 32 31.6193 32 33 M78 33 L78 39.5 M32 33 L32 39.5 M32 39.5 L78 39.5 M32 39.5 L32 57.5 M78 39.5 L78 57.5 M78 57.5 L32 57.5 M50.5 48.5 L60 48.5 M50.5 66 L60 66 M41.2308 76 L69.2692 76 M69.2692 76 L70.1742 78.9411 C70.3679 79.5705 70.9494 80 71.6079 80 L75 80 C75.8284 80 76.5 79.3284 76.5 78.5 L76.5 75.792",viewW:110,viewH:110}},{id:"oven",group:"appliance",art:{d:"M29 76 C29 77.3807 30.1193 78.5 31.5 78.5 L78.5 78.5 C79.8807 78.5 81 77.3807 81 76 M29 76 L29 40 M29 76 L29 82.5 C29 83.8807 30.1193 85 31.5 85 L78.5 85 C79.8807 85 81 83.8807 81 82.5 L81 76 M81 76 L81 40 M81 40 C81 38.6193 79.8807 37.5 78.5 37.5 L31.5 37.5 C30.1193 37.5 29 38.6193 29 40 M81 40 L81 27.5 C81 26.1193 79.8807 25 78.5 25 L31.5 25 C30.1193 25 29 26.1193 29 27.5 L29 40 M35.75 31 L45.25 31 M43 42 L67 42 M40.5 72 L69.5 72 C70.8807 72 72 70.8807 72 69.5 L72 49.5 C72 48.1193 70.8807 47 69.5 47 L40.5 47 C39.1193 47 38 48.1193 38 49.5 L38 69.5 C38 70.8807 39.1193 72 40.5 72 Z M69.5 31 C69.5 32.1046 68.6046 33 67.5 33 C66.3954 33 65.5 32.1046 65.5 31 C65.5 29.8954 66.3954 29 67.5 29 C68.6046 29 69.5 29.8954 69.5 31 Z M77 31 C77 32.1046 76.1046 33 75 33 C73.8954 33 73 32.1046 73 31 C73 29.8954 73.8954 29 75 29 C76.1046 29 77 29.8954 77 31 Z",viewW:110,viewH:110}},{id:"plant",group:"other",art:{d:"M55.7064 55.8805 L55.7064 52.9357 M55.7064 52.9357 C56.839 47.0461 62.7965 41.9801 68.6182 37.5322 M55.7064 52.9357 C50.7678 48.7899 47.7236 46.7763 41.6621 43.8748 M67.4992 61.3174 L65.9151 75.8488 C65.7779 77.1181 64.7063 78.0801 63.4296 78.0801 L48.4373 78.0801 C47.1606 78.0801 46.089 77.1181 45.9518 75.8488 L44.3593 61.3174 L67.4992 61.3174 Z M60.2363 44.7807 C58.4234 36.1732 66.8047 29.604 76.9989 31.869 C76.9989 40.024 68.3904 48.6318 60.2363 44.7807 Z M50.476 49.9288 C51.9926 41.2641 43.391 34.9863 33.2805 37.5996 C33.5602 45.7498 42.4589 54.0573 50.476 49.9288 Z M43.1152 61.3174 L68.7509 61.3174 C69.3031 61.3174 69.7509 60.8697 69.7509 60.3174 L69.7509 56.8809 C69.7509 56.3286 69.3031 55.8809 68.7509 55.8809 L43.1152 55.8809 C42.5629 55.8809 42.1152 56.3286 42.1152 56.8809 L42.1152 60.3174 C42.1152 60.8697 42.5629 61.3174 43.1152 61.3174 Z",viewW:110,viewH:110}},{id:"rug",group:"other",art:{d:"M90.2693 33.8735 L84.648 33.8735 M25.6208 33.8735 L19.9995 33.8735 M90.2693 39.0264 L84.648 39.0264 M25.6208 39.0264 L19.9995 39.0264 M90.2693 44.1792 L84.648 44.1792 M25.6208 44.1792 L19.9995 44.1792 M90.2693 49.332 L84.648 49.332 M25.6208 49.332 L19.9995 49.332 M90.2693 54.4854 L84.648 54.4854 M25.6208 54.4854 L19.9995 54.4854 M90.2693 59.6382 L84.648 59.6382 M25.6208 59.6382 L19.9995 59.6382 M90.2693 64.791 L84.648 64.791 M25.6208 64.791 L19.9995 64.791 M90.2693 69.9438 L84.648 69.9438 M25.6208 69.9438 L19.9995 69.9438 M90.2693 75.0967 L84.648 75.0967 M25.6208 75.0967 L19.9995 75.0967 M28.121 32 L82.145 32 C83.5257 32 84.645 33.1193 84.645 34.5 L84.645 74.939 C84.645 76.3197 83.5257 77.439 82.145 77.439 L28.121 77.439 C26.7403 77.439 25.621 76.3197 25.621 74.939 L25.621 34.5 C25.621 33.1193 26.7403 32 28.121 32 Z M29.8369 32 L29.8369 77.439 M80.4302 32 L80.4302 77.439 M37.8005 54.4852 L55.6014 46.0532 L73.4022 54.4852 L55.6014 62.9172 L37.8005 54.4852 Z",viewW:110,viewH:110}},{id:"shelving",group:"furniture",art:{d:"M64 58.5 L64 47 C64 46.4477 64.4477 46 65 46 L68 46 C68.5523 46 69 46.4477 69 47 M64 58.5 L69 58.5 M64 58.5 L28 58.5 L28 39 L35.5 39 M69 58.5 L69 47 M69 58.5 L69 44.5 M69 58.5 L76 58.5 M69 47 L69 44.5 M52.5 39 L52.5 27.5 C52.5 26.9477 52.0523 26.5 51.5 26.5 L48.5 26.5 C47.9477 26.5 47.5 26.9477 47.5 27.5 M52.5 39 L47.5 39 M52.5 39 L81 39 L81 58.5 L76 58.5 M47.5 39 L47.5 27.5 M47.5 39 L47.5 25 M47.5 39 L40.5 39 M47.5 27.5 L47.5 25 M40.5 39 L40.5 27.5 M40.5 39 L40.5 25 M40.5 39 L35.5 39 M35.5 39 L35.5 27.5 C35.5 26.9477 35.9477 26.5 36.5 26.5 L39.5 26.5 C40.0523 26.5 40.5 26.9477 40.5 27.5 M40.5 27.5 L40.5 25 M49 72 L36.5 72 M50.5 72 L36.5 72 C35.9477 72 35.5 71.5523 35.5 71 L35.5 68.5 C35.5 67.9477 35.9477 67.5 36.5 67.5 L49 67.5 C49.5523 67.5 50 67.9477 50 68.5 L50 71 C50 71.5523 49.5523 72 49 72 M50.5 78 C51.0523 78 51.5 77.5523 51.5 77 L51.5 73 C51.5 72.4477 51.0523 72 50.5 72 L49 72 M36.5 72 C35.9477 72 35.5 72.4477 35.5 73 L35.5 77 C35.5 77.5523 35.9477 78 36.5 78 M76 58.5 L76 44.5 C76 43.9477 75.5523 43.5 75 43.5 L70 43.5 C69.4477 43.5 69 43.9477 69 44.5 M47.5 25 C47.5 24.4477 47.0523 24 46.5 24 L41.5 24 C40.9477 24 40.5 24.4477 40.5 25 M50.5 78 L36.5 78 M50.5 78 L81 78 L81 85 L28 85 L28 78 L36.5 78 M28 89.5 L28 23 C28 21.6193 29.1193 20.5 30.5 20.5 L78.5 20.5 C79.8807 20.5 81 21.6193 81 23 L81 89.5",viewW:110,viewH:110}},{id:"shower",group:"sanitary",art:{d:"M39 84 L39 31.7143 C39 25.245 44.2564 20 50.75 20 C56.4663 20 61.2394 24.5462 62.1824 29.0091 M51.5 39.25 C51.5 33.5891 56.0891 29 61.75 29 C67.4109 29 72 33.5891 72 39.25 L51.5 39.25 M54.75 44.25 L54.75 46.75 M62 44.25 L62 46.75 M69.25 44.25 L69.25 46.75 M54.75 50.5 L54.75 53 M62 50.5 L62 53 M69.25 50.5 L69.25 53 M54.75 56.75 L54.75 59.25 M62 56.75 L62 59.25 M69.25 56.75 L69.25 59.25 M54.75 63 L54.75 65.5 M62 63 L62 65.5 M69.25 63 L69.25 65.5 M31 84 L80 84 C80.5523 84 81 84.4477 81 85 L81 88 C81 88.5523 80.5523 89 80 89 L31 89 C30.4477 89 30 88.5523 30 88 L30 85 C30 84.4477 30.4477 84 31 84",viewW:110,viewH:110}},{id:"sink",group:"sanitary",art:{d:"M51 41.5 L58.5 41.5 M51 41.5 C50.4477 41.5 50 41.9477 50 42.5 L50 48 M51 41.5 L55 41.5 M58.5 41.5 C59.0523 41.5 59.5 41.9477 59.5 42.5 L59.5 48 M58.5 41.5 L55 41.5 M59.5 48 L77 48 C78.3807 48 79.5 49.1193 79.5 50.5 L79.5 57 C79.5 62.5228 75.0228 67 69.5 67 L40 67 C34.4772 67 30 62.5228 30 57 L30 50.5 C30 49.1193 31.1193 48 32.5 48 L50 48 M59.5 48 L50 48 M45 37 L45 35 C45 33.6739 45.5268 32.4021 46.4645 31.4645 C47.4021 30.5268 48.6739 30 50 30 C51.3261 30 52.5979 30.5268 53.5355 31.4645 C54.4732 32.4021 55 33.6739 55 35 L55 41.5 M45 80 L64.5 80 C65.0523 80 65.5 79.5523 65.5 79 L65.5 67 L44 67 L44 79 C44 79.5523 44.4477 80 45 80 Z",viewW:110,viewH:110}},{id:"sofa",group:"furniture",art:{d:"M88.5 44.6689 L88.5 34 C88.5 31.2386 86.2614 29 83.5 29 L59.5 29 C56.7386 29 54.5 31.2386 54.5 34 M88.5 44.6689 C89.2354 44.2435 90.0893 44 91 44 M88.5 44.6689 C88.3992 44.7272 88.3006 44.7889 88.2045 44.8539 M54.5 61.75 L54.5 34 M54.5 61.75 C54.5 64.3734 52.3734 66.5 49.75 66.5 L25.25 66.5 C22.6266 66.5 20.5 64.3734 20.5 61.75 M54.5 61.75 C54.5 59.1266 52.3734 57 49.75 57 L25.25 57 C24.6761 57 24.1261 57.1018 23.6168 57.2882 M54.5 61.75 C54.5 64.3734 56.6266 66.5 59.25 66.5 L83.75 66.5 C86.3734 66.5 88.5 64.3734 88.5 61.75 M88.5 61.75 C88.5 59.9118 87.4558 58.3175 85.9283 57.5278 C85.8889 57.5075 85.8493 57.4877 85.8093 57.4684 C85.1863 57.1682 84.4878 57 83.75 57 L59.25 57 C56.6266 57 54.5 59.1266 54.5 61.75 M54.5 34 C54.5 31.2386 52.2614 29 49.5 29 L25.5 29 C22.7386 29 20.5 31.2386 20.5 34 L20.5 44.416 M20.5 44.416 C19.8875 44.1484 19.2111 44 18.5 44 M20.5 44.416 C22.2659 45.1876 23.5 46.9497 23.5 49 M18.5 44 C21.2614 44 23.5 46.2386 23.5 49 M18.5 44 L18 44 C15.2386 44 13 46.2386 13 49 L13 70.5 C13 73.2614 15.2386 75.5 18 75.5 M23.5 49 L23.5 57.3328 M23.5 57.3328 C21.7427 58.0295 20.5 59.7446 20.5 61.75 M23.5 57.3328 C23.5387 57.3174 23.5776 57.3026 23.6168 57.2882 M91 44 C89.9645 44 89.0025 44.3148 88.2045 44.8539 C86.8744 45.7525 86 47.2741 86 49 L86 57.5657 M85.9283 57.5278 C85.9523 57.5402 85.9762 57.5528 86 57.5657 C87.4884 58.3677 88.5 59.9407 88.5 61.75 M91 44 L91.5 44 C94.2614 44 96.5 46.2386 96.5 49 L96.5 70.5 C96.5 73.2614 94.2614 75.5 91.5 75.5 M91.5 75.5 L18 75.5 M91.5 75.5 L90.5 75.5 M18 75.5 L18.5 75.5 M20.5 61.75 C20.5 59.7005 21.798 57.9542 23.6168 57.2882 M18.5 75.5 L26.5 75.5 M18.5 75.5 L18.5 80.5 C18.5 81.3284 19.1716 82 20 82 L23.3921 82 C24.0506 82 24.6321 81.5705 24.8258 80.9411 L26.5 75.5 M26.5 75.5 L82.5 75.5 M90.5 75.5 L82.5 75.5 M90.5 75.5 L90.5 80.5 C90.5 81.3284 89.8284 82 89 82 L85.6079 82 C84.9494 82 84.3679 81.5705 84.1742 80.9411 L82.5 75.5",viewW:110,viewH:110}},{id:"stairs",group:"other",art:{d:"M73.4707 46.8057 L73.4707 28.5242 M73.4707 46.8057 L73.1504 46.8057 M73.4707 46.8057 L82.6039 46.8057 M73.4707 28.5242 L73.425 28.5242 M73.4707 28.5242 L75.6731 28.5242 M62.8987 54.2946 L62.8987 36.7397 M61.5762 61.7837 L61.5762 55.2944 C61.5762 54.7421 62.0239 54.2944 62.5762 54.2944 L62.8987 54.2946 L72.1504 54.2945 M52.3262 61.7837 L52.3262 45.1306 M52.3262 61.7837 L52.0039 61.7837 M52.3262 61.7837 L61.5762 61.7837 M62.8987 36.7397 L52.3262 45.1306 L42.1934 53.1725 L31.6211 61.5632 M42.1934 69.2725 L42.1934 53.1725 M42.1934 69.2725 L41.873 69.2725 M83.6035 69.2725 L83.6024 69.2725 L51.0039 69.2725 L42.1934 69.2725 M83.6031 76.7612 L83.6031 83.25 C83.6031 83.8023 83.1554 84.25 82.6031 84.25 L31.6231 84.2499 M41.873 69.2725 L83.6035 69.2725 L83.6031 76.7612 M83.6031 76.7612 L31.6231 76.7612 M31.6231 76.7612 L40.873 76.7613 L83.6031 76.7612 M31.6231 84.2499 L27.7773 84.2499 C27.2251 84.2499 26.7773 83.8021 26.7773 83.2499 L26.7773 57.4971 C26.7773 56.9448 27.2251 56.4971 27.7773 56.4971 L28.9352 56.4971 M31.6231 84.2499 L31.6231 76.7612 M31.6231 76.7612 L31.6211 61.5632 L31.6231 56.4971 M29.0212 56.4971 L31.6231 56.4971 L31.6228 57.2227 M31.6211 61.5632 L62.8987 36.7397 M31.6211 61.5632 L31.6228 57.2227 M73.425 28.5242 L75.6731 28.5242 M73.425 28.5242 C73.3119 28.5242 73.202 28.5624 73.1134 28.6328 L62.8987 36.7397 M75.6731 28.5242 C76.6463 28.5242 77.4352 27.7353 77.4352 26.7621 C77.4352 25.7889 76.6463 25 75.6731 25 L71.9495 25 C71.7935 25 71.6421 25.0532 71.5204 25.1508 L31.6228 57.2227 M41.873 69.2725 C41.3208 69.2725 40.873 69.7202 40.873 70.2725 L40.873 76.7613 M52.0039 61.7837 L83.6024 61.7837 M52.0039 61.7837 C51.4516 61.7837 51.0039 62.2314 51.0039 62.7837 L51.0039 69.2725 M83.6022 54.2944 L83.6024 61.7837 L83.6024 69.2725 M83.6024 61.7837 L61.5762 61.7837 M83.6022 54.2944 L83.6039 47.8057 C83.6039 47.2534 83.1562 46.8057 82.6039 46.8057 M83.6022 54.2944 L72.1504 54.2945 M73.1504 46.8057 L82.6039 46.8057 M73.1504 46.8057 C72.5981 46.8057 72.1504 47.2534 72.1504 47.8057 L72.1504 54.2945 M28.9352 56.4971 C28.9495 56.4973 28.9638 56.4974 28.9782 56.4974 C28.9925 56.4974 29.0069 56.4973 29.0212 56.4971 M28.9352 56.4971 C27.2519 56.4741 25.8945 55.1024 25.8945 53.4137 C25.8945 51.7107 27.2751 50.3301 28.9782 50.3301 C30.6812 50.3301 32.0618 51.7107 32.0618 53.4137 C32.0618 55.1024 30.7044 56.4741 29.0212 56.4971 M28.9352 56.4971 L29.0212 56.4971",viewW:110,viewH:110}},{id:"toilet",group:"sanitary",art:{d:"M64.5372 72.1021 L67.6892 84.7575 C67.847 85.3886 67.3696 86 66.7191 86 L37.6483 86 C37.0414 86 36.5743 85.4636 36.6578 84.8624 L38.9999 68 C40.0716 64 32.5 64.5 32 57 L32 26.5 C32 25.1193 33.1193 24 34.5 24 L45 24 C46.3807 24 47.5 25.1193 47.5 26.5 L47.5 52 M32 57 L47.5 57 M47.5 52 L76.5 52 C77.8807 52 79 53.1193 79 54.5 L79 57 M47.5 52 L47.5 57 M54.9999 71.75 C58.5528 72.6096 61.7379 72.6416 64.5372 72.1021 C73.95 70.2877 79 62.0101 79 57 M79 57 L47.5 57",viewW:110,viewH:110}},{id:"tv",group:"appliance",art:{d:"M23.5 31 L86 31 C87.3807 31 88.5 32.1193 88.5 33.5 L88.5 67.5 C88.5 68.8807 87.3807 70 86 70 L23.5 70 C22.1193 70 21 68.8807 21 67.5 L21 33.5 C21 32.1193 22.1193 31 23.5 31 M50 70 L50 78 M59.5 70 L59.5 78 M40 78 L70 78 M42.5466 45.9951 L52.5466 45.9951 M47.5466 45.9951 L47.5 56.0336 M56.75 45.5 L61.75 55.5 L66.75 45.5",viewW:110,viewH:110}},{id:"wardrobe",group:"furniture",art:{d:"M54.5 20.5 L30.5 20.5 C29.1193 20.5 28 21.6193 28 23 L28 82.5 C28 83.8807 29.1193 85 30.5 85 L54.5 85 M54.5 20.5 L54.5 85 M54.5 20.5 L78.5 20.5 C79.8807 20.5 81 21.6193 81 23 L81 82.5 C81 83.8807 79.8807 85 78.5 85 L54.5 85 M79 84.95 L79 88.5 C79 89.0523 78.5523 89.5 78 89.5 L31 89.5 C30.4477 89.5 30 89.0523 30 88.5 L30 84.95 M50.5 48 L50.5 57.5 M58.5 48 L58.5 57.5",viewW:110,viewH:110}},{id:"washer",group:"appliance",art:{d:"M81 40 C81 38.6193 79.8807 37.5 78.5 37.5 L31.5 37.5 C30.1193 37.5 29 38.6193 29 40 M35.75 31 L45.25 31 M31.5 85 L78.5 85 C79.8807 85 81 83.8807 81 82.5 L81 55.5 L81 27.5 C81 26.1193 79.8807 25 78.5 25 L31.5 25 C30.1193 25 29 26.1193 29 27.5 L29 56 L29 82.5 C29 83.8807 30.1193 85 31.5 85 Z M72 60.5 C72 69.8888 64.3888 77.5 55 77.5 C45.6112 77.5 38 69.8888 38 60.5 C38 51.1112 45.6112 43.5 55 43.5 C64.3888 43.5 72 51.1112 72 60.5 Z M66.5 60.5 C66.5 66.8513 61.3513 72 55 72 C48.6487 72 43.5 66.8513 43.5 60.5 C43.5 54.1487 48.6487 49 55 49 C61.3513 49 66.5 54.1487 66.5 60.5 Z M69.5 31 C69.5 32.1046 68.6046 33 67.5 33 C66.3954 33 65.5 32.1046 65.5 31 C65.5 29.8954 66.3954 29 67.5 29 C68.6046 29 69.5 29.8954 69.5 31 Z M77 31 C77 32.1046 76.1046 33 75 33 C73.8954 33 73 32.1046 73 31 C73 29.8954 73.8954 29 75 29 C76.1046 29 77 29.8954 77 31 Z",viewW:110,viewH:110}},{id:"work_table",group:"furniture",art:{d:"M68.5 61 L68.5 73.5 C68.5 74.3284 69.1716 75 70 75 L87 75 C87.8284 75 88.5 74.3284 88.5 73.5 L88.5 61 L88.4844 47 M26.4844 47 L26.4844 73.5 C26.4844 74.3284 25.8128 75 24.9844 75 L23.9844 75 C23.1559 75 22.4844 74.3284 22.4844 73.5 L22.4844 47 L22.4844 43 L24.866 35.5974 C25.2388 34.6346 26.165 34 27.1974 34 L83.7743 34 C84.8054 34 85.7307 34.633 86.1044 35.5939 L88.4844 43 L88.4844 47 M88.4844 47 L68.5 47 M68.5 47 L68.5 61 M68.5 47 L26.4844 47 M68.5 61 L88.5 61 M76.5 51 L80.5 51 M88.4844 43 L22.4844 43 M22.4844 47 L26.4844 47 M76.5 65 L80.5 65",viewW:110,viewH:110}}];class Id{constructor(t,e){this.host=t,this.hooks=e}place(t,e="mouse"){const i=this.host._decorImagePalette,s=this.host._curSpaceCfg;if(!i||!s)return;const o=this.hooks.decorSnap(t,e),a=fe(i.width,i.height),n=be(a.w,this.host._cellCm,this.host._gridPitch)/pt,r=be(a.h,this.host._cellCm,this.host._gridPitch)/this.host._decorH,l="di"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),h=this.hooks.geometrySnapshot();s.decor=[...this.host._decorList,{id:l,kind:"image",asset_id:i.asset_id,x:se(o[0]/pt-n/2),y:se(o[1]/this.host._decorH-r/2),w:n,h:r,opacity:1}],this.host._decorSel=l,this.host._decorTool="select",this.host._decorImagePalette=null,this.hooks.clearFurniturePreview(),this.hooks.recordGeometry(this.host._t("history.decor_add"),h),this.hooks.saveConfig(),this.host.requestUpdate()}renderPlacementPreview(){const t=this.host._furnPreviewInput,e=this.host._decorImagePalette;if(!t||!e||"decor"!==this.host._mode||"image"!==this.host._decorTool||!this.host._pointerModality.hoverEnabled)return d;const i=this.hooks.decorSnap(t.raw,"mouse"),s=fe(e.width,e.height),o=be(s.w,this.host._cellCm,this.host._gridPitch)/pt,a=be(s.h,this.host._cellCm,this.host._gridPitch)/this.host._decorH,n=this.host._display(e.url);return n?Tt`<image class="decor-image-placement-preview" href=${n}
|
||
x=${i[0]-o*pt/2} y=${i[1]-a*this.host._decorH/2}
|
||
========
|
||
@pointerdown=${dd}
|
||
@pointerup=${dd}
|
||
@pointercancel=${dd}
|
||
@click=${dd}
|
||
@dblclick=${dd}
|
||
@wheel=${dd}>
|
||
${t?.visibleLabel?p`<span class="editor-context-label">${t.visibleLabel}</span>`:d}
|
||
<div class="editor-secondary-content">${t?.content||d}</div>
|
||
</div>
|
||
</div>`}afterRender(){const t=this.host.root();this._blocked&&(this._openGroupId?this.closeGroup(!1):"palette"===this._currentModel?.kind&&this._currentModel.dismiss?.()),this._syncGlobalDismissListener();const e=t.querySelector(".editor-secondary"),s=this._renderedContext,i=e?.dataset.contextId||"";if(i&&s&&i!==s&&!window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches&&(this._contentAnimation?.cancel(),this._contentAnimation=e?.querySelector(".editor-secondary-content")?.animate([{opacity:.35,transform:"translateY(-4px)"},{opacity:1,transform:"translateY(0)"}],{duration:100,easing:"ease-out"})),this._renderedContext=i,s&&i!==s&&this._focusOwned){const s=i?e?.querySelector('[tabindex="0"], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled])'):t.querySelector(".editbar-tools");s?.focus?.(),this._focusOwned=!!i}if("palette"===this._currentModel?.kind&&this._currentModel.launcherId){const e=[...t.querySelectorAll("[data-editor-palette]")].find(t=>t.dataset.editorPalette===this._currentModel?.launcherId);e&&null!==e.offsetParent||this._currentModel.dismiss?.()}if(!this._openGroupId)return;const o=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===this._openGroupId);o&&null!==o.offsetParent||this.closeGroup(!0)}handleOutsideDismiss(t){if(hd(t,t=>t.hasAttribute("data-editor-navigation")))return"pointerdown"===t.type?this.closeForNavigation():"click"===t.type&&this._dismissPointerTarget&&this._clearDismissClick(),!1;if("click"===t.type&&this._dismissPointerTarget){return!!(t.composedPath?.()||[t.target]).includes(this._dismissPointerTarget)&&(this._clearDismissClick(),t.preventDefault(),t.stopImmediatePropagation(),!0)}const e=this._openGroupId||this._blocked||"palette"!==this._currentModel?.kind?null:this._currentModel;if("pointerdown"===t.type&&(this._openGroupId||e)){const s=hd(t,t=>t.classList.contains("editor-secondary")),i=hd(t,t=>!!t.dataset.editorGroup),o=hd(t,t=>!!t.dataset.editorPalette),a=hd(t,t=>t.classList.contains("stage"));if(!(s||i||o||"stay-open-on-canvas"===e?.dismissPolicy&&a))return t.preventDefault(),t.stopImmediatePropagation(),this._dismissPointerTarget=t.target,clearTimeout(this._dismissTimer),this._dismissTimer=window.setTimeout(()=>{this._clearDismissClick()},800),this._openGroupId?this.closeGroup(!1):e?.dismiss?.(),this._syncGlobalDismissListener(),!0}return!1}_activateGroupItem(t,e,s){if(t.id!==this._openGroupId)return;const i=t.items.find(t=>t.id===e);if(!i||i.disabled)return;const o="toggle"===i.role&&"stay-open"===i.closePolicy,a=0===s.detail;o||(this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener()),i.invoke(),!o&&a&&this.host.updateComplete().then(()=>{const e=[...this.host.root().querySelectorAll("[data-editor-group]")].find(e=>e.dataset.editorGroup===t.id&&null!==e.offsetParent);e?.focus()})}_groupKeydown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;const e=[...t.currentTarget.querySelectorAll(".editor-group-item:not([disabled])")];if(!e.length)return;t.preventDefault();const s=e.indexOf(this.host.root().activeElement),i="Home"===t.key?0:"End"===t.key?e.length-1:"ArrowLeft"===t.key?s<=0?e.length-1:s-1:(s+1)%e.length;e[i]?.focus()}_clearDismissClick(){this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}_syncGlobalDismissListener(){const t=!this._blocked&&"palette"===this._currentModel?.kind,e=!!this._openGroupId||t||!!this._dismissPointerTarget;e!==this._globalDismissListening&&(this._globalDismissListening=e,e?(window.addEventListener("pointerdown",this._globalDismissGuard,!0),window.addEventListener("click",this._globalDismissGuard,!0)):(window.removeEventListener("pointerdown",this._globalDismissGuard,!0),window.removeEventListener("click",this._globalDismissGuard,!0)))}}const dd=t=>t.stopPropagation(),pd=new WeakSet,ud=t=>{t._regSignature="",t._maybeRebuildDevices(),t.requestUpdate()};async function _d(t,e,s,i,o,a=""){const n=t.host,r=n._serverCfg;if(!r)return!1;let l=JSON.parse(JSON.stringify(r));l.markers=l.markers||[];let h=l.markers.find(t=>t.id===e);if(!h){const t=n._devices.find(t=>t.id===e);if(!t||"device"!==t.bindingKind&&"entity"!==t.bindingKind||!t.bindingRef)return!1;h={id:t.id,binding:`${t.bindingKind}:${t.bindingRef}`,space:t.space||null,area:t.area||null,hidden:!!t.hidden},l.markers.push(h)}h.vacuum=function(t,e){const s=e.matrix.map(t=>Number(t.toFixed(6))),i=t?.map_routes;if(Array.isArray(i)&&i.length){const o=i.find(t=>t.id===e.routeId)||i.find(t=>t.source===e.source&&t.map_id===e.mapId);if(o)return{...t,map_routes:ma(i,o.id,s)}}return{...t,source:e.source,calibration:{...t?.calibration||{},[e.mapId]:s}}}(h.vacuum||{},{source:s,mapId:i,routeId:a,matrix:o}),l=t._prepareConfigCandidate(l);const c=n._adoption.beginOptimistic(r,l);n._adoption.stageLocalConfig(l),ud(n),n._saveConfigDebounced.pending()&&n._saveConfigDebounced.cancel();try{return await t._saveConfigNow(c),!0}catch(t){return n._rollbackOptimistic(c),ud(n),n._showToast(n._t("toast.cfg_save_failed",{err:n._errText(t)})),!1}}function md(t){return 1===t}function gd(t){return`${t}-${globalThis.crypto?.randomUUID?.()??`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}`}function fd(t){const e=function(t){return JSON.stringify({message:t.message.trim(),contact:t.contact.trim(),previewToken:t.attach&&t.preview?t.preview.token:""})}(t);return{idempotencyKey:t.submissionFingerprint&&t.submissionFingerprint!==e?gd("report"):t.idempotencyKey,fingerprint:e}}function bd(t){return[...t].length}function vd(t,e=Date.now()){const s=t.message.trim();return s?bd(s)>1e4?"message_too_long":bd(t.contact.trim())>320?"contact_too_long":t.attach&&!t.preview?"preview_missing":t.attach&&t.preview.expiresAt<=e?"preview_expired":null:"message_required"}function yd(t,e=Date.now()){return"building"!==t.status&&"sending"!==t.status&&"success"!==t.status&&null===vd(t,e)}function wd(t){const e=function(t){const e=/Firefox\/(\d+)/i.exec(t);if(e)return{family:"firefox",major:Number(e[1])||0};const s=/(?:Chrome|Chromium|Edg)\/(\d+)/i.exec(t);if(s)return{family:"chromium",major:Number(s[1])||0};const i=/Version\/(\d+).+Safari\//i.exec(t);return i?{family:"webkit",major:Number(i[1])||0}:{family:"unknown",major:0}}(t.userAgent??globalThis.navigator?.userAgent??""),s=t.now??Date.now(),i=Number(t.registryLastSuccess||0),o=i<=0?"unknown":s-i<=6e5?"fresh":"stale",a=["en","ru","de","fr"].includes(t.language)?t.language:"en",n=globalThis.matchMedia?.bind(globalThis);return{browser_family:e.family,browser_major:Math.max(0,Math.min(999,e.major)),language:a,coarse_pointer:t.coarsePointer??!!n?.("(pointer: coarse)").matches,hover_capable:t.hoverCapable??!!n?.("(hover: hover)").matches,registry_access:"full"===t.registryAccess?"full":"limited"===t.registryAccess?"partial":"unavailable",registry_age_bucket:o}}function $d(t){const e=t&&"object"==typeof t&&"code"in t?String(t.code||""):"";return new Set(["support_invalid_message","support_preview_expired","support_package_too_large","support_rate_limited","support_unavailable","support_rejected","unauthorized"]).has(e)?e:"support_unavailable"}const kd=[{id:"air_conditioner",group:"appliance",art:{d:"M85 71.5 L85 63 M25 71.5 L25 63 M25 71.5 L89.5 71.5 C90.8807 71.5 92 70.3807 92 69 L92 41.5 C92 40.1193 90.8807 39 89.5 39 L20.5 39 C19.1193 39 18 40.1193 18 41.5 L18 69 C18 70.3807 19.1193 71.5 20.5 71.5 L25 71.5 Z M85 63 C85 61.6193 83.8807 60.5 82.5 60.5 L27.5 60.5 C26.1193 60.5 25 61.6193 25 63 M85 63 L85 66.5 L25 66.5 L25 63",viewW:110,viewH:110}},{id:"armchair",group:"furniture",art:{d:"M77.5 48.5 L77.5 39 C77.5 33.4772 73.0228 29 67.5 29 L42.5 29 C36.9772 29 32.5 33.4772 32.5 39 L32.5 48.5205 M77.5 48.5 C80.8137 48.5 83.5 51.1863 83.5 54.5 C83.5 57.1123 81.8302 59.3334 79.5 60.1572 L79.5 71.5 C79.5 73.7091 77.7091 75.5 75.5 75.5 M77.5 48.5 C74.2576 48.5 71.617 51.072 71.5049 54.2871 C71.5012 54.3576 71.5 54.4286 71.5 54.5 L71.5 61.75 M38 61.75 L38 54 C38 53.2396 37.7873 52.5291 37.4189 51.9238 C36.5228 50.0421 34.6765 48.7002 32.5 48.5205 M32.5 48.5205 C32.3351 48.5069 32.1684 48.5 32 48.5 M75.5 75.5 L34 75.5 M75.5 75.5 L72.5 75.5 M34 75.5 C31.7909 75.5 30 73.7091 30 71.5 L30 60.1572 C27.6698 59.3334 26 57.1123 26 54.5 C26 51.1863 28.6863 48.5 32 48.5 M34 75.5 L36.5 75.5 M32 48.5 C34.3914 48.5 36.4549 49.8996 37.4189 51.9238 M38 61.75 C38 64.3734 40.1266 66.5 42.75 66.5 L66.75 66.5 C69.3734 66.5 71.5 64.3734 71.5 61.75 M38 61.75 C38 59.1266 40.1266 57 42.75 57 L66.75 57 C69.3734 57 71.5 59.1266 71.5 61.75 M36.5 75.5 L44.5 75.5 M36.5 75.5 L36.5 80.5 C36.5 81.3284 37.1716 82 38 82 L41.3921 82 C42.0506 82 42.6321 81.5705 42.8258 80.9411 L44.5 75.5 M44.5 75.5 L64.5 75.5 M72.5 75.5 L64.5 75.5 M72.5 75.5 L72.5 80.5 C72.5 81.3284 71.8284 82 71 82 L67.6079 82 C66.9494 82 66.3679 81.5705 66.1742 80.9411 L64.5 75.5",viewW:110,viewH:110}},{id:"bathtub",group:"sanitary",art:{d:"M28 74.8457 L28 80 C28 80.8284 28.6716 81.5 29.5 81.5 L32.8921 81.5 C33.5506 81.5 34.1321 81.0705 34.3258 80.4411 L35.6923 76 M28.0191 74.8558 C28.0127 74.8524 28.0063 74.8491 28 74.8457 C25.4198 73.4833 23.483 71.0169 22.8673 67.9996 M19.5 51.5 L90 51.5 M19.5 51.5 C18.1193 51.5 17 50.3807 17 49 C17 47.6193 18.1193 46.5 19.5 46.5 M19.5 51.5 L22.8673 67.9996 M90 51.5 C91.3807 51.5 92.5 50.3807 92.5 49 C92.5 47.6193 91.3807 46.5 90 46.5 M90 51.5 L86.6327 67.9996 C85.9778 71.2088 83.8285 73.7948 81 75.0922 M90 46.5 L19.5 46.5 M90 46.5 L20 46.5 M19.5 46.5 L20 46.5 M22.8673 67.9996 C23.4846 71.0243 25.4293 73.4954 28.0191 74.8558 M30 36 L30 34 C30 32.6739 29.4732 31.4021 28.5355 30.4645 C27.5979 29.5268 26.3261 29 25 29 C23.6739 29 22.4021 29.5268 21.4645 30.4645 C20.5268 31.4021 20 32.6739 20 34 L20 46.5 M81 75.0922 C79.7247 75.6771 78.3114 76 76.8347 76 L73.3077 76 M81 75.0922 L81 80 C81 80.8284 80.3284 81.5 79.5 81.5 L76.1079 81.5 C75.4494 81.5 74.8679 81.0705 74.6742 80.4411 L73.3077 76 M73.3077 76 L35.6923 76 M35.6923 76 L32.6653 76 C31.1128 76 29.6303 75.643 28.3047 75 C28.2086 74.9534 28.1134 74.9053 28.0191 74.8558",viewW:110,viewH:110}},{id:"bed",group:"furniture",art:{d:"M16 75.5 L24 75.5 M16 75.5 L16 80.5 C16 81.3284 16.6716 82 17.5 82 L20.8921 82 C21.5506 82 22.1321 81.5705 22.3258 80.9411 L24 75.5 M16 75.5 L15 75.5 M24 75.5 L86.5 75.5 M94.5 75.5 L86.5 75.5 M94.5 75.5 L94.5 80.5 C94.5 81.3284 93.8284 82 93 82 L89.6079 82 C88.9494 82 88.3679 81.5705 88.1742 80.9411 L86.5 75.5 M94.5 75.5 L95.5 75.5 M88 50.1296 L88 31.5 C88 30.1193 86.8807 29 85.5 29 L25 29 C23.6193 29 22.5 30.1193 22.5 31.5 L22.5 50.1296 M87.9383 50.1068 C87.9589 50.1143 87.9795 50.1219 88 50.1296 C91.7967 51.5483 94.5 55.2085 94.5 59.5 M22.5617 50.1068 C22.5411 50.1143 22.5205 50.1219 22.5 50.1296 C18.7033 51.5483 16 55.2085 16 59.5 M94.5 65.5 L94.5 59.5 M94.5 65.5 L16 65.5 M94.5 65.5 L95.5 65.5 M16 65.5 L16 59.5 M16 65.5 L15 65.5 M84.5 49.5 L26 49.5 M84.5 49.5 L80 49.5 M94.5 59.5 C94.5 55.1853 91.7674 51.5088 87.9383 50.1068 C86.8662 49.7142 85.7081 49.5 84.5 49.5 M26 49.5 L30.5 49.5 M16 59.5 C16 55.1853 18.7326 51.5088 22.5617 50.1068 C23.6338 49.7142 24.7919 49.5 26 49.5 M15 75.5 L95.5 75.5 M15 75.5 C14.4477 75.5 14 75.0523 14 74.5 L14 66.5 C14 65.9477 14.4477 65.5 15 65.5 M95.5 75.5 C96.0523 75.5 96.5 75.0523 96.5 74.5 L96.5 66.5 C96.5 65.9477 96.0523 65.5 95.5 65.5 M95.5 65.5 L15 65.5 M51.5 49.5 L51.5 45.5 C51.5 42.7386 49.2614 40.5 46.5 40.5 L35.5 40.5 C32.7386 40.5 30.5 42.7386 30.5 45.5 L30.5 49.5 M51.5 49.5 L30.5 49.5 M51.5 49.5 L59 49.5 M80 49.5 L80 45.5 C80 42.7386 77.7614 40.5 75 40.5 L64 40.5 C61.2386 40.5 59 42.7386 59 45.5 L59 49.5 M80 49.5 L59 49.5",viewW:110,viewH:110}},{id:"bidet",group:"sanitary",art:{d:"M46 67.5 L64.5 67.5 M46 67.5 C40.4772 67.5 36 63.0228 36 57.5 L36 53 M46 67.5 C45.4902 67.5 44.9893 67.4618 44.5 67.3882 L44.5 79.5 C44.5 80.0523 44.9477 80.5 45.5 80.5 L65 80.5 C65.5523 80.5 66 80.0523 66 79.5 L66 67.3882 C65.5107 67.4618 65.0098 67.5 64.5 67.5 M64.5 67.5 C70.0229 67.5 74.5 63.0228 74.5 57.5 L74.5 53 M74.5 53 L74.5 47.5 C74.5 46.9477 74.0523 46.5 73.5 46.5 M74.5 53 L36 53 M36 53 L36 47.5 C36 46.9477 36.4477 46.5 37 46.5 M73.5 46.5 L37 46.5 M73.5 46.5 L60 46.5 M37 46.5 L50.5 46.5 M51.5 40 L59 40 M51.5 40 C50.9477 40 50.5 40.4477 50.5 41 L50.5 46.5 M51.5 40 L53 40 M59 40 C59.5523 40 60 40.4477 60 41 L60 46.5 M59 40 L57.5 40 M60 46.5 L50.5 46.5 M57.5 40 L57.5 30 C57.5 29.4477 57.0523 29 56.5 29 L54 29 C53.4477 29 53 29.4477 53 30 M57.5 40 L53 40 M53 40 L53 30 M53 40 L53 36 M53 30 L53 31.5 M53 31.5 L49 31.5 C48.4477 31.5 48 31.9477 48 32.5 L48 35 C48 35.5523 48.4477 36 49 36 L53 36 M53 31.5 L53 36",viewW:110,viewH:110}},{id:"boiler",group:"appliance",art:{d:"M51.5 81.5 L51.5 86 C51.5 86.5523 51.0523 87 50.5 87 L47.5 87 C46.9477 87 46.5 86.5523 46.5 86 L46.5 81.5 M51.5 81.5 L46.5 81.5 M51.5 81.5 L59 81.5 M46.5 81.5 L44 81.5 M64 81.5 L64 86 C64 86.5523 63.5523 87 63 87 L60 87 C59.4477 87 59 86.5523 59 86 L59 81.5 M64 81.5 L59 81.5 M64 81.5 L66.5 81.5 M74.5 73 L74.5 73.5 C74.5 77.9183 70.9183 81.5 66.5 81.5 M44 81.5 C39.5817 81.5 36 77.9183 36 73.5 L36 73 L36 31 C36 26.5817 39.5817 23 44 23 L66.5 23 C70.9183 23 74.5 26.5817 74.5 31 L74.5 73 M74.5 73 L36 73 M66.5 81.5 L44 81.5 M55 42.5 L58.5 39 M62.5 42.5 C62.5 46.366 59.366 49.5 55.5 49.5 C51.634 49.5 48.5 46.366 48.5 42.5 C48.5 38.634 51.634 35.5 55.5 35.5 C59.366 35.5 62.5 38.634 62.5 42.5 Z",viewW:110,viewH:110}},{id:"chair",group:"furniture",art:{d:"M41.25 60.5 L68.75 60.5 M68.75 60.5 C70.5449 60.5 72 59.0449 72 57.25 C72 55.6281 70.8119 54.2836 69.2585 54.0395 C69.0928 54.0135 68.923 54 68.75 54 L41.25 54 C41.077 54 40.9072 54.0135 40.7415 54.0395 C39.1881 54.2836 38 55.6281 38 57.25 C38 59.0449 39.4551 60.5 41.25 60.5 M41.25 60.5 L46 60.5 M68.75 60.5 L64 60.5 M64 60.5 L69.5 60.5 L69.5 82 C69.5 82.8284 68.8284 83.5 68 83.5 L67.3752 83.5 C66.5972 83.5 65.9483 82.9051 65.8809 82.1299 L64 60.5 Z M64 60.5 L46 60.5 M46 60.5 L40.5 60.5 L40.5 82 C40.5 82.8284 41.1716 83.5 42 83.5 L42.6248 83.5 C43.4028 83.5 44.0517 82.9051 44.1191 82.1299 L46 60.5 Z M40.7415 54.0395 C40.5847 53.5546 40.5 53.0372 40.5 52.5 L40.5 39.5 C40.5 32.5964 46.0964 27 53 27 L57 27 C63.9036 27 69.5 32.5964 69.5 39.5 L69.5 52.5 C69.5 53.0372 69.4153 53.5546 69.2585 54.0395",viewW:110,viewH:110}},{id:"coffee_table",group:"furniture",art:{d:"M85.2381 55 L86.5 55 C87.0523 55 87.5 54.5523 87.5 54 L87.5 51 L84.6598 43.4847 C84.2586 42.5818 83.3633 42 82.3753 42 L26.6247 42 C25.6367 42 24.7414 42.5818 24.3402 43.4847 L21.5 51 L21.5 54 C21.5 54.5523 21.9477 55 22.5 55 L25 55 M87.5 51 L21.5 51 M25 55 L25 66.5 C25 67.3284 25.6716 68 26.5 68 L27.2113 68 C27.983 68 28.6288 67.4144 28.7041 66.6464 L29.8459 55 M25 55 L29.8459 55 M29.8459 55 L80.3922 55 M80.3922 55 L81.534 66.6464 C81.6093 67.4144 82.2551 68 83.0268 68 L83.7381 68 C84.5665 68 85.2381 67.3284 85.2381 66.5 L85.2381 55 M80.3922 55 L85.2381 55",viewW:110,viewH:110}},{id:"computer",group:"appliance",art:{d:"M43 65 L48 65 M43 65 L24.5 65 C23.1193 65 22 63.8807 22 62.5 L22 40.5 C22 39.1193 23.1193 38 24.5 38 L64.5 38 C65.8807 38 67 39.1193 67 40.5 L67 62.5 C67 63.8807 65.8807 65 64.5 65 L48 65 M43 65 L43 72 M48 65 L48 72 M37 72 L43 72 M54.0711 72 L48 72 M76 60 L84 60 M76 43 L84 43 M35 53 L35 46 L39.5 46 C40.4283 46 41.3185 46.3687 41.9749 47.0251 C42.6313 47.6815 43 48.5717 43 49.5 C43 50.4283 42.6312 51.3185 41.9749 51.9749 C41.3185 52.6313 40.4283 53 39.5 53 L35 53 Z M35 53 L35 56 M54.5355 54.5355 C53.8363 55.2348 52.9454 55.711 51.9755 55.9039 C51.0055 56.0969 50.0002 55.9978 49.0866 55.6194 C48.173 55.241 47.3921 54.6001 46.8427 53.7779 C46.2932 52.9556 46 51.9889 46 51 C46 50.0111 46.2932 49.0444 46.8427 48.2221 C47.3921 47.3999 48.173 46.759 49.0866 46.3806 C50.0002 46.0022 51.0055 45.9031 51.9755 46.0961 C52.9454 46.289 53.8363 46.7652 54.5355 47.4645 M48 72 L43 72 M74.5 72 L85.5 72 C86.8807 72 88 70.8807 88 69.5 L88 40.5 C88 39.1193 86.8807 38 85.5 38 L74.5 38 C73.1193 38 72 39.1193 72 40.5 L72 69.5 C72 70.8807 73.1193 72 74.5 72 Z",viewW:110,viewH:110}},{id:"cooktop",group:"appliance",art:{d:"M25 31.5 C25 30.1193 26.1193 29 27.5 29 L82.5 29 C83.8807 29 85 30.1193 85 31.5 L85 78.5 C85 79.8807 83.8807 81 82.5 81 L27.5 81 C26.1193 81 25 79.8807 25 78.5 L25 31.5 Z M49.5 66.5 C49.5 70.9183 45.9183 74.5 41.5 74.5 C37.0817 74.5 33.5 70.9183 33.5 66.5 C33.5 62.0817 37.0817 58.5 41.5 58.5 C45.9183 58.5 49.5 62.0817 49.5 66.5 Z M76 43.5 C76 47.9183 72.4183 51.5 68 51.5 C63.5817 51.5 60 47.9183 60 43.5 C60 39.0817 63.5817 35.5 68 35.5 C72.4183 35.5 76 39.0817 76 43.5 Z M73 66.5 C73 69.2614 70.7614 71.5 68 71.5 C65.2386 71.5 63 69.2614 63 66.5 C63 63.7386 65.2386 61.5 68 61.5 C70.7614 61.5 73 63.7386 73 66.5 Z M49.5 43.5 C49.5 47.9183 45.9183 51.5 41.5 51.5 C37.0817 51.5 33.5 47.9183 33.5 43.5 C33.5 39.0817 37.0817 35.5 41.5 35.5 C45.9183 35.5 49.5 39.0817 49.5 43.5 Z",viewW:110,viewH:110}},{id:"dining_table",group:"furniture",art:{d:"M26.875 47 L23.5 47 C22.9477 47 22.5 46.5523 22.5 46 L22.5 43 L24.8802 35.5939 C25.2539 34.633 26.1791 34 27.2102 34 L83.7898 34 C84.8209 34 85.7462 34.633 86.1198 35.5939 L88.5 43 L88.5 46 C88.5 46.5523 88.0523 47 87.5 47 L84.125 47 M22.5 43 L88.5 43 M78.875 47 L84.742 73.8205 C84.8926 74.5092 85.5024 75 86.2073 75 L86.7474 75 C87.6682 75 88.3716 74.1781 88.2294 73.2684 L84.125 47 M78.875 47 L84.125 47 M78.875 47 L32.125 47 M32.125 47 L26.258 73.8205 C26.1074 74.5092 25.4976 75 24.7927 75 L24.2526 75 C23.3318 75 22.6284 74.1781 22.7706 73.2684 L26.875 47 M32.125 47 L26.875 47",viewW:110,viewH:110}},{id:"dishwasher",group:"appliance",art:{d:"M29 76C29 77.3807 30.1193 78.5 31.5 78.5H78.5C79.8807 78.5 81 77.3807 81 76M29 76V82.5C29 83.8807 30.1193 85 31.5 85H78.5C79.8807 85 81 83.8807 81 82.5V76M29 76V40M81 76V40M81 40C81 38.6193 79.8807 37.5 78.5 37.5H31.5C30.1193 37.5 29 38.6193 29 40M81 40V27.5C81 26.1193 79.8807 25 78.5 25H31.5C30.1193 25 29 26.1193 29 27.5V40M43 42H67M35.75 31H45.25M69.5 31C69.5 32.1046 68.6046 33 67.5 33C66.3954 33 65.5 32.1046 65.5 31C65.5 29.8954 66.3954 29 67.5 29C68.6046 29 69.5 29.8954 69.5 31ZM77 31C77 32.1046 76.1046 33 75 33C73.8954 33 73 32.1046 73 31C73 29.8954 73.8954 29 75 29C76.1046 29 77 29.8954 77 31Z",viewW:110,viewH:110}},{id:"dryer",group:"appliance",art:{d:"M81 82.5 L81 27.5 M81 82.5 C81 83.8807 79.8807 85 78.5 85 L31.5 85 C30.1193 85 29 83.8807 29 82.5 L29 55.5 M81 82.5 L81 40 M81 27.5 C81 26.1193 79.8807 25 78.5 25 L31.5 25 C30.1193 25 29 26.1193 29 27.5 M81 27.5 L81 40 M29 27.5 L29 55.5 M29 27.5 L29 40 M81 40 C81 38.6193 79.8807 37.5 78.5 37.5 L31.5 37.5 C30.1193 37.5 29 38.6193 29 40 M29 40 L29 55.5 M35.75 31 L45.25 31 M55.9943 55 C55.9943 55 54.6654 56.8105 54.5153 58.1429 C54.3169 59.9042 56.1139 60.6968 55.9943 62.4643 C55.8942 63.9429 54.5153 66 54.5153 66 M60.4943 55 C60.4943 55 59.1654 56.8105 59.0153 58.1429 C58.8169 59.9042 60.6139 60.6968 60.4943 62.4643 C60.3942 63.9429 59.0153 66 59.0153 66 M50.9943 55 C50.9943 55 49.6654 56.8105 49.5153 58.1429 C49.3169 59.9042 51.1139 60.6968 50.9943 62.4643 C50.8942 63.9429 49.5153 66 49.5153 66 M72 60.5 C72 69.8888 64.3888 77.5 55 77.5 C45.6112 77.5 38 69.8888 38 60.5 C38 51.1112 45.6112 43.5 55 43.5 C64.3888 43.5 72 51.1112 72 60.5 Z M66.5 60.5 C66.5 66.8513 61.3513 72 55 72 C48.6487 72 43.5 66.8513 43.5 60.5 C43.5 54.1487 48.6487 49 55 49 C61.3513 49 66.5 54.1487 66.5 60.5 Z M69.5 31 C69.5 32.1046 68.6046 33 67.5 33 C66.3954 33 65.5 32.1046 65.5 31 C65.5 29.8954 66.3954 29 67.5 29 C68.6046 29 69.5 29.8954 69.5 31 Z M77 31 C77 32.1046 76.1046 33 75 33 C73.8954 33 73 32.1046 73 31 C73 29.8954 73.8954 29 75 29 C76.1046 29 77 29.8954 77 31 Z",viewW:110,viewH:110}},{id:"exercise",group:"other",art:{d:"M55.091 60.072 L65.7741 35.5156 M42.2119 56.2083 L55.091 60.072 L60.8511 61.8001 L66.5032 63.4957 C70.733 64.7646 73.6297 68.6579 73.6297 73.074 L73.6297 76.2635 L29.3385 76.2635 L29.3385 65.7866 C29.3385 60.9371 32.7227 57.0804 37.0256 56.051 C38.5108 55.6956 40.1055 55.6771 41.7081 56.0709 M41.7081 56.0709 C41.876 56.1122 42.044 56.1579 42.2119 56.2083 L60.8511 61.8001 M71.9311 35.5156 L76.4108 35.5156 C78.2451 35.5156 79.9321 34.5112 80.8064 32.8987 L83.8375 27.308 C84.3011 26.4529 83.9993 25.384 83.1569 24.8976 C82.2982 24.4018 81.2002 24.696 80.7045 25.5547 L77.8652 30.4723 C77.3293 31.4005 76.3389 31.9723 75.2671 31.9723 L65.6573 31.9723 C64.6788 31.9723 63.8856 32.7655 63.8856 33.744 C63.8856 34.7224 64.6788 35.5156 65.6573 35.5156 L65.7741 35.5156 M71.9311 35.5156 C71.9603 35.7673 71.9261 36.0298 71.8188 36.2793 L60.8511 61.8001 M71.9311 35.5156 L65.7741 35.5156 M41.7081 56.0709 L38.03 42.6022 M37.0256 56.051 L33.3529 42.6022 M38.03 42.6022 L33.3529 42.6022 L29.7814 42.6022 C28.5583 42.6022 27.5668 41.6107 27.5668 40.3876 C27.5668 39.1646 28.5583 38.1731 29.7814 38.1731 L41.2971 38.1731 C42.5202 38.1731 43.5117 39.1646 43.5117 40.3876 C43.5117 41.6107 42.5202 42.6022 41.2971 42.6022 L38.03 42.6022 Z M25.7952 78.921 C25.7952 77.4533 26.985 76.2635 28.4526 76.2635 L74.5155 76.2636 C75.9832 76.2636 77.173 77.4533 77.173 78.921 C77.173 80.3887 75.9832 81.5785 74.5155 81.5785 L28.4526 81.5785 C26.985 81.5785 25.7952 80.3887 25.7952 78.921 Z M29.3385 81.5785 L29.3385 84.5677 C29.3385 85.3962 30.01 86.0677 30.8385 86.0677 L33.6379 86.0677 C34.2512 86.0677 34.8028 85.6943 35.0306 85.1248 L36.5002 81.5785 L29.3385 81.5785 Z M73.6297 81.5785 L73.6297 84.5677 C73.6297 85.3962 72.9581 86.0677 72.1297 86.0677 L69.3303 86.0677 C68.717 86.0677 68.1654 85.6943 67.9376 85.1248 L66.5002 81.5785 L73.6297 81.5785 Z M45.2833 66.0766 C45.2833 68.7673 43.102 70.9486 40.4113 70.9486 C37.7205 70.9486 35.5392 68.7673 35.5392 66.0766 C35.5392 63.3858 37.7205 61.2045 40.4113 61.2045 C43.102 61.2045 45.2833 63.3858 45.2833 66.0766 Z",viewW:110,viewH:110}},{id:"fireplace",group:"other",art:{d:"M71.1884 73.8943 L71.1884 50.4399 C71.1884 47.6784 68.9498 45.4399 66.1884 45.4399 L43.1445 45.4399 C40.3831 45.4399 38.1445 47.6784 38.1445 50.4399 L38.1445 73.8942 M38.1445 73.8942 L26.7031 73.8942 L26.7031 34.4252 L82.6629 34.4252 L82.6629 73.8942 L71.1884 73.8943 L38.1445 73.8942 Z M62.0101 62.8795 L47.3239 62.8795 C45.8031 62.8795 44.5703 64.1124 44.5703 65.6332 C44.5703 67.154 45.8031 68.3868 47.3239 68.3868 M47.3239 68.3868 C45.8031 68.3868 44.5703 69.6195 44.5703 71.1403 C44.5703 72.6611 45.8031 73.894 47.3239 73.894 M47.3239 68.3868 C48.8447 68.3868 50.0776 69.6195 50.0776 71.1403 C50.0776 72.6611 48.8447 73.894 47.3239 73.894 M47.3239 68.3868 L61.9918 68.3868 M47.3239 73.894 L62.0101 73.894 C63.5309 73.894 64.7637 72.6611 64.7637 71.1403 C64.7637 69.6242 63.5385 68.3945 62.0243 68.3869 M62.0114 68.3869 C62.0049 68.3869 61.9983 68.3869 61.9918 68.3868 M62.0114 68.3869 C62.0157 68.3869 62.02 68.3869 62.0243 68.3869 M62.0114 68.3869 L62.0243 68.3869 M62.0114 68.3869 L61.9918 68.3868 M61.9918 68.3868 C60.48 68.3763 59.2578 67.1475 59.2578 65.6332 C59.2578 64.1124 60.4906 62.8796 62.0114 62.8796 C63.5322 62.8796 64.7651 64.1124 64.7651 65.6332 C64.7651 67.1498 63.5392 68.3799 62.0243 68.3869 M61.9918 68.3868 L62.0101 68.3868 C62.0148 68.3868 62.0195 68.3868 62.0243 68.3869 M24 81.6962 L85.3341 81.6962 C85.8864 81.6962 86.3341 81.2485 86.3341 80.6962 L86.3341 74.8942 C86.3341 74.3419 85.8864 73.8942 85.3341 73.8942 L24 73.8942 C23.4477 73.8942 23 74.3419 23 74.8942 L23 80.6962 C23 81.2485 23.4477 81.6962 24 81.6962 Z M24 34.4252 L85.3341 34.4252 C85.8864 34.4252 86.3341 33.9775 86.3341 33.4252 L86.3341 29 C86.3341 28.4477 85.8864 28 85.3341 28 L24 28 C23.4477 28 23 28.4477 23 29 L23 33.4252 C23 33.9775 23.4477 34.4252 24 34.4252 Z",viewW:110,viewH:110}},{id:"fridge",group:"appliance",art:{d:"M35.5 87 C34.1193 87 33 85.8807 33 84.5 M35.5 87 L74.5 87 M35.5 87 L35.5 90.5 C35.5 91.0523 35.9477 91.5 36.5 91.5 L73.5 91.5 C74.0523 91.5 74.5 91.0523 74.5 90.5 L74.5 87 M33 84.5 L33 20.5 M33 84.5 L33 46.5 M77.5 84.5 L77.5 20.5 M77.5 84.5 C77.5 85.8807 76.3807 87 75 87 L74.5 87 M77.5 84.5 L77.5 46.5 M77.5 20.5 C77.5 19.1193 76.3807 18 75 18 L35.5 18 C34.1193 18 33 19.1193 33 20.5 M77.5 20.5 L77.5 46.5 M33 20.5 L33 46.5 M33 46.5 L77.5 46.5 M38.5 41 L38.5 31.5 M38.5 62 L38.5 52.5",viewW:110,viewH:110}},{id:"hood",group:"appliance",art:{d:"M66 57 L83 69 L83 71.5 C83 72.8807 81.8807 74 80.5 74 L29.5 74 C28.1193 74 27 72.8807 27 71.5 L27 69 L44 57 M44 57 L66 57 M44 57 L44 37.5 C44 36.1193 45.1193 35 46.5 35 L63.5 35 C64.8807 35 66 36.1193 66 37.5 L66 57 M83 69 L27 69",viewW:110,viewH:110}},{id:"kitchen_cabinet",group:"furniture",art:{d:"M72 84.95 L72 88 C72 88.5523 71.5523 89 71 89 L39 89 C38.4477 89 38 88.5523 38 88 L38 84.95 M55 20 L71.5 20 C72.8807 20 74 21.1193 74 22.5 L74 39.5 C74 40.8807 72.8807 42 71.5 42 L55 42 M55 20 L55 42 M55 20 L38.5 20 C37.1193 20 36 21.1193 36 22.5 L36 39.5 C36 40.8807 37.1193 42 38.5 42 L55 42 M59 33 L59 38 M51 33 L51 38 M55 85 L71.5 85 C72.8807 85 74 83.8807 74 82.5 L74 65.5 C74 64.1193 72.8807 63 71.5 63 L55 63 M55 85 L55 63 M55 85 L38.5 85 C37.1193 85 36 83.8807 36 82.5 L36 65.5 C36 64.1193 37.1193 63 38.5 63 L55 63 M67 67 L62 67 M48 67 L43 67",viewW:110,viewH:110}},{id:"kitchen_sink",group:"sanitary",art:{d:"M49 54 L49 59 M51.5 37.5 L44 37.5 M51.5 37.5 C52.0523 37.5 52.5 37.9477 52.5 38.5 L52.5 44 M51.5 37.5 L48 37.5 M44 37.5 C43.4477 37.5 43 37.9477 43 38.5 L43 44 M44 37.5 L48 37.5 M43 44 L21.5 44 C20.1193 44 19 45.1193 19 46.5 L19 81.5 C19 82.8807 20.1193 84 21.5 84 L89.5 84 C90.8807 84 92 82.8807 92 81.5 L92 46.5 C92 45.1193 90.8807 44 89.5 44 L52.5 44 M43 44 L52.5 44 M58 33 L58 31 C58 29.6739 57.4732 28.4021 56.5355 27.4645 C55.5979 26.5268 54.3261 26 53 26 C51.6739 26 50.4021 26.5268 49.4645 27.4645 C48.5268 28.4021 48 29.6739 48 31 L48 37.5 M62 54 L62 59 M26 50 L52.5 50 C53.0523 50 53.5 50.4477 53.5 51 L53.5 77 C53.5 77.5523 53.0523 78 52.5 78 L26 78 C25.4477 78 25 77.5523 25 77 L25 51 C25 50.4477 25.4477 50 26 50 Z M58.5 50 L85 50 C85.5523 50 86 50.4477 86 51 L86 77 C86 77.5523 85.5523 78 85 78 L58.5 78 C57.9477 78 57.5 77.5523 57.5 77 L57.5 51 C57.5 50.4477 57.9477 50 58.5 50 Z",viewW:110,viewH:110}},{id:"nightstand",group:"furniture",art:{d:"M34.5 76 C33.1193 76 32 74.8807 32 73.5 M34.5 76 L41.2308 76 M34.5 76 C34.3288 76 34.1616 75.9828 34 75.95 L34 78.5 C34 79.3284 34.6716 80 35.5 80 L38.8921 80 C39.5506 80 40.1321 79.5705 40.3258 78.9411 L41.2308 76 M32 73.5 L32 33 M32 73.5 L32 57.5 M78 73.5 L78 33 M69.2692 76 L75.5 76 C75.8556 76 76.1938 75.9258 76.5 75.792 C77.383 75.4062 78 74.5252 78 73.5 M78 73.5 L78 57.5 M78 33 C78 31.6193 76.8807 30.5 75.5 30.5 L34.5 30.5 C33.1193 30.5 32 31.6193 32 33 M78 33 L78 39.5 M32 33 L32 39.5 M32 39.5 L78 39.5 M32 39.5 L32 57.5 M78 39.5 L78 57.5 M78 57.5 L32 57.5 M50.5 48.5 L60 48.5 M50.5 66 L60 66 M41.2308 76 L69.2692 76 M69.2692 76 L70.1742 78.9411 C70.3679 79.5705 70.9494 80 71.6079 80 L75 80 C75.8284 80 76.5 79.3284 76.5 78.5 L76.5 75.792",viewW:110,viewH:110}},{id:"oven",group:"appliance",art:{d:"M29 76 C29 77.3807 30.1193 78.5 31.5 78.5 L78.5 78.5 C79.8807 78.5 81 77.3807 81 76 M29 76 L29 40 M29 76 L29 82.5 C29 83.8807 30.1193 85 31.5 85 L78.5 85 C79.8807 85 81 83.8807 81 82.5 L81 76 M81 76 L81 40 M81 40 C81 38.6193 79.8807 37.5 78.5 37.5 L31.5 37.5 C30.1193 37.5 29 38.6193 29 40 M81 40 L81 27.5 C81 26.1193 79.8807 25 78.5 25 L31.5 25 C30.1193 25 29 26.1193 29 27.5 L29 40 M35.75 31 L45.25 31 M43 42 L67 42 M40.5 72 L69.5 72 C70.8807 72 72 70.8807 72 69.5 L72 49.5 C72 48.1193 70.8807 47 69.5 47 L40.5 47 C39.1193 47 38 48.1193 38 49.5 L38 69.5 C38 70.8807 39.1193 72 40.5 72 Z M69.5 31 C69.5 32.1046 68.6046 33 67.5 33 C66.3954 33 65.5 32.1046 65.5 31 C65.5 29.8954 66.3954 29 67.5 29 C68.6046 29 69.5 29.8954 69.5 31 Z M77 31 C77 32.1046 76.1046 33 75 33 C73.8954 33 73 32.1046 73 31 C73 29.8954 73.8954 29 75 29 C76.1046 29 77 29.8954 77 31 Z",viewW:110,viewH:110}},{id:"plant",group:"other",art:{d:"M55.7064 55.8805 L55.7064 52.9357 M55.7064 52.9357 C56.839 47.0461 62.7965 41.9801 68.6182 37.5322 M55.7064 52.9357 C50.7678 48.7899 47.7236 46.7763 41.6621 43.8748 M67.4992 61.3174 L65.9151 75.8488 C65.7779 77.1181 64.7063 78.0801 63.4296 78.0801 L48.4373 78.0801 C47.1606 78.0801 46.089 77.1181 45.9518 75.8488 L44.3593 61.3174 L67.4992 61.3174 Z M60.2363 44.7807 C58.4234 36.1732 66.8047 29.604 76.9989 31.869 C76.9989 40.024 68.3904 48.6318 60.2363 44.7807 Z M50.476 49.9288 C51.9926 41.2641 43.391 34.9863 33.2805 37.5996 C33.5602 45.7498 42.4589 54.0573 50.476 49.9288 Z M43.1152 61.3174 L68.7509 61.3174 C69.3031 61.3174 69.7509 60.8697 69.7509 60.3174 L69.7509 56.8809 C69.7509 56.3286 69.3031 55.8809 68.7509 55.8809 L43.1152 55.8809 C42.5629 55.8809 42.1152 56.3286 42.1152 56.8809 L42.1152 60.3174 C42.1152 60.8697 42.5629 61.3174 43.1152 61.3174 Z",viewW:110,viewH:110}},{id:"rug",group:"other",art:{d:"M90.2693 33.8735 L84.648 33.8735 M25.6208 33.8735 L19.9995 33.8735 M90.2693 39.0264 L84.648 39.0264 M25.6208 39.0264 L19.9995 39.0264 M90.2693 44.1792 L84.648 44.1792 M25.6208 44.1792 L19.9995 44.1792 M90.2693 49.332 L84.648 49.332 M25.6208 49.332 L19.9995 49.332 M90.2693 54.4854 L84.648 54.4854 M25.6208 54.4854 L19.9995 54.4854 M90.2693 59.6382 L84.648 59.6382 M25.6208 59.6382 L19.9995 59.6382 M90.2693 64.791 L84.648 64.791 M25.6208 64.791 L19.9995 64.791 M90.2693 69.9438 L84.648 69.9438 M25.6208 69.9438 L19.9995 69.9438 M90.2693 75.0967 L84.648 75.0967 M25.6208 75.0967 L19.9995 75.0967 M28.121 32 L82.145 32 C83.5257 32 84.645 33.1193 84.645 34.5 L84.645 74.939 C84.645 76.3197 83.5257 77.439 82.145 77.439 L28.121 77.439 C26.7403 77.439 25.621 76.3197 25.621 74.939 L25.621 34.5 C25.621 33.1193 26.7403 32 28.121 32 Z M29.8369 32 L29.8369 77.439 M80.4302 32 L80.4302 77.439 M37.8005 54.4852 L55.6014 46.0532 L73.4022 54.4852 L55.6014 62.9172 L37.8005 54.4852 Z",viewW:110,viewH:110}},{id:"shelving",group:"furniture",art:{d:"M64 58.5 L64 47 C64 46.4477 64.4477 46 65 46 L68 46 C68.5523 46 69 46.4477 69 47 M64 58.5 L69 58.5 M64 58.5 L28 58.5 L28 39 L35.5 39 M69 58.5 L69 47 M69 58.5 L69 44.5 M69 58.5 L76 58.5 M69 47 L69 44.5 M52.5 39 L52.5 27.5 C52.5 26.9477 52.0523 26.5 51.5 26.5 L48.5 26.5 C47.9477 26.5 47.5 26.9477 47.5 27.5 M52.5 39 L47.5 39 M52.5 39 L81 39 L81 58.5 L76 58.5 M47.5 39 L47.5 27.5 M47.5 39 L47.5 25 M47.5 39 L40.5 39 M47.5 27.5 L47.5 25 M40.5 39 L40.5 27.5 M40.5 39 L40.5 25 M40.5 39 L35.5 39 M35.5 39 L35.5 27.5 C35.5 26.9477 35.9477 26.5 36.5 26.5 L39.5 26.5 C40.0523 26.5 40.5 26.9477 40.5 27.5 M40.5 27.5 L40.5 25 M49 72 L36.5 72 M50.5 72 L36.5 72 C35.9477 72 35.5 71.5523 35.5 71 L35.5 68.5 C35.5 67.9477 35.9477 67.5 36.5 67.5 L49 67.5 C49.5523 67.5 50 67.9477 50 68.5 L50 71 C50 71.5523 49.5523 72 49 72 M50.5 78 C51.0523 78 51.5 77.5523 51.5 77 L51.5 73 C51.5 72.4477 51.0523 72 50.5 72 L49 72 M36.5 72 C35.9477 72 35.5 72.4477 35.5 73 L35.5 77 C35.5 77.5523 35.9477 78 36.5 78 M76 58.5 L76 44.5 C76 43.9477 75.5523 43.5 75 43.5 L70 43.5 C69.4477 43.5 69 43.9477 69 44.5 M47.5 25 C47.5 24.4477 47.0523 24 46.5 24 L41.5 24 C40.9477 24 40.5 24.4477 40.5 25 M50.5 78 L36.5 78 M50.5 78 L81 78 L81 85 L28 85 L28 78 L36.5 78 M28 89.5 L28 23 C28 21.6193 29.1193 20.5 30.5 20.5 L78.5 20.5 C79.8807 20.5 81 21.6193 81 23 L81 89.5",viewW:110,viewH:110}},{id:"shower",group:"sanitary",art:{d:"M39 84 L39 31.7143 C39 25.245 44.2564 20 50.75 20 C56.4663 20 61.2394 24.5462 62.1824 29.0091 M51.5 39.25 C51.5 33.5891 56.0891 29 61.75 29 C67.4109 29 72 33.5891 72 39.25 L51.5 39.25 M54.75 44.25 L54.75 46.75 M62 44.25 L62 46.75 M69.25 44.25 L69.25 46.75 M54.75 50.5 L54.75 53 M62 50.5 L62 53 M69.25 50.5 L69.25 53 M54.75 56.75 L54.75 59.25 M62 56.75 L62 59.25 M69.25 56.75 L69.25 59.25 M54.75 63 L54.75 65.5 M62 63 L62 65.5 M69.25 63 L69.25 65.5 M31 84 L80 84 C80.5523 84 81 84.4477 81 85 L81 88 C81 88.5523 80.5523 89 80 89 L31 89 C30.4477 89 30 88.5523 30 88 L30 85 C30 84.4477 30.4477 84 31 84",viewW:110,viewH:110}},{id:"sink",group:"sanitary",art:{d:"M51 41.5 L58.5 41.5 M51 41.5 C50.4477 41.5 50 41.9477 50 42.5 L50 48 M51 41.5 L55 41.5 M58.5 41.5 C59.0523 41.5 59.5 41.9477 59.5 42.5 L59.5 48 M58.5 41.5 L55 41.5 M59.5 48 L77 48 C78.3807 48 79.5 49.1193 79.5 50.5 L79.5 57 C79.5 62.5228 75.0228 67 69.5 67 L40 67 C34.4772 67 30 62.5228 30 57 L30 50.5 C30 49.1193 31.1193 48 32.5 48 L50 48 M59.5 48 L50 48 M45 37 L45 35 C45 33.6739 45.5268 32.4021 46.4645 31.4645 C47.4021 30.5268 48.6739 30 50 30 C51.3261 30 52.5979 30.5268 53.5355 31.4645 C54.4732 32.4021 55 33.6739 55 35 L55 41.5 M45 80 L64.5 80 C65.0523 80 65.5 79.5523 65.5 79 L65.5 67 L44 67 L44 79 C44 79.5523 44.4477 80 45 80 Z",viewW:110,viewH:110}},{id:"sofa",group:"furniture",art:{d:"M88.5 44.6689 L88.5 34 C88.5 31.2386 86.2614 29 83.5 29 L59.5 29 C56.7386 29 54.5 31.2386 54.5 34 M88.5 44.6689 C89.2354 44.2435 90.0893 44 91 44 M88.5 44.6689 C88.3992 44.7272 88.3006 44.7889 88.2045 44.8539 M54.5 61.75 L54.5 34 M54.5 61.75 C54.5 64.3734 52.3734 66.5 49.75 66.5 L25.25 66.5 C22.6266 66.5 20.5 64.3734 20.5 61.75 M54.5 61.75 C54.5 59.1266 52.3734 57 49.75 57 L25.25 57 C24.6761 57 24.1261 57.1018 23.6168 57.2882 M54.5 61.75 C54.5 64.3734 56.6266 66.5 59.25 66.5 L83.75 66.5 C86.3734 66.5 88.5 64.3734 88.5 61.75 M88.5 61.75 C88.5 59.9118 87.4558 58.3175 85.9283 57.5278 C85.8889 57.5075 85.8493 57.4877 85.8093 57.4684 C85.1863 57.1682 84.4878 57 83.75 57 L59.25 57 C56.6266 57 54.5 59.1266 54.5 61.75 M54.5 34 C54.5 31.2386 52.2614 29 49.5 29 L25.5 29 C22.7386 29 20.5 31.2386 20.5 34 L20.5 44.416 M20.5 44.416 C19.8875 44.1484 19.2111 44 18.5 44 M20.5 44.416 C22.2659 45.1876 23.5 46.9497 23.5 49 M18.5 44 C21.2614 44 23.5 46.2386 23.5 49 M18.5 44 L18 44 C15.2386 44 13 46.2386 13 49 L13 70.5 C13 73.2614 15.2386 75.5 18 75.5 M23.5 49 L23.5 57.3328 M23.5 57.3328 C21.7427 58.0295 20.5 59.7446 20.5 61.75 M23.5 57.3328 C23.5387 57.3174 23.5776 57.3026 23.6168 57.2882 M91 44 C89.9645 44 89.0025 44.3148 88.2045 44.8539 C86.8744 45.7525 86 47.2741 86 49 L86 57.5657 M85.9283 57.5278 C85.9523 57.5402 85.9762 57.5528 86 57.5657 C87.4884 58.3677 88.5 59.9407 88.5 61.75 M91 44 L91.5 44 C94.2614 44 96.5 46.2386 96.5 49 L96.5 70.5 C96.5 73.2614 94.2614 75.5 91.5 75.5 M91.5 75.5 L18 75.5 M91.5 75.5 L90.5 75.5 M18 75.5 L18.5 75.5 M20.5 61.75 C20.5 59.7005 21.798 57.9542 23.6168 57.2882 M18.5 75.5 L26.5 75.5 M18.5 75.5 L18.5 80.5 C18.5 81.3284 19.1716 82 20 82 L23.3921 82 C24.0506 82 24.6321 81.5705 24.8258 80.9411 L26.5 75.5 M26.5 75.5 L82.5 75.5 M90.5 75.5 L82.5 75.5 M90.5 75.5 L90.5 80.5 C90.5 81.3284 89.8284 82 89 82 L85.6079 82 C84.9494 82 84.3679 81.5705 84.1742 80.9411 L82.5 75.5",viewW:110,viewH:110}},{id:"stairs",group:"other",art:{d:"M73.4707 46.8057 L73.4707 28.5242 M73.4707 46.8057 L73.1504 46.8057 M73.4707 46.8057 L82.6039 46.8057 M73.4707 28.5242 L73.425 28.5242 M73.4707 28.5242 L75.6731 28.5242 M62.8987 54.2946 L62.8987 36.7397 M61.5762 61.7837 L61.5762 55.2944 C61.5762 54.7421 62.0239 54.2944 62.5762 54.2944 L62.8987 54.2946 L72.1504 54.2945 M52.3262 61.7837 L52.3262 45.1306 M52.3262 61.7837 L52.0039 61.7837 M52.3262 61.7837 L61.5762 61.7837 M62.8987 36.7397 L52.3262 45.1306 L42.1934 53.1725 L31.6211 61.5632 M42.1934 69.2725 L42.1934 53.1725 M42.1934 69.2725 L41.873 69.2725 M83.6035 69.2725 L83.6024 69.2725 L51.0039 69.2725 L42.1934 69.2725 M83.6031 76.7612 L83.6031 83.25 C83.6031 83.8023 83.1554 84.25 82.6031 84.25 L31.6231 84.2499 M41.873 69.2725 L83.6035 69.2725 L83.6031 76.7612 M83.6031 76.7612 L31.6231 76.7612 M31.6231 76.7612 L40.873 76.7613 L83.6031 76.7612 M31.6231 84.2499 L27.7773 84.2499 C27.2251 84.2499 26.7773 83.8021 26.7773 83.2499 L26.7773 57.4971 C26.7773 56.9448 27.2251 56.4971 27.7773 56.4971 L28.9352 56.4971 M31.6231 84.2499 L31.6231 76.7612 M31.6231 76.7612 L31.6211 61.5632 L31.6231 56.4971 M29.0212 56.4971 L31.6231 56.4971 L31.6228 57.2227 M31.6211 61.5632 L62.8987 36.7397 M31.6211 61.5632 L31.6228 57.2227 M73.425 28.5242 L75.6731 28.5242 M73.425 28.5242 C73.3119 28.5242 73.202 28.5624 73.1134 28.6328 L62.8987 36.7397 M75.6731 28.5242 C76.6463 28.5242 77.4352 27.7353 77.4352 26.7621 C77.4352 25.7889 76.6463 25 75.6731 25 L71.9495 25 C71.7935 25 71.6421 25.0532 71.5204 25.1508 L31.6228 57.2227 M41.873 69.2725 C41.3208 69.2725 40.873 69.7202 40.873 70.2725 L40.873 76.7613 M52.0039 61.7837 L83.6024 61.7837 M52.0039 61.7837 C51.4516 61.7837 51.0039 62.2314 51.0039 62.7837 L51.0039 69.2725 M83.6022 54.2944 L83.6024 61.7837 L83.6024 69.2725 M83.6024 61.7837 L61.5762 61.7837 M83.6022 54.2944 L83.6039 47.8057 C83.6039 47.2534 83.1562 46.8057 82.6039 46.8057 M83.6022 54.2944 L72.1504 54.2945 M73.1504 46.8057 L82.6039 46.8057 M73.1504 46.8057 C72.5981 46.8057 72.1504 47.2534 72.1504 47.8057 L72.1504 54.2945 M28.9352 56.4971 C28.9495 56.4973 28.9638 56.4974 28.9782 56.4974 C28.9925 56.4974 29.0069 56.4973 29.0212 56.4971 M28.9352 56.4971 C27.2519 56.4741 25.8945 55.1024 25.8945 53.4137 C25.8945 51.7107 27.2751 50.3301 28.9782 50.3301 C30.6812 50.3301 32.0618 51.7107 32.0618 53.4137 C32.0618 55.1024 30.7044 56.4741 29.0212 56.4971 M28.9352 56.4971 L29.0212 56.4971",viewW:110,viewH:110}},{id:"toilet",group:"sanitary",art:{d:"M64.5372 72.1021 L67.6892 84.7575 C67.847 85.3886 67.3696 86 66.7191 86 L37.6483 86 C37.0414 86 36.5743 85.4636 36.6578 84.8624 L38.9999 68 C40.0716 64 32.5 64.5 32 57 L32 26.5 C32 25.1193 33.1193 24 34.5 24 L45 24 C46.3807 24 47.5 25.1193 47.5 26.5 L47.5 52 M32 57 L47.5 57 M47.5 52 L76.5 52 C77.8807 52 79 53.1193 79 54.5 L79 57 M47.5 52 L47.5 57 M54.9999 71.75 C58.5528 72.6096 61.7379 72.6416 64.5372 72.1021 C73.95 70.2877 79 62.0101 79 57 M79 57 L47.5 57",viewW:110,viewH:110}},{id:"tv",group:"appliance",art:{d:"M23.5 31 L86 31 C87.3807 31 88.5 32.1193 88.5 33.5 L88.5 67.5 C88.5 68.8807 87.3807 70 86 70 L23.5 70 C22.1193 70 21 68.8807 21 67.5 L21 33.5 C21 32.1193 22.1193 31 23.5 31 M50 70 L50 78 M59.5 70 L59.5 78 M40 78 L70 78 M42.5466 45.9951 L52.5466 45.9951 M47.5466 45.9951 L47.5 56.0336 M56.75 45.5 L61.75 55.5 L66.75 45.5",viewW:110,viewH:110}},{id:"wardrobe",group:"furniture",art:{d:"M54.5 20.5 L30.5 20.5 C29.1193 20.5 28 21.6193 28 23 L28 82.5 C28 83.8807 29.1193 85 30.5 85 L54.5 85 M54.5 20.5 L54.5 85 M54.5 20.5 L78.5 20.5 C79.8807 20.5 81 21.6193 81 23 L81 82.5 C81 83.8807 79.8807 85 78.5 85 L54.5 85 M79 84.95 L79 88.5 C79 89.0523 78.5523 89.5 78 89.5 L31 89.5 C30.4477 89.5 30 89.0523 30 88.5 L30 84.95 M50.5 48 L50.5 57.5 M58.5 48 L58.5 57.5",viewW:110,viewH:110}},{id:"washer",group:"appliance",art:{d:"M81 40 C81 38.6193 79.8807 37.5 78.5 37.5 L31.5 37.5 C30.1193 37.5 29 38.6193 29 40 M35.75 31 L45.25 31 M31.5 85 L78.5 85 C79.8807 85 81 83.8807 81 82.5 L81 55.5 L81 27.5 C81 26.1193 79.8807 25 78.5 25 L31.5 25 C30.1193 25 29 26.1193 29 27.5 L29 56 L29 82.5 C29 83.8807 30.1193 85 31.5 85 Z M72 60.5 C72 69.8888 64.3888 77.5 55 77.5 C45.6112 77.5 38 69.8888 38 60.5 C38 51.1112 45.6112 43.5 55 43.5 C64.3888 43.5 72 51.1112 72 60.5 Z M66.5 60.5 C66.5 66.8513 61.3513 72 55 72 C48.6487 72 43.5 66.8513 43.5 60.5 C43.5 54.1487 48.6487 49 55 49 C61.3513 49 66.5 54.1487 66.5 60.5 Z M69.5 31 C69.5 32.1046 68.6046 33 67.5 33 C66.3954 33 65.5 32.1046 65.5 31 C65.5 29.8954 66.3954 29 67.5 29 C68.6046 29 69.5 29.8954 69.5 31 Z M77 31 C77 32.1046 76.1046 33 75 33 C73.8954 33 73 32.1046 73 31 C73 29.8954 73.8954 29 75 29 C76.1046 29 77 29.8954 77 31 Z",viewW:110,viewH:110}},{id:"work_table",group:"furniture",art:{d:"M68.5 61 L68.5 73.5 C68.5 74.3284 69.1716 75 70 75 L87 75 C87.8284 75 88.5 74.3284 88.5 73.5 L88.5 61 L88.4844 47 M26.4844 47 L26.4844 73.5 C26.4844 74.3284 25.8128 75 24.9844 75 L23.9844 75 C23.1559 75 22.4844 74.3284 22.4844 73.5 L22.4844 47 L22.4844 43 L24.866 35.5974 C25.2388 34.6346 26.165 34 27.1974 34 L83.7743 34 C84.8054 34 85.7307 34.633 86.1044 35.5939 L88.4844 43 L88.4844 47 M88.4844 47 L68.5 47 M68.5 47 L68.5 61 M68.5 47 L26.4844 47 M68.5 61 L88.5 61 M76.5 51 L80.5 51 M88.4844 43 L22.4844 43 M22.4844 47 L26.4844 47 M76.5 65 L80.5 65",viewW:110,viewH:110}}];class xd{constructor(t,e){this.host=t,this.hooks=e}place(t,e="mouse"){const s=this.host._decorImagePalette,i=this.host._curSpaceCfg;if(!s||!i)return;const o=this.hooks.decorSnap(t,e),a=ge(s.width,s.height),n=fe(a.w,this.host._cellCm,this.host._gridPitch)/pt,r=fe(a.h,this.host._cellCm,this.host._gridPitch)/this.host._decorH,l="di"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),h=this.hooks.geometrySnapshot();i.decor=[...this.host._decorList,{id:l,kind:"image",asset_id:s.asset_id,x:ie(o[0]/pt-n/2),y:ie(o[1]/this.host._decorH-r/2),w:n,h:r,opacity:1}],this.host._decorSel=l,this.host._decorTool="select",this.host._decorImagePalette=null,this.hooks.clearFurniturePreview(),this.hooks.recordGeometry(this.host._t("history.decor_add"),h),this.hooks.saveConfig(),this.host.requestUpdate()}renderPlacementPreview(){const t=this.host._furnPreviewInput,e=this.host._decorImagePalette;if(!t||!e||"decor"!==this.host._mode||"image"!==this.host._decorTool||!this.host._pointerModality.hoverEnabled)return d;const s=this.hooks.decorSnap(t.raw,"mouse"),i=ge(e.width,e.height),o=fe(i.w,this.host._cellCm,this.host._gridPitch)/pt,a=fe(i.h,this.host._cellCm,this.host._gridPitch)/this.host._decorH,n=this.host._display(e.url);return n?Tt`<image class="decor-image-placement-preview" href=${n}
|
||
x=${s[0]-o*pt/2} y=${s[1]-a*this.host._decorH/2}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
width=${o*pt} height=${a*this.host._decorH}
|
||
opacity="0.65" preserveAspectRatio="none" pointer-events="none"></image>`:d}renderMissing(t,e,i,s,o,a,n,r,l){const h=s+a/2,c=o+n/2;return Tt`<g class="${e} dimage-missing"
|
||
data-hp="decor" data-id=${t.id} data-kind="image" transform=${i}
|
||
@pointerdown=${r} @dblclick=${l}>
|
||
<title>${this.host._t("decor.image_unavailable")}</title>
|
||
<rect x=${s} y=${o} width=${a} height=${n}></rect>
|
||
<path d=${`M${s} ${o}L${s+a} ${o+n}M${s+a} ${o}L${s} ${o+n}`}></path>
|
||
<text class="dimage-missing-label" x=${h} y=${c}
|
||
fill="var(--primary-text-color, #333)" stroke="var(--card-background-color, #fff)"
|
||
stroke-width="2" paint-order="stroke" pointer-events="none"
|
||
font-size=${Math.min(18,.25*n)} text-anchor="middle" dominant-baseline="middle"
|
||
textLength=${Math.max(1,Math.min(.8*a,160))}
|
||
lengthAdjust="spacingAndGlyphs">${this.host._t("decor.image_unavailable")}</text>
|
||
</g>`}async uploadFromInput(t,e=!1){const i=t.target,s=i.files?.[0];if(i.value="",!s||this.host._decorAssetBusy)return;let o;try{o=await Ko(s,2097152)}catch{return void this.host._showToast(this.host._t("backup.error.invalid_image"))}if("reject"!==o.kind)return"guard"===o.kind?(this.hooks.setGuardReplace(e),void(this.host._backdropGuard=o.state)):void await this.upload(s,s.name,e);this.host._showToast(this.host._t("toast.plan_formats"))}async upload(t,e,i){if(!this.host._decorAssetBusy){this.host._decorAssetBusy=!0;try{const s=new FormData;s.append("file",t,e);const o=this.host.hass?.fetchWithAuth?await this.host.hass.fetchWithAuth("/api/houseplan/assets/upload",{method:"POST",body:s}):await fetch("/api/houseplan/assets/upload",{method:"POST",body:s,headers:this.host.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.host.hass.auth.data.access_token}`}:{}}),a=await o.json().catch(()=>({}));if(!o.ok||a.error||!a.asset){const t={invalid_format:"backup.error.invalid_image",invalid_image:"backup.error.invalid_image",unsupported_image:"backup.error.unsupported_image",too_large:"backdrop.too_large_title",capacity_exceeded:"decor.image_error_capacity"};throw new Error(this.host._t(t[String(a.error)]||"backup.error.io_error"))}const n=ve({assets:[a.asset]}).values().next().value;if(!n)throw new Error(this.host._t("backup.error.io_error"));this.host._decorAssets=new Map(this.host._decorAssets).set(n.asset_id,n),this.host._decorAssetCatalog=[n,...this.host._decorAssetCatalog.filter(t=>t.asset_id!==n.asset_id)],i&&"image"===this.host._decorShapeDialog?.kind?this.host._decorShapeDialog={...this.host._decorShapeDialog,assetId:n.asset_id}:this.host._decorImagePalette=n,this.host.requestUpdate()}catch(t){this.host._showToast(this.host._t("decor.image_upload_failed",{err:this.host._errText(t)}))}finally{this.host._decorAssetBusy=!1}}}async delete(t){if(t.used_by?.length)return void this.host._showToast(this.host._t("decor.image_in_use"));if(await this.host._confirmDanger({key:`delete-decor-asset:${t.asset_id}`,kind:"destructive",title:this.host._t("decor.image_delete_title"),message:this.host._t("decor.image_delete_message",{name:t.name}),confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}))try{await this.host.hass.callWS({type:"houseplan/assets/delete",asset_id:t.asset_id}),this.host._decorAssetCatalog=this.host._decorAssetCatalog.filter(e=>e.asset_id!==t.asset_id),this.host._decorAssets.delete(t.asset_id),this.host._decorImagePalette?.asset_id===t.asset_id&&(this.host._decorImagePalette=null),this.host.requestUpdate()}catch(t){this.host._showToast("in_use"===t?.code?this.host._t("decor.image_in_use"):this.host._t("backup.error.io_error"))}}async loadCatalog(){try{const t=await this.host.hass.callWS({type:"houseplan/assets/list"}),e=ve(t);this.host._decorAssetCatalog=[...e.values()],this.host._decorAssets=new Map([...this.host._decorAssets,...e]),this.host.requestUpdate()}catch{this.host._showToast(this.host._t("backup.error.io_error"))}}renderImagePalette(){const t=this.host._decorImagePalette;return p`<div class="furnpalette imagepalette" role="dialog"
|
||
aria-label=${this.host._t("decor.image_title")}
|
||
@pointerdown=${t=>t.stopPropagation()}>
|
||
<div class="furnhd"><ha-icon icon="mdi:image-plus-outline"></ha-icon>${this.host._t("decor.image_title")}
|
||
<span class="spacer"></span>
|
||
<button class="btn furnclose" title=${this.host._t("btn.close")} @click=${()=>{this.host._decorImagePalette=null,this.hooks.clearFurniturePreview(),this.host._decorTool="select"}}><ha-icon icon="mdi:close"></ha-icon></button>
|
||
</div>
|
||
<div class="furnbody">
|
||
<label class="btn primary imageupload ${this.host._decorAssetBusy?"disabled":""}">
|
||
<ha-icon icon="mdi:upload"></ha-icon>${this.host._t(this.host._decorAssetBusy?"decor.image_uploading":"decor.image_upload")}
|
||
<input type="file" accept=".png,.jpg,.jpeg,.webp,.svg,image/png,image/jpeg,image/webp,image/svg+xml"
|
||
?disabled=${this.host._decorAssetBusy}
|
||
@change=${t=>this.uploadFromInput(t)} />
|
||
</label>
|
||
<div class="furnrow imageassets">
|
||
${this.host._decorAssetCatalog.length?d:p`<span class="furnhint imageempty">${this.host._t("decor.image_none")}</span>`}
|
||
${this.host._decorAssetCatalog.map(e=>p`<div class="imageasset">
|
||
<button class="furnitem ${t?.asset_id===e.asset_id?"on":""}"
|
||
title=${e.name} @click=${()=>{this.host._decorImagePalette=e,this.host.requestUpdate()}}>
|
||
<img src=${this.host._display(e.url)} alt="" /><span>${e.name}</span>
|
||
${e.used_by?.length?p`<small>${this.host._t("decor.image_used",{n:e.used_by.length})}</small>`:d}
|
||
</button>
|
||
<button class="btn ghost imageassetdelete" title=${this.host._t("btn.delete")}
|
||
?disabled=${!!e.used_by?.length}
|
||
@click=${()=>this.delete(e)}><ha-icon icon="mdi:delete-outline"></ha-icon></button>
|
||
</div>`)}
|
||
</div>
|
||
</div>
|
||
<div class="furnsize"><span class="furnhint">${this.host._t(t?"decor.image_place_hint":"decor.image_pick_hint")}</span></div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</div>`}renderFurniturePalette(){const t=this.host._furnPalette,e=this.host._furnCategory,i=ye.flatMap(t=>we(t)),s=Pd.filter(t=>i.some(e=>e.category===t.id)),o=s.find(t=>t.id===e)||null,a=o?i.filter(t=>t.category===o.id):[],n=this.host._t(this.host._imperial?"gs.unit_ft":"gs.unit_m");return p`<div class="furnpalette" @pointerdown=${t=>t.stopPropagation()}>
|
||
========
|
||
</div>`}renderFurniturePalette(){const t=this.host._furnPalette,e=this.host._furnCategory,s=ve.flatMap(t=>ye(t)),i=kd.filter(t=>s.some(e=>e.category===t.id)),o=i.find(t=>t.id===e)||null,a=o?s.filter(t=>t.category===o.id):[],n=this.host._t(this.host._imperial?"gs.unit_ft":"gs.unit_m");return p`<div class="furnpalette" @pointerdown=${t=>t.stopPropagation()}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="furnhd">
|
||
<ha-icon icon="mdi:sofa-outline"></ha-icon>${this.host._t("furn.title")}
|
||
<span class="spacer"></span>
|
||
<button class="btn furnclose" title=${this.host._t("btn.close")}
|
||
@click=${()=>{this.hooks.clearFurniturePreview(),this.host._furnPalette=null,this.hooks.furnShiftDetach(),this.host._furnCategory=null,this.host._decorTool="select"}}>
|
||
<ha-icon icon="mdi:close"></ha-icon>
|
||
</button>
|
||
</div>
|
||
<div class="furnbody">
|
||
${o?p`
|
||
<button class="btn ghost furnback" @click=${()=>{this.hooks.clearFurniturePreview(),this.host._furnPalette=null,this.hooks.furnShiftDetach(),this.host._furnCategory=null}}>
|
||
<ha-icon icon="mdi:arrow-left"></ha-icon>${this.host._t("furn.back_to_categories")}
|
||
</button>
|
||
<div class="furngroup" data-category=${o.id}>
|
||
${this.host._t(`furn.cat_${o.id}`)}
|
||
</div>
|
||
<div class="furnrow furnvariants">
|
||
${a.map(e=>p`<button
|
||
class="furnitem ${t?.symbol===e.id?"on":""}" data-symbol=${e.id}
|
||
title=${this.host._t(`furn.sym_${e.id}`)}
|
||
@click=${()=>this.hooks.furnPick(e.id)}>
|
||
${(t=>{const e=Ce(t);return e?Tt`<svg class="furnprev" viewBox=${`0 0 ${e.viewW} ${e.viewH}`}
|
||
preserveAspectRatio="xMidYMid meet" aria-hidden="true"><path
|
||
d=${e.d} fill="none" stroke="currentColor" stroke-width="1.2"
|
||
vector-effect="non-scaling-stroke" stroke-linecap="round"
|
||
stroke-linejoin="round"></path></svg>`:Tt`<svg class="furnprev" aria-hidden="true"></svg>`})(e.id)}<span>${this.host._t(`furn.sym_${e.id}`)}</span>
|
||
</button>`)}
|
||
</div>
|
||
`:ye.map(t=>p`
|
||
<div class="furngroup" data-group=${t}>${this.host._t(`furn.group_${t}`)}</div>
|
||
<div class="furnrow furncategories">
|
||
${s.filter(e=>e.group===t).map(t=>p`<button
|
||
class="furnitem furncategory" data-category=${t.id}
|
||
title=${this.host._t(`furn.cat_${t.id}`)}
|
||
@click=${()=>{this.hooks.clearFurniturePreview(),this.host._furnPalette=null,this.hooks.furnShiftDetach(),this.host._furnCategory=t.id}}>
|
||
${(t=>Tt`<svg class="furnprev furncatprev" viewBox=${`0 0 ${t.art.viewW} ${t.art.viewH}`}
|
||
preserveAspectRatio="xMidYMid meet" aria-hidden="true"><path
|
||
d=${t.art.d} fill="none" stroke="currentColor" stroke-width="1.5"
|
||
vector-effect="non-scaling-stroke" stroke-linecap="round"
|
||
stroke-linejoin="round"></path></svg>`)(t)}<span>${this.host._t(`furn.cat_${t.id}`)}</span>
|
||
</button>`)}
|
||
</div>`)}
|
||
</div>
|
||
${t?p`<div class="furnsize">
|
||
<label>${this.host._t("furn.width")}<span class="furnunit">${n}</span></label>
|
||
<input class="namein furnw" type="number" min="0.01" step="0.05"
|
||
.value=${String(this.hooks.furnFieldValue(t.w))}
|
||
@input=${e=>this.host._furnPalette={...t,w:this.hooks.furnFieldToCm(Number(e.target.value))}} />
|
||
<label>${this.host._t("furn.depth")}<span class="furnunit">${n}</span></label>
|
||
<input class="namein furnh" type="number" min="0.01" step="0.05"
|
||
.value=${String(this.hooks.furnFieldValue(t.h))}
|
||
@input=${e=>this.host._furnPalette={...t,h:this.hooks.furnFieldToCm(Number(e.target.value))}} />
|
||
<span class="furnhint">${this.host._t("furn.place_hint")}</span>
|
||
</div>`:p`<div class="furnsize"><span class="furnhint">${this.host._t("furn.pick_hint")}</span></div>`}
|
||
</div>`}furnitureSizeInput(t,e){const i=this.host._decorShapeDialog;if(!i||"furniture"!==i.kind&&"image"!==i.kind)return;const s=$e(e,this.host._imperial,ke*this.host._cellCm),o="w"===t?"sizeWField":"sizeHField",a="w"===t?"sizeWCm":"sizeHCm",n="w"===t?"flipH":"flipV";this.host._decorShapeDialog={...i,[o]:e,...null===s?{}:{[a]:Math.abs(s),[n]:s<0}}}furnitureFlip(t,e){const i=this.host._decorShapeDialog;if(!i||"furniture"!==i.kind&&"image"!==i.kind)return;const s="w"===t?i.sizeWField:i.sizeHField,o=$e(s,this.host._imperial,ke*this.host._cellCm),a="w"===t?i.sizeWCm:i.sizeHCm,n=Math.abs(o??a??.1),r="w"===t?"sizeWField":"sizeHField",l="w"===t?"flipH":"flipV";this.host._decorShapeDialog={...i,[r]:xe(n,e,this.host._imperial),[l]:e}}renderShapeDialog(){const t=this.host._decorShapeDialog,e="rect"===t.kind||"ellipse"===t.kind,i=this.host._t(`decor.${t.kind}`),s=this.host._t(this.host._imperial?"gs.unit_ft":"gs.unit_m"),o="furniture"===t.kind||"image"===t.kind?$e(t.sizeWField,this.host._imperial,ke*this.host._cellCm):null,a="furniture"===t.kind||"image"===t.kind?$e(t.sizeHField,this.host._imperial,ke*this.host._cellCm):null,n=!("furniture"!==t.kind&&"image"!==t.kind||null!==o&&null!==a),r="image"===t.kind?this.host._decorAssetCatalog.find(e=>e.asset_id===t.assetId)||this.host._decorAssets.get(t.assetId||""):null;return p`<hp-dialog .hass=${this.host.hass} data-kind="decor"
|
||
.title=${this.host._t("decor.object_title",{kind:i})} icon="mdi:pencil-outline"
|
||
dismiss-on-scrim @hp-close=${()=>this.host._decorShapeDialog=null}>
|
||
<div class="body">
|
||
${"furniture"===t.kind?p`
|
||
<label>${this.host._t("furn.symbol")}</label>
|
||
<select class="namein"
|
||
@change=${e=>this.host._decorShapeDialog={...t,symbol:e.target.value}}>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${Pd.map(t=>({category:t,symbols:we(t.group).filter(e=>e.category===t.id)})).filter(t=>t.symbols.length).map(({category:e,symbols:i})=>p`
|
||
========
|
||
${kd.map(t=>({category:t,symbols:ye(t.group).filter(e=>e.category===t.id)})).filter(t=>t.symbols.length).map(({category:e,symbols:s})=>p`
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<optgroup label=${`${this.host._t(`furn.group_${e.group}`)} · ${this.host._t(`furn.cat_${e.id}`)}`}>
|
||
${i.map(e=>p`<option value=${e.id}
|
||
?selected=${e.id===Me(t.symbol||"")}>
|
||
${this.host._t(`furn.sym_${e.id}`)}
|
||
</option>`)}
|
||
</optgroup>`)}
|
||
</select>`:"image"===t.kind?p`
|
||
<label>${this.host._t("decor.image_asset")}</label>
|
||
<select class="namein" .value=${t.assetId||""}
|
||
@change=${e=>this.host._decorShapeDialog={...t,assetId:e.target.value}}>
|
||
${this.host._decorAssetCatalog.map(e=>p`<option value=${e.asset_id}
|
||
?selected=${e.asset_id===t.assetId}>${e.name}</option>`)}
|
||
</select>
|
||
${r?p`<div class="imagepropertypreview">
|
||
<img src=${this.host._display(r.url)} alt=${r.name} />
|
||
<span>${r.name}</span>
|
||
</div>`:d}
|
||
<label class="btn ghost imageupload">
|
||
<ha-icon icon="mdi:image-refresh-outline"></ha-icon>${this.host._t("decor.image_replace")}
|
||
<input type="file" accept=".png,.jpg,.jpeg,.webp,.svg,image/png,image/jpeg,image/webp,image/svg+xml"
|
||
?disabled=${this.host._decorAssetBusy}
|
||
@change=${t=>this.uploadFromInput(t,!0)} />
|
||
</label>`:d}
|
||
${"image"===t.kind?p`
|
||
<label>${this.host._t("space.opacity")}</label>
|
||
<input class="namein" type="range" min="0" max="1" step="0.01"
|
||
.value=${String(t.opacity)}
|
||
@input=${e=>this.host._decorShapeDialog={...t,opacity:Number(e.target.value)}} />`:p`<hp-color-opacity .label=${this.host._t("decor.color")}
|
||
.color=${t.color} .opacity=${t.opacity}
|
||
.opacityLabel=${this.host._t("space.opacity")}
|
||
.pickerLabels=${this.host._colorPickerLabels}
|
||
@hp-color-opacity-change=${e=>this.host._decorShapeDialog={...t,...e.detail}}></hp-color-opacity>`}
|
||
${"image"!==t.kind?p`<label>${this.host._t("decor.width")}</label>
|
||
<div class="colorrow"><input class="namein" type="number"
|
||
min=${this.host._decorSmallField(.1)} max=${this.host._decorSmallField(100)} step="0.1"
|
||
.value=${String(this.host._decorSmallField(t.widthCm))}
|
||
@input=${e=>this.host._decorShapeDialog={...t,widthCm:this.host._decorSmallCm(Number(e.target.value))}} /><span class="opl">${this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}</span></div>`:d}
|
||
${"line"===t.kind?p`
|
||
<label>${this.host._t("decor.line_style")}</label>
|
||
<div role="radiogroup" aria-label=${this.host._t("decor.line_style")}>
|
||
<label class="srcrow"><input type="radio" name="decor-line-style"
|
||
.checked=${"dashed"!==t.lineStyle}
|
||
@change=${()=>this.host._decorShapeDialog={...t,lineStyle:"solid"}} />
|
||
<span>${this.host._t("decor.line_style_solid")}</span></label>
|
||
<label class="srcrow"><input type="radio" name="decor-line-style"
|
||
.checked=${"dashed"===t.lineStyle}
|
||
@change=${()=>this.host._decorShapeDialog={...t,lineStyle:"dashed"}} />
|
||
<span>${this.host._t("decor.line_style_dashed")}</span></label>
|
||
</div>
|
||
<label>${this.host._t("decor.length")}</label>
|
||
<div class="colorrow"><input class="namein" type="number" min="0.01" step="0.01"
|
||
.value=${String(this.host._decorLargeField(t.lengthCm||0))}
|
||
@input=${e=>this.host._decorShapeDialog={...t,lengthCm:this.host._decorLargeCm(Number(e.target.value))}} />
|
||
<span class="opl">${s}</span></div>`:"furniture"===t.kind||"image"===t.kind?p`
|
||
<label>${this.host._t("decor.size")}</label>
|
||
<div class="colorrow"><input class="namein" type="number" step="any"
|
||
aria-invalid=${null===o?"true":"false"}
|
||
.value=${t.sizeWField||""}
|
||
@input=${t=>this.furnitureSizeInput("w",t.target.value)} />
|
||
<span>×</span><input class="namein" type="number" step="any"
|
||
aria-invalid=${null===a?"true":"false"}
|
||
.value=${t.sizeHField||""}
|
||
@input=${t=>this.furnitureSizeInput("h",t.target.value)} />
|
||
<span class="opl">${s}</span></div>
|
||
<label class="dfill"><input type="checkbox" .checked=${!!t.flipH}
|
||
@change=${t=>this.furnitureFlip("w",t.target.checked)} />${this.host._t("decor.flip_h")}</label>
|
||
<label class="dfill"><input type="checkbox" .checked=${!!t.flipV}
|
||
@change=${t=>this.furnitureFlip("h",t.target.checked)} />${this.host._t("decor.flip_v")}</label>`:p`
|
||
<label>${this.host._t("decor.size")}</label>
|
||
<div class="colorrow"><input class="namein" type="number" min="0.01" step="0.01"
|
||
.value=${String(this.host._decorLargeField(t.sizeWCm||0))}
|
||
@input=${e=>this.host._decorShapeDialog={...t,sizeWCm:this.host._decorLargeCm(Number(e.target.value))}} />
|
||
<span>×</span><input class="namein" type="number" min="0.01" step="0.01"
|
||
.value=${String(this.host._decorLargeField(t.sizeHCm||0))}
|
||
@input=${e=>this.host._decorShapeDialog={...t,sizeHCm:this.host._decorLargeCm(Number(e.target.value))}} />
|
||
<span class="opl">${s}</span></div>`}
|
||
<label>${this.host._t("decor.angle")}</label>
|
||
<input class="namein" type="number" min="-180" max="180" step="1"
|
||
.value=${t.angle}
|
||
@input=${e=>this.host._decorShapeDialog={...t,angle:e.target.value}} />
|
||
${e?p`<label class="dfill"><input type="checkbox" .checked=${!!t.fill}
|
||
@change=${e=>this.host._decorShapeDialog={...t,fill:e.target.checked}} />${this.host._t("decor.fill")}</label>
|
||
<hp-color-opacity .label=${this.host._t("decor.fill_color")}
|
||
.color=${t.fillColor||t.color} .opacity=${t.fillOpacity??.25}
|
||
.opacityLabel=${this.host._t("space.opacity")}
|
||
.pickerLabels=${this.host._colorPickerLabels} .disabled=${!t.fill}
|
||
@hp-color-opacity-change=${e=>this.host._decorShapeDialog={...t,fillColor:e.detail.color,fillOpacity:e.detail.opacity}}></hp-color-opacity>`:d}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel"
|
||
@click=${()=>this.host._decorShapeDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<button class="btn primary" data-hp="dialog-confirm" ?disabled=${n}
|
||
@click=${this.hooks.saveShape}>${this.host._t("btn.save")}</button>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}}const Dd=(t,e)=>t[0]*e[1]-t[1]*e[0],Ld=(t,e)=>t[0]*e[0]+t[1]*e[1],Td=(t,e)=>[t[0]-e[0],t[1]-e[1]],Rd=(t,e,i)=>[t[0]+e[0]*i,t[1]+e[1]*i];function Fd(t,e,i){return Math.abs(Dd(t,e))<=i}function zd(t,e,i){return Math.abs(Dd(Td(t,e),i))}function Nd(t,e,i,s,o){const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(!(r>o&&i>0))return[];const l=[a/r,n/r];return function(t,e,i){const s=e.map(([e,i])=>[Math.max(0,Math.min(e,i)),Math.min(t,Math.max(e,i))]).filter(([t,e])=>e>t+i).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),o=[];for(const t of s){const e=o[o.length-1];!e||t[0]>e[1]+i?o.push([...t]):e[1]=Math.max(e[1],t[1])}const a=[];let n=0;for(const[t,e]of o)t>n+i&&a.push([n,t]),n=Math.max(n,e);return t>n+i&&a.push([n,t]),a}(r,s.flatMap(e=>{const s=e.b[0]-e.a[0],a=e.b[1]-e.a[1],n=Math.hypot(s,a);if(!(n>o&&Fd(l,[s/n,a/n],1e-6)))return[];if(zd(e.a,t,l)>1.1*Math.max(i,o)||zd(e.b,t,l)>1.1*Math.max(i,o))return[];return[[Ld(Td(e.a,t),l),Ld(Td(e.b,t),l)]]}),o).flatMap(([e,s])=>{const o=Ie({a:Rd(t,l,e),b:Rd(t,l,s),halfDepth:i});return o?[o]:[]})}function Ed(t){const e=t.coordScale??1,i=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),s=[];for(const i of t.rooms||[]){if(!i?.id)continue;const o=kt(t.rooms,i.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!o||o.poly.length<3)continue;const a=Se(o.poly,o.offsets);!a||a.length<3||s.push({roomId:i.id,profile:o,inner:a})}s.sort((t,e)=>t.roomId.localeCompare(e.roomId));const o=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,i=[Math.cos(e),Math.sin(e)],s=Math.max(0,t.length)/2;return{a:Rd([t.x,t.y],i,-s),b:Rd([t.x,t.y],i,s)}}),a=[];for(const s of Pe(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of Nd(s.a,s.b,s.depthUnits/2,o,i))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 s=X(e.cm,t.cellCm,t.gridPitch)/2;for(const t of Nd(e.a,e.b,s,n.get(e.id)||[],i))a.push({body:t,partitionId:e.id})}return{rooms:s,boundaries:a,epsilon:i}}function Ad(t,e,i,s){const o=t.profile.offsets[e];if(!(o>0))return null;const a=function(t,e){const i=t[e],s=t[(e+1)%t.length],o=s[0]-i[0],a=s[1]-i[1],n=Math.hypot(o,a)||1;return function(t){let e=0;for(let i=0;i<t.length;i++){const s=t[i],o=t[(i+1)%t.length];e+=s[0]*o[1]-o[0]*s[1]}return e/2}(t)>=0?[-a/n,o/n]:[a/n,-o/n]}(t.profile.poly,e),n=Rd(i.center,a,o),r=[];for(let e=0;e<t.inner.length;e++){const o=t.inner[e],a=t.inner[(e+1)%t.inner.length],l=Td(a,o),h=Math.hypot(l[0],l[1]);if(!(h>s&&Fd(i.axis,[l[0]/h,l[1]/h],1e-6)))continue;if(zd(o,n,i.axis)>s||zd(a,n,i.axis)>s)continue;const c=Ld(Td(o,n),i.axis),d=Ld(Td(a,n),i.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 i=[];for(const s of t){const t=i[i.length-1];!t||s[0]>t[1]+e?i.push([...s]):t[1]=Math.max(t[1],s[1])}return i}(r,s).find(([t,e])=>t<=s&&e>=-s);if(!l)return null;const[h,c]=l,d=Rd(n,i.axis,-i.half),p=Rd(n,i.axis,i.half),u=Math.max(0,-i.half-h),_=Math.max(0,c-i.half),m=u>0?Rd(n,i.axis,h):d,g=_>0?Rd(n,i.axis,c):p,f=Ld(a,i.normal)>=0?1:-1,b=(e,s,o)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:i.axis,labelNormal:a,distance:o,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:b(d,m,u),right:b(p,g,_)}}function Od(t){const e=Rd(t.center,t.axis,-t.half),i=Rd(t.center,t.axis,t.half),s=Rd(t.center,t.axis,Math.min(-t.half,t.targetLo)),o=Rd(t.center,t.axis,Math.max(t.half,t.targetHi)),a=(e,i)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(i[0]-e[0],i[1]-e[1]),source:"host-end"});return[a(e,s),a(i,o)]}function Bd(t,e,i,s){const o=Td(i,e),a=Ld(o,o);if(!(a>s*s))return Math.hypot(...Td(t,e))<=s;const n=Ld(Td(t,e),o)/a;if(n<-s||n>1+s)return!1;const r=Rd(e,o,Math.max(0,Math.min(1,n)));return Math.hypot(...Td(t,r))<=s}function Hd(t,e,i){let s=!1;for(let o=0,a=e.length-1;o<e.length;a=o++){if(Bd(t,e[a],e[o],i))return!0;const[n,r]=e[o],[l,h]=e[a];r>t[1]!=h>t[1]&&t[0]<(l-n)*(t[1]-r)/(h-r)+n&&(s=!s)}return s}function Wd(t,e,i,s,o,a){const n=Td(s,i),r=Dd(e,n);if(Math.abs(r)<=a)return null;const l=Td(i,t),h=Dd(l,n)/r,c=Dd(l,e)/r;return h<-a||h>o+a||c<-a||c>1+a?null:Math.max(0,Math.min(o,h))}function Gd(t,e,i){const s=Od(i),o="partition"===t.host?.kind?t.host.id:void 0;return[{base:s[0],direction:[-i.axis[0],-i.axis[1]]},{base:s[1],direction:i.axis}].map(({base:t,direction:i})=>{const s=t.distance,a=function(t,e,i,s,o,a){let n=null;for(const r of s)if(!o||r.partitionId!==o){if(Hd(t,r.body,a))return 0;for(let s=0;s<r.body.length;s++){const o=Wd(t,e,r.body[s],r.body[(s+1)%r.body.length],i,a);null!=o&&(null==n||o<n)&&(n=o)}}return n}(t.from,i,s,e.boundaries,o,e.epsilon);if(null==a)return t;const n=Rd(t.from,i,a);return{...t,to:n,label:[(t.from[0]+n[0])/2,(t.from[1]+n[1])/2],distance:a,source:"connected-face"}})}function jd(t,e){const i=function(t){const e=t.angle*Math.PI/180,i=[Math.cos(e),Math.sin(e)],s=[-i[1],i[0]],o=[t.x,t.y],a=[t.target.a,t.target.b].map(t=>Ld(Td(t,o),i));return{center:o,axis:i,normal:s,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...a),targetHi:Math.max(...a)}}(t),s=e.rooms.flatMap(t=>{const s=function(t,e,i){const{profile:s}=t;let o=null;for(let t=0;t<s.poly.length;t++){if(!(s.kinds[t]&&s.offsets[t]>0))continue;const a=s.poly[t],n=s.poly[(t+1)%s.poly.length],r=Td(n,a),l=Math.hypot(r[0],r[1]);if(!(l>i&&Fd(e.axis,[r[0]/l,r[1]/l],1e-6)))continue;if(zd(a,e.center,e.axis)>i||zd(n,e.center,e.axis)>i)continue;const h=Ld(Td(a,e.center),e.axis),c=Ld(Td(n,e.center),e.axis),d=Math.min(h,c),p=Math.max(h,c);if(d>-e.half+i||p<e.half-i)continue;const u=Math.max(0,d>0?d:p<0?-p:0);(!o||u<o.offset-i||Math.abs(u-o.offset)<=i&&t<o.edge)&&(o={edge:t,offset:u})}return o?.edge??null}(t,i,e.epsilon);return null==s?[]:[{room:t,edge:s}]});if(s.length>2)return Od(i);if(s.length){const t=s.map(({room:t,edge:s})=>Ad(t,s,i,e.epsilon));if(t.some(t=>!t))return Od(i);const o=t;return[...o.map(t=>t.left),...o.map(t=>t.right)]}return Gd(t,e,i)}function Ud(t,e,i,s,o){const a=(n=t,JSON.parse(JSON.stringify(n)));var n;const r=[...new Set(s.filter(t=>"string"==typeof t&&t))],l={partitionsMerged:0,partitionsReconciled:0,openingsRehosted:0,changed:!1};if(!r.length||!Array.isArray(a?.partitions))return{space:a,report:l};const h=JSON.stringify(a),c=sn(a.partitions,{pitch:o.pitch,seedIds:r,geometry:an(a)});c.merged&&(a.partitions=c.partitions);const d=Array.isArray(a.openings)?a.openings:[];c.merged&&on(d,c.partitions,c.openingMoves,{coordScale:o.coordScale,cellCm:o.cellCm,gridPitch:o.gridPitch});const p=function(t,e,i){const s=new Set(t.map(t=>t.id)),o=new Map(i.map(t=>[t.fromId,t.toId]));return[...new Set(e.map(t=>o.get(t)||t).filter(t=>s.has(t)))].sort((t,e)=>t.localeCompare(e))}(c.partitions,r,c.openingMoves),u=vn(a,{rooms:e.rooms,wall_columns:e.wall_columns,partitions:c.partitions.map(t=>({...t,a:[t.a[0]*o.coordScale,t.a[1]*o.coordScale],b:[t.b[0]*o.coordScale,t.b[1]*o.coordScale]}))},a.walls,i,{...o,partitionIds:p});return u.partitionsReconciled&&(u.walls.length?a.walls=u.walls:delete a.walls,u.partitions.length?a.partitions=u.partitions:delete a.partitions,u.openings.length?a.openings=u.openings:delete a.openings),{space:a,report:{partitionsMerged:c.merged,partitionsReconciled:u.partitionsReconciled,openingsRehosted:u.openingsRehosted,changed:JSON.stringify(a)!==h}}}const qd=t=>void 0===t?t:JSON.parse(JSON.stringify(t)),Kd=(t,e)=>!!t&&"object"==typeof t&&Object.prototype.hasOwnProperty.call(t,e);function Vd(t,e){const i=e?new Set(e):null;return(t||[]).filter(t=>"string"==typeof t?.id&&(!i||i.has(t.id))).map(t=>{const e=t.vacuum;return{markerId:t.id,roomIdPresent:Kd(t,"room_id"),...Kd(t,"room_id")?{roomId:qd(t.room_id)}:{},vacuumPresent:Kd(t,"vacuum"),segmentMapPresent:Kd(e,"segment_map"),...Kd(e,"segment_map")?{segmentMap:qd(e?.segment_map)}:{}}}).sort((t,e)=>t.markerId.localeCompare(e.markerId))}function Jd(t,e){const i=qd([...t||[]]),s=new Set;for(const t of i){if("string"!=typeof t?.id)continue;let i=!1;"delete"===e.kind?t.room_id===e.roomId&&(delete t.room_id,i=!0):t.room_id===e.dropId&&(t.room_id=e.keepId,i=!0);const o=t.vacuum?.segment_map;if(o&&"object"==typeof o&&!Array.isArray(o)){for(const t of Object.keys(o))"delete"===e.kind&&o[t]===e.roomId?(delete o[t],i=!0):"merge"===e.kind&&o[t]===e.dropId&&(o[t]=e.keepId,i=!0);"delete"===e.kind&&0===Object.keys(o).length&&(t.vacuum&&delete t.vacuum.segment_map,t.vacuum&&0===Object.keys(t.vacuum).length&&delete t.vacuum)}i&&s.add(t.id)}const o=[...s].sort((t,e)=>t.localeCompare(e));return{markers:i,before:Vd(t,o),after:Vd(i,o),changed:o.length}}const Yd="1.78.0-beta.1";bo.adopt(ra,la);const Zd=2e3,Xd=(t,e,i,s)=>{for(t.delete(e),t.set(e,i);t.size>s;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},Qd=1e3,tp=2e3,ep=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}},ip="e40dce8a0e21fa0d8552321bbcf22b164da42dda6875c015cf13dbdfe105abb4";class sp{constructor(t){this.host=t,this.languageRuntime=vd,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();if(this.host._activeWallChainId&&this.host._wallChainRedo.length){const t=this.host._activeWallChainId,e=this.host._path.map(t=>[...t]),i=[...this.host._activeWallChainPartitionIds],s=[...this.host._wallChainSegmentCms],o=[...this.host._wallChainRedo],a=o[o.length-1],n=this.host._geometryHistory.redo();if(!n)return;return this._applyGeometryState(n.after,!0)?(this.host._activeWallChainId=t,this.host._path=[...e,[...a.point]],this.host._activeWallChainPartitionIds=[...i,a.id],this.host._wallChainSegmentCms=[...s,a.cm],this.host._wallChainRedo=o.slice(0,-1),this._clearPlanSnapHover(),void this.host._showToast(this.host._t("history.redone",{name:n.name}))):void this.host._geometryHistory.clear()}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,i=this.host._spaceModel();if(!t||!e||!i)return;const s=Mt(t.cm);if(null==s)return void this._showPhysicalRange("column"===t.kind?De:100,"column"===t.kind?1:0);const o=this.host._imperial?2.54*s:s,a="column"===t.kind?De:100,n="column"===t.kind?1:0;if(!Number.isFinite(o)||o<n||o>a)return void this._showPhysicalRange(a,n);if("column"===t.kind){const e=i.wall_columns.find(e=>e.id===t.id);if(!e)return;const s=Mt(t.angle||"0");if("circle"!==t.shape&&(null==s||s<0||s>=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:s};if(i.wall_columns.some(e=>e.id!==t.id&&Le(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 i=(e.partitions||[]).find(e=>e.id===t.id);if(i&&0===o&&Te(e.openings,{kind:"partition",id:t.id}))return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"));i&&(i.cm=o)}else if("column"===t.kind){const i=(e.wall_columns||[]).find(e=>e.id===t.id);i&&(i.cm=Re(o),i.shape="circle"===t.shape?"circle":"square","square"===i.shape?i.angle=Mt(t.angle||"0"):delete i.angle)}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;const i=this._geometrySnapshot();if("partition"===t.kind){const i=(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(i.length)return void(this.host._partitionDeleteDialog={id:t.id,openings:i.map(t=>JSON.parse(JSON.stringify(t)))})}const s="partition"===t.kind?"partitions":"wall_columns";e[s]=(e[s]||[]).filter(e=>e.id!==t.id),e[s].length||delete e[s],this.host._activeWallChainPartitionIds.includes(t.id)&&this._cancelPath(),this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),i)},this._confirmPartitionDelete=()=>{const t=this.host._partitionDeleteDialog,e=this.host._curSpaceCfg;if(!t||!e)return;const i=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"),i)},this._furnShiftListener=t=>{if("Shift"!==t.key)return;const e=this.host._furnPreviewInput;if(!e)return;const i="keydown"===t.type;e.free!==i&&(this.host._furnPreviewInput={...e,free:i},this.host.requestUpdate())},this._furnShiftAttached=!1,this._confirmRoomDelete=t=>{const e=this.host._roomDeleteDialog,i=this.host._curSpaceCfg,s=this.host._spaceModel();if(!e||!i||!s)return;const o=s.rooms.find(t=>t.id===e.roomId);if(!o)return void(this.host._roomDeleteDialog=null);const a=this.host._openCuts(),n=od(G(s.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd).filter(t=>t.roomId===o.id),s.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&&(i.partitions||[]).length+r>tp)return void this.host._showToast(this.host._t("toast.physical_limit"));const l=this._geometrySnapshot(),h=Jd(this.host._serverCfg?.markers||[],{kind:"delete",roomId:e.roomId});l&&h.changed&&(l.roomReferences=h.before);const c=Fe(s.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd);if(t){i.partitions||=[];const t=new Map,e=new Map,s=t=>{const e=(i.wall_segments||[]).find(e=>{const i=[Number(e.a?.[0])*Qd,Number(e.a?.[1])*Qd],s=[Number(e.b?.[0])*Qd,Number(e.b?.[1])*Qd];return this._samePt(t.a,i)&&this._samePt(t.b,s)||this._samePt(t.a,s)&&this._samePt(t.b,i)});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?i.partitions.find(t=>t.id===a.reusePartitionId):e.get(a.interval.key);n||(n={id:s(a.interval)||`partition-room-${o}-${e.size}`,a:[a.interval.a[0]/Qd,a.interval.a[1]/Qd],b:[a.interval.b[0]/Qd,a.interval.b[1]/Qd],cm:a.interval.cm},i.partitions.push(n),e.set(a.interval.key,n)),t.set(a.interval.key,n)}for(const e of i.openings||[]){const i=n.openingIntervals.get(e.id),s=i?t.get(i):null,o=this.host._openingsR.find(t=>t.id===e.id);if(!s||!o)continue;const a={a:[s.a[0]*Qd,s.a[1]*Qd],b:[s.b[0]*Qd,s.b[1]*Qd]};e.host={kind:"partition",id:s.id,t:ad([o.rx,o.ry],a)}}}else if(n.removeOpeningIds.length){const t=new Set(n.removeOpeningIds);i.openings=(i.openings||[]).filter(e=>!t.has(e.id)),i.openings.length||delete i.openings}i.rooms=i.rooms.filter(t=>t.id!==o.id),h.changed&&this.host._serverCfg&&(this.host._serverCfg.markers=h.markers),this.host._cfgEpoch++;const d=this.host._normalizeWalls(c,this.host._openCuts());d.length?i.walls=d:delete i.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 i=["on_plan","available","hidden","readd"],s="ArrowRight"===t.key?1:-1,o=(i.indexOf(e.tab)+s+i.length)%i.length;this.host._deviceInbox={...e,tab:i[o],limit:100,onlyNew:!1},t.preventDefault()},this._keepClosedAsPartitions=()=>{this.host._wallFaceBatch?this._decideWallFace(!1):this.host._contourClosed&&!this.host._pendingSplit&&this.host._curSpaceCfg&&this._finalizeWallChainPartitions(this.host._activeWallChainPartitionIds)&&(this.host._roomDialog=!1,this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host.requestUpdate())},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,glowRadiusInput:String(e),bgColor:Be(this.host._settings,{bgColor:null})||null,northDeg:Oe(this.host._settings,{}),northDegInput:null===Oe(this.host._settings,{})?"":String(Oe(this.host._settings,{})),bgMode:Ae(this.host._settings,{}),sunRays:Ee(this.host._settings,{}),sunRayOrigin:Ne(this.host._settings),radarShowLive:!1!==this.host._settings.radar?.show_live,showRoomTooltip:ze(this.host._settings),zigbeeTopology:Ct(this.host._settings),busy:!1},function(t,e){u(t,"settings",Ir(e))}(this.host,this.host._settingsDialog)},this._openSupportDialog=()=>{this.host._norm&&this.host._canEdit&&(clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this._supportPreviewGeneration+=1,this.host._supportDialog={draftId:wd("draft"),idempotencyKey:wd("report"),submissionFingerprint:"",contact:"",message:"",attach:!1,status:"idle",preview:null,rawOpen:!1,errorCode:"",reportId:""})},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:He).map(t=>({...t}));this.host._rulesDialog={rules:e,test:"",busy:!1}},this._discoveryPreviewMemo=null,this._decorImages=new Id(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)}),this._radarSetup=new pc({hass:()=>t.hass,requestUpdate:()=>t.requestUpdate(),t:(e,i)=>t._t(e,i),configFromDraft:Na,apply:e=>{t._markerDialog&&(t._markerDialog={...t._markerDialog,radar:e,radarEligible:!0,radarTouched:!0,radarRemove:!1})},confirmDiscard:()=>t._confirmDanger((t=>({key:"discard-radar-setup",kind:"warning",title:t("radar.discard_setup_title"),message:t("radar.discard_setup"),confirmLabel:t("btn.close"),cancelLabel:t("btn.cancel")}))(e=>t._t(e)))}),this.optimizePlans=new uc({dialog:()=>t._alignDialog,setDialog:e=>{t._alignDialog=e},t:(e,i)=>t._t(e,i),hass:()=>t.hass,config:()=>t._serverCfg,planReady:()=>!!t._norm,layout:()=>t._layout,integrationVersion:()=>t._haIntegrationVersion,cardVersion:()=>We(Yd),requestUpdate:()=>t.requestUpdate(),showToast:e=>t._showToast(e),errorText:e=>t._errText(e),checkGeometry:e=>t._checkOptimizeGeometry(e),referenceContext:t=>this._optimizeReferenceContext(t),showMigrationBlocked:t=>this._showWallModelMigrationBlocked(t),clearGeometryGesture:()=>this._clearGeometryGesture(),commit:(e,i)=>pr(t,e,i),reloadAfterConflict:()=>Promise.all([t._reloadConfigOnly(!0),t._reloadLayoutOnly()])}),t._editorSecondary=new _d({root:()=>t.renderRoot,requestUpdate:()=>t.requestUpdate(),updateComplete:()=>t.updateComplete,clearTip:()=>{t._tip=null}}),t._resize=new sh}_routeLiveEditorUpdate(t,e){const i=Kr(this.host,t,e);return!i&&this.host._resize.preview&&(this._resizeBaseFrameStable=!1),i}_commitLiveEditor(){!function(t){const e=t,i=jr(t);i.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(i.raf),i.raf=0,Yr(i);const s=e.renderRoot?.querySelector("[data-hp-live-editor]");s&&Lt(d,s);const o=e.renderRoot?.querySelector("[data-hp-live-editor-html]");if(o){const t=e._viewOr(e._baseVb());Lt(e._renderLiveEditorMeasurements(t),o)}Ur(i,i.requestedRevision)}(this.host)}_disposeLiveEditor(){this._radarSetup.reset(),function(t){Or(t);const e=Br.get(t);e&&(e.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e.raf),Yr(e),Ur(e,e.requestedRevision),Br.delete(t))}(this.host)}_cancelRadarSetup(){this._radarSetup.interrupt()}async _whenLiveEditorSettled(){await this.host.updateComplete,await function(t){const e=Br.get(t);if(!e||!e.raf||e.paintedRevision>=e.requestedRevision)return Promise.resolve();const i=e.requestedRevision;return new Promise(t=>e.waiters.push({revision:i,resolve:t}))}(this.host)}_queuePointerMove(t,e){Er(this.host,t,e)}_flushPointerMove(t){Ar(this.host,t)}_cancelPointerMove(t){Or(this.host,t)}_help(t){const e=`${t}.aria`,i=l(this.host.hass,this.host._config?.language);return Ge(i,t)&&Ge(i,e)?p`<hp-help data-help-key=${t}
|
||
.text=${Wt(i,t)} .ariaLabel=${Wt(i,e)}></hp-help>`:d}_setMode(t,e=!0){t!==this.host._mode&&this.host._cancelDangerConfirm(),this.host._endTabDrag(),this._clearFurniturePreview(),this.host._pendingNavMode=null;const i=this.host._spaceModel();if(!i)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),i=this.host._modeTransitionTargetZoom,s=this.host._modeTransitionTargetCenterX,o=this.host._modeTransitionTargetCenterY;this.host._cancelModeTransition(!1),this.host._commitViewModeAtomic(e,i,s,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 s=this.host._mode,o=this.host._effectiveProjection(),a=this.host._currentModeVisual(s),n=this.host._modeTransitionBusy,r=a&&"view"!==s&&"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=!i.bg&&"view"===t!=("view"===s),h=n&&"view"===s&&"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"===s&&"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,w:"flat"===o?e?.w: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(this.host._mode=t,"devices"===s&&"devices"!==t&&(this.host._showHidden=!1,this.host._deviceInbox=null,this.host._deviceInboxReturn=null,this.host._deviceInboxMemo=null),this.host._editorChromeMode="view"===t?s:t,"view"===t){"view"===s||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",i=null!=t.cx&&null!=t.cy&&"iso"===e?je([t.cx,t.cy],0):null;d=i?.[0]??t.cx,p=i?.[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.host._saveNav()}_primeDrawWallField(){null===this.host._drawWallField&&(this.host._drawWallField=Ue(j,this.host._imperial))}_showPhysicalRange(t=this.host._drawWallMaxCm,e=0){this.host._showToast(this.host._t("toast.physical_range",{min:Ue(e,this.host._imperial),max:Ue(t,this.host._imperial),unit:this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_mergeSpacePartitions(t,e){const i=t?.partitions||[];if(i.length<2)return 0;const s=sn(i,{pitch:A,seedIds:e,geometry:an(t)});return s.merged?(t.partitions=s.partitions,on(t.openings,t.partitions,s.openingMoves,{coordScale:Qd,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch}),s.merged):0}_finalizeWallChainPartitions(t){if(!t.length)return!0;const e=this.host._curSpaceCfg,i=this.host._spaceModel(),s=this._geometrySnapshot();if(!e||!i||!s)return!1;const o=t.map(t=>Mh(e,t)).find(Boolean)||null,a={path:this.host._path.map(t=>[...t]),chainId:this.host._activeWallChainId,ids:[...this.host._activeWallChainPartitionIds],cms:[...this.host._wallChainSegmentCms],redo:this.host._wallChainRedo.map(t=>({...t,point:[...t.point]})),closingCm:this.host._closingWallCm};let n;try{n=Ud(e,i,this.host._openCuts(),t,{pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Qd})}catch{return this.host._showToast(this.host._t("toast.geometry_unsafe")),!1}if(!n.report.changed)return!0;const r=this.host._serverCfg,l=r?.spaces?.findIndex(t=>t.id===s.spaceId)??-1;if(l<0)return!1;r.spaces[l]=n.space;const h=function(t,e,i,s){const{host:o}=t,a=o._serverCfg,n=()=>t._commitPhysicalGeometry(e,i,[],!1);if(!i||!a||!s||10!==Number(a.model_version||0))return n();let r;try{r=ir(a).config}catch(e){return t._clearGeometryGesture(),t._restoreGeometryStateLocal(i),t._showWallModelMigrationBlocked(e),!1}const l=r.spaces.find(t=>t.id===i.spaceId),h=JSON.parse(JSON.stringify(a));if(!l||!t._restoreGeometryStateInConfig(h,i))return n();const c=h.spaces.find(t=>t.id===i.spaceId),d=Ch(l,s),p=Ch(c,s);if(!d||!p)return n();const u={...r,spaces:[d.space]},_={...h,spaces:[p.space]};let m=null,g=!1;try{const t=o._path.length>=2?o._path.map(t=>[t[0]/Sh,t[1]/Sh]):[];g=Fn(l)<=Fn(i,t)&&o._checkSpacePhysicalGeometry(u,i.spaceId,t=>{m=t}).ok}catch{g=!1}if(!g)return Ph(t,i);const f=t._junctionLimitsIntroduced(u,_,i.spaceId,m,d.roomIds);if(f.length)return t._clearGeometryGesture(),t._restoreGeometryStateLocal(i),o._showToast(t._junctionLimitLabel(f[0])),!1;or(a,r);const b=a.spaces.find(t=>t.id===i.spaceId),v=o._pendingPhysicalWrites.get(i.spaceId);return o._pendingPhysicalWrites.set(i.spaceId,{before:v?.before||i,fingerprint:ee(b)}),t._saveConfig(),!0}(this,this.host._t("history.wall_segment"),s,o);return!!h||(this.host._path=a.path,this.host._activeWallChainId=a.chainId,this.host._activeWallChainPartitionIds=a.ids,this.host._wallChainSegmentCms=a.cms,this.host._wallChainRedo=a.redo,this.host._closingWallCm=a.closingCm,!1)}_finishWallChain(){return!("draw"===this.host._tool&&!this.host._wallFaceBatch&&!this.host._roomDialog)||!!this._finalizeWallChainPartitions(this.host._activeWallChainPartitionIds)&&(this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],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,"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 i="partition"===t?(e.partitions||[]).length>=tp:(e.wall_columns||[]).length>=500;return i&&this.host._showToast(this.host._t("toast.physical_limit")),i}_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[qe(Ke(t[0],e)),qe(Ke(t[1],e))]}_snapDrawPoint(t,e=!1){const i=this.host._path[this.host._path.length-1],s=e&&i?Ve(i,t,this.host._gridPitch,fo):t;return this._snap(s)}_planSnapOpeningCuts(t,e){if(!this.host._openingsR.length)return[];const i=this.host._openingWallIndexFor(t,e).value,s=[];for(const e of this.host._roomWallOpeningInputs(this.host._openingsR,t)){const t=Z(i,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;s.push([e.x-a,e.y-n,e.x+a,e.y+n])}return s}_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,t.rooms.length,t.partitions.length].join("|");if(this.host._planSnapGeometryCache?.key===e)return this.host._planSnapGeometryCache;const i=this.host._openCuts(),s=xc({space:t,roomCuts:this._planSnapOpeningCuts(t,i),partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this.host._gridPitch});return this.host._planSnapGeometryCache={key:e,value:s},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,t.rooms.length,t.partitions.length].join("|");if(this.host._hiddenWallDiagnosticCache?.key===e)return this.host._hiddenWallDiagnosticCache;const i=kc({space:t,epsilon:2e-4*this.host._gridPitch});return this.host._hiddenWallDiagnosticCache={key:e,value:i},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,t.rooms.length,t.partitions.length].join("|");if(this.host._planStructuralGeometryCache?.key===e)return this.host._planStructuralGeometryCache;const i=xc({space:t,epsilon:2e-4*this.host._gridPitch});return this.host._planStructuralGeometryCache={key:e,value:i},this.host._planStructuralGeometryCache}_planSnapContextKey(t){const e=this.host._path[0],i=this.host._path[this.host._path.length-1];return[t,this.host._tool,this.host._path.length,e?`${e[0]},${e[1]}`:"",i?`${i[0]},${i[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const i=this._planSnapGeometrySnapshot(),s=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=this.host._path.length>1?this.host._path.slice(1):s?[s]:[],n={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this.host._gridPitch,excludePoints:a,extraEndpoints:o,epsilon:2e-4*this.host._gridPitch},r=e&&s?Dc(i.value,t,{...n,anchor:s}):function(t,e,i){if(!(mc(e)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??_c,o=i.excludePoints||[],a=Pc(Sc(t,e,i),i.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=ge([e[0],e[1]],t);if(r>i.tolerance)continue;const l=Ic(a,e,i.gridStep);!Mc(l,o,s)&&Cc(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:[]}}(i.value,t,n),l="resolved"===r.kind?r.candidate:null,h=l?[...l.point]:this._snapDrawPoint(t,e),c=s?Je(s,h):h;return{point:c,candidate:l&&nt(c,l.point)?l:null,conflicts:"ambiguous"===r.kind?r.conflicts:[],ambiguous:"ambiguous"===r.kind,contextKey:this._planSnapContextKey(i.key)}}_clearPlanSnapHover(t=!0){this.host._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this.host._cursorPt=null)}_samePt(t,e){return nt(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,i=e=>"string"==typeof e&&e.length>=1&&e.length<=64&&!t.has(e),s=e=>(t.add(e),!0),o=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=ke);if(Array.isArray(e.partitions)&&(e.partitions=e.partitions.filter(t=>t&&i(t.id)&&o(t.a)&&o(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&s(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&&i(t.id)&&o(t.center)&&s(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:Re(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:Ye(t.angle)}})),e.wall_columns.length||delete e.wall_columns),Array.isArray(e.walls)){const t=Ze($t({spaces:[e]}),e.id),i=t?Xe(e,t,Qd,.02*_t).contour.map(t=>t.map(t=>t/Qd)):et(e.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);e.walls=mt(e.walls,e.rooms||[],A,1,i),e.walls.length||delete e.walls}}}_rollbackRejectedPhysicalWrites(t){if(!this.host._serverCfg||!t.length)return!1;let e=!1;for(const[i]of t){const t=this.host._pendingPhysicalWrites.get(i);t&&(e=this._restoreGeometryStateInConfig(this.host._serverCfg,t.before)||e,this.host._pendingPhysicalWrites.delete(i))}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._adoption.refreshConfigFingerprint(),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),Qe(t)}_writeConfig(t=null){this.host._writesPending++,this.host._writeChain=ti(this.host._writeChain,async()=>{if(!this.host._serverCfg)return;const e=xt(this.host._serverCfg),i=this._prepareConfigCandidate(this.host._serverCfg),s=xt(i);t&&e===t.attemptedFingerprint&&Object.assign(t,{revision:this.host._cfgRev,attempted:i,attemptedFingerprint:s});const o=[...this.host._pendingPhysicalWrites.entries()];for(const[t,e]of o){const s=i.spaces.find(e=>e.id===t),o=ee(s);if(o===e.fingerprint)continue;let a=!1;try{a=this.host._checkSpacePhysicalGeometry(i,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}this.host._adoption.stageConfigCandidate(i);try{await this.host._sendConfigCandidate(i)}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 i=t?.spaces?.find(t=>t.id===e);if(!i)return null;const s=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!==i[t]&&(o[t]=i[t]);return{spaceId:e,rooms:s(i.rooms||[]),...Array.isArray(i.openings)?{openings:s(i.openings)}:{},...Array.isArray(i.walls)?{walls:s(i.walls)}:{},...Array.isArray(i.wall_segments)?{wall_segments:s(i.wall_segments)}:{},...Array.isArray(i.open_spans)?{open_spans:s(i.open_spans)}:{},...Array.isArray(i.partitions)?{partitions:s(i.partitions)}:{},...Array.isArray(i.wall_columns)?{wall_columns:s(i.wall_columns)}:{},...Array.isArray(i.decor)?{decor:s(i.decor)}:{},plan_transform:o}}_geometrySnapshot(t=this.host._space){return this._geometrySnapshotFromConfig(this.host._serverCfg,t)}_recordGeometry(t,e){if(!e)return;const i=this._geometrySnapshot(e.spaceId);i&&JSON.stringify(e)!==JSON.stringify(i)&&(e.wallChainSeedIds&&(i.wallChainSeedIds=[...this.host._activeWallChainPartitionIds]),e.roomReferences&&(i.roomReferences=Vd(this.host._serverCfg?.markers||[],e.roomReferences.map(t=>t.markerId))),this.host._geometryHistory.push({name:t,before:e,after:i}),this.host.requestUpdate())}_restoreGeometryStateInConfig(t,e,i=!1){const s=t?.spaces?.find(t=>t.id===e.spaceId);if(!s)return!1;const o=t=>JSON.parse(JSON.stringify(t)),a=new Map((s.rooms||[]).map(t=>[t.id,t]));if(s.rooms=o(e.rooms),i)for(const t of s.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?s[t]=o(e):i&&"wall_segments"===t||delete s[t]},r=new Map((s.openings||[]).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("partitions",e.partitions),n("wall_columns",e.wall_columns),n("decor",e.decor),i)for(const t of s.openings||[]){const e=r.get(t.id);t.host||"wall"!==e?.host?.kind||(t.host=o(e.host))}for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete s[t];return Object.assign(s,o(e.plan_transform||{})),e.roomReferences&&(t.markers||=[],function(t,e){const i=new Map((t||[]).map(t=>[t?.id,t]));for(const t of e){const e=i.get(t.markerId);e&&(t.roomIdPresent?e.room_id=qd(t.roomId):delete e.room_id,t.segmentMapPresent?(e.vacuum&&"object"==typeof e.vacuum&&!Array.isArray(e.vacuum)||(e.vacuum={}),e.vacuum.segment_map=qd(t.segmentMap)||{}):e.vacuum&&"object"==typeof e.vacuum&&!Array.isArray(e.vacuum)&&(delete e.vacuum.segment_map,t.vacuumPresent||0!==Object.keys(e.vacuum).length||delete e.vacuum))}}(t.markers,e.roomReferences)),!0}_canonicalWallChainHistoryState(t){if(this.host._activeWallChainId||!t.wallChainSeedIds?.length)return t;if(!this.host._serverCfg)return null;const e=JSON.parse(JSON.stringify(this.host._serverCfg));if(!this._restoreGeometryStateInConfig(e,t))return null;let i;try{i=ir(e).config}catch{return null}const s=i.spaces?.find(e=>e.id===t.spaceId),o=Ze($t(i),t.spaceId);if(!s||!o)return null;const a=Ud(s,o,ei(s,o,_t,Qd),t.wallChainSeedIds,{pitch:A,cellCm:Number(s.cell_cm)>0?Number(s.cell_cm):5,gridPitch:_t,coordScale:Qd}),n=i.spaces.findIndex(e=>e.id===t.spaceId);let r;i.spaces[n]=a.space;try{r=ir(i).config}catch{return null}const l=this._geometrySnapshotFromConfig(r,t.spaceId);return l?(l.wallChainSeedIds=[...t.wallChainSeedIds],t.roomReferences&&(l.roomReferences=JSON.parse(JSON.stringify(t.roomReferences))),l):null}_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 Cn?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 i of t?.wall_segments||[])i?.a&&i?.b&&e.push({id:String(i.id||""),a:i.a,b:i.b,cm:Number(i.cm)});for(const i of t?.partitions||[])i?.a&&i?.b&&e.push({id:String(i.id||""),a:i.a,b:i.b,cm:Number(i.cm)});return e}_junctionLimitViolations(t,e,i,s){const o=(t?.spaces||[]).find(t=>t?.id===e);return o?function(t,e,i,s,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=[...Jh(i),...tc(i,n,A),...ic(i,n,A)];let l=s?.multiWallNodes||null;if(!l)try{l=re(a.rooms||[],a.walls||[],[],A,n,A,1)}catch{l=null}const h=s&&"lightweight"!==s.status?s:null;let c="ok"===h?.status||"degraded-extra"===h?.status?h.roomGeom:null;const d=null===s||"lightweight"===s?.status;if(!c&&!d&&l?.nodes.length)try{const t=le(a.rooms||[],a.walls||[],[],[],A,n,A,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 i=null;try{i=he(a.rooms||[],e,a.walls||[],[],A,n,A,1,d?null:c??void 0,l)}catch{i=null}r.push(...sc(e,i,n,A))}return r}(t,e,this._limitSegmentsOf(o),i,s):[]}_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,i,s,o){const a=o?.length?new Set(o):void 0;let n;const r=(e.spaces||[]).find(t=>t?.id===i);let l="";try{l=ee(r)}catch{l=""}const h=!a&&e&&"object"==typeof e?this._junctionBaselineCache.get(e):void 0;if(h&&l&&h.fingerprint===l&&h.spaceId===i&&(n=h.violations),!n){try{const t=Number(e?.model_version||0)>=10?e:ir(e).config;n=this.host._junctionLimitViolations(t,i,a?null:void 0,a)}catch{return[]}!a&&e&&"object"==typeof e&&l&&this._junctionBaselineCache.set(e,{spaceId:i,fingerprint:l,violations:n})}let c=[],d=n;try{c=this.host._junctionLimitViolations(t,i,s,a),a&&(d=n.filter(t=>"clearance"!==t.rule||a.has(t.subject)))}catch{return[{rule:"check_failed",subject:i,actual:0,limit:0}]}return oc(c,d)}_commitPhysicalGeometry(t,e,i=[],s=!0){if(!e||!this.host._serverCfg)return!1;const o=this.host._serverCfg,a=t=>{const i=t?.spaces?.find(t=>t.id===e.spaceId);return i?{...t,spaces:[i]}:t},n=this._geometrySnapshotFromConfig(o,e.spaceId),r=o.spaces.find(t=>t.id===e.spaceId);if(!r||ee(e)===ee(r))return!1;let l,h=!1;try{h=this.host._checkSpacePhysicalGeometry(a(o),e.spaceId).ok}catch{h=!1}if(!h)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;let c=e;try{if(Number(o.model_version||0)<9){const t=JSON.parse(JSON.stringify(o));if(!this._restoreGeometryStateInConfig(t,e))throw new Cn("invalid-room",e.spaceId);const i=ir(t).config;c=this._geometrySnapshotFromConfig(i,e.spaceId)||e,c.wallChainSeedIds=e.wallChainSeedIds,c.roomReferences=e.roomReferences;const s=JSON.parse(JSON.stringify(i));if(!n||!this._restoreGeometryStateInConfig(s,n,!0))throw new Cn("invalid-room",e.spaceId);const a=i.spaces.find(t=>t.id===e.spaceId),r=s.spaces.find(t=>t.id===e.spaceId);if(!Array.isArray(n.wall_segments)&&JSON.stringify(e.rooms)===JSON.stringify(n.rooms))for(const t of r?.wall_segments||[])t.cm=rt(n.walls,t.a,t.b,A,1);const h=((t,e,i)=>{const s=new Map,o=new Map((t?.rooms||[]).map(t=>[t.id,t])),a=new Map((e||[]).map(t=>[t.id,t])),{rooms:n}=Un(i,Gn(t));for(const t of n){const e=a.get(t.id),n=o.get(t.id),r=B(e),l=(i.rooms||[]).find(e=>e.id===t.id),h=B(l),c=B(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<r.length;e++){const i=(t,e,i,s)=>{const o=[];for(let a=0;a<t.length;a++){const n=t[a],r=t[(a+1)%t.length];if(Nn(n,i,s)>Mn||Nn(r,i,s)>Mn)continue;const l=zn(n,i,s),h=zn(r,i,s);l<-1e-9||h>1+Mn||h<=l+Mn||o.push({start:l,id:e[a]})}return o.sort((t,e)=>t.start-e.start)},o=i(c,n.wall_ids,r[e],r[(e+1)%r.length]),a=i(t.poly,t.wall_ids,h[e],h[(e+1)%h.length]);if(o.length&&o.length===a.length)for(let t=0;t<o.length;t++){const e=s.get(a[t].id);if(e&&e!==o[t].id)throw new Cn("duplicate-id",a[t].id);s.set(a[t].id,o[t].id)}}}return s})(a,e.rooms,r);l=ir(s,{lineageHints:h,lineageSpaceId:e.spaceId}).config}else l=ir(o).config}catch(t){return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this._showWallModelMigrationBlocked(t),!1}let d=!1;try{const t=l.spaces.find(t=>t.id===e.spaceId),s=this.host._path.length>=2?this.host._path.map(t=>[t[0]/Qd,t[1]/Qd]):[];s.push(...i.map(t=>[t[0],t[1]])),d=Fn(t)<=Fn(c,s)&&this.host._checkSpacePhysicalGeometry(a(l),e.spaceId).ok}catch{d=!1}if(!d)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;const p=JSON.parse(JSON.stringify(o));this._restoreGeometryStateInConfig(p,e);const u=this._junctionLimitsIntroduced(l,p,e.spaceId);if(u.length)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this._junctionLimitLabel(u[0])),!1;or(o,l),s&&this._recordGeometry(t,c);const _=o.spaces.find(t=>t.id===e.spaceId),m=this.host._pendingPhysicalWrites.get(e.spaceId);return this.host._pendingPhysicalWrites.set(e.spaceId,{before:m?.before||c,fingerprint:ee(_)}),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._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],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){const i=this._canonicalWallChainHistoryState(t);if(!i||!this.host._canCommitSpace(i.spaceId))return!1;const s=this._geometrySnapshot(i.spaceId);if(!s||!this._restoreGeometryStateLocal(i))return!1;const o=this.host._serverCfg,a=ee(s)!==ee(i);if(a){let t=!1;try{const s=o?this.host._checkSpacePhysicalGeometry(o,i.spaceId):null;t=!!s?.ok||!(!e||"wall-degraded-extra"!==s?.reason)}catch{t=!1}if(!t)return this._restoreGeometryStateLocal(s),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1}let n;try{n=ir(o).config}catch(t){return this._restoreGeometryStateLocal(s),this._showWallModelMigrationBlocked(t),!1}if(a){let t=!1;try{const s=n?this.host._checkSpacePhysicalGeometry(n,i.spaceId):null;t=!!s?.ok||!(!e||"wall-degraded-extra"!==s?.reason)}catch{t=!1}if(!t)return this._restoreGeometryStateLocal(s),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;or(o,n);const a=o?.spaces.find(t=>t.id===i.spaceId),r=this.host._pendingPhysicalWrites.get(i.spaceId);this.host._pendingPhysicalWrites.set(i.spaceId,{before:r?.before||s,fingerprint:ee(a)})}else or(o,n);return this._clearGeometryGesture(),this.host._space!==i.spaceId&&(this.host._commitSpace(i.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 i=B(e);return!!i&&ii(t,i)})}_overlapRoom(t){return this.host._spaceModel()?.rooms.find(e=>{const i=B(e);return!!i&&Xt(t,i)})}_pointInRoom(t,e){return e.poly?si(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(!Dl(t))return!0;const e=t.length,i=.001;for(let s=0;s<e;s++){const o=t[s],a=t[(s+1)%e];for(let n=s+1;n<e;n++){if(n===s+1||0===s&&n===e-1)continue;const r=t[n],l=t[(n+1)%e],h=[r[0],r[1],l[0],l[1]],c=[o[0],o[1],a[0],a[1]];if(ge(o,h)<=i||ge(a,h)<=i||ge(r,c)<=i||ge(l,c)<=i)return!0}}return!1}_canAppendWallPoint(){if(null==this.host._drawWallCm)return this._showPhysicalRange(100),!1;if(this.host._path.length>=500)return this.host._showToast(this.host._t("toast.physical_limit")),!1;const t=this.host._curSpaceCfg;return!((t?.partitions||[]).length>=tp)||(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 i=t.composedPath?.()||[];if(i.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(i.some(t=>t?.classList?.contains?.("physical-hit")))return;const s=this._svgPoint(t);if("select"===this.host._tool)return void(this.host._physicalSel=null);if("resize"===this.host._tool){if(this.host._resize.dragging||i.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(s,t));return this.host._resize.selectRoom(t?.id||null),void this.host.requestUpdate()}if("delroom"===this.host._tool)return void this._deleteRoomClick(s);if("opening"===this.host._tool)return void this._openingClick(s);if("merge"===this.host._tool)return void this._mergeClick(s);if("wallthick"===this.host._tool)return void this._wallThickClick(s);if("split"===this.host._tool)return void this._splitClick(s);if("column"===this.host._tool)return void this._columnClick(s);this.host._wallRepairDiagnostic=null;const o=this._resolvePlanDrawPoint(s,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=Je(this.host._path[this.host._path.length-1],this.host._path[0])}if(!this.host._path.length){if(!t.shiftKey&&!o.candidate&&this._offerExistingWallFace(s))return;return this.host._activeWallChainId=`chain-${Date.now().toString(36)}`,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],void(this.host._path=[a])}const n=this.host._path[this.host._path.length-1];if(this._samePt(a,n))return;if(!this._canAppendWallPoint())return;const r=this.host._drawWallCm;if(null==r)return void this._showPhysicalRange(100);const l=this.host._curSpaceCfg;if(!l)return;const h=this.host._path.map(t=>[...t]),c=this.host._activeWallChainId,d=[...this.host._activeWallChainPartitionIds],p=[...this.host._wallChainSegmentCms],u=this._wallGraphSources([]),_=this._geometrySnapshot();_&&(_.wallChainSeedIds=[...d]);const m=`partition-${crypto.randomUUID?.()||`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}`;if(l.partitions||=[],l.partitions.push({id:m,a:[n[0]/Qd,n[1]/Qd],b:[a[0]/Qd,a[1]/Qd],cm:r}),this.host._path=[...this.host._path,a],this.host._wallChainSegmentCms=[...this.host._wallChainSegmentCms,r],this.host._activeWallChainPartitionIds=[...d,m],this.host._wallChainRedo=[],!Ih(this,this.host._t("history.wall_segment"),_))return this.host._activeWallChainId=c,this.host._activeWallChainPartitionIds=d,this.host._path=h,void(this.host._wallChainSegmentCms=p);this._offerWallFaces(h,h.length-1,u)}_activeWallSourceKey(t){const e=this.host._activeWallChainPartitionIds[t],i=e?this._planStructuralGeometrySnapshot().value.segments.find(t=>"partition"===t.sourceKind&&t.sourceId===e):null;return i?`static:${i.key}`:`active:${this.host._activeWallChainId||"session"}:${t}`}_wallGraphSources(t){return this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}))}_wallFaceGraph(t,e){const i=`${this.host._space}|${e}|${JSON.stringify(t)}`,s=this.host._wallFaceGraphCache.findIndex(t=>t.key===i);if(s>=0){const[t]=this.host._wallFaceGraphCache.splice(s,1);return this.host._wallFaceGraphCache.push(t),t.value}const o=td(t,e);return this.host._wallFaceGraphCache.push({key:i,value:o}),this.host._wallFaceGraphCache.length>4&&this.host._wallFaceGraphCache.shift(),o}_offerWallFaces(t,e=this.host._path.length-2,i){if(this.host._path.length<2||this.host._wallFaceBatch||this.host._roomDialog)return;const s=this.host._spaceModel();if(!s)return;const o=this._activeWallSourceKey(e),a=2e-4*this.host._gridPitch;let n,r;try{const e=i||this._wallGraphSources(t);r=this._wallGraphSources(this.host._path),n=function(t,e,i){const s=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!s.has(t.key)&&t.sourceKeys.includes(i))}(this._wallFaceGraph(e,a),this._wallFaceGraph(r,a),o)}catch{return}if(!n.length){const t=pd(r,{requiredSourceKey:o,maxDistance:X(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 s.rooms){const e=B(t);if(!t.id||!e)continue;const i=oi(e,this.host._path,.02*this.host._gridPitch);if(!i)continue;const[s,o]=i,a=te(s)>=te(o)?s:o,r=a===s?o:s,l=[...n].sort((t,e)=>Math.abs(t.area-te(r))-Math.abs(e.area-te(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._wallChainSegmentCms],activePartitionIds:[...this.host._activeWallChainPartitionIds]},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 i,s=ed(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!s){const o=pd(this._wallGraphSources([]),{point:t,maxDistance:X(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)s=o.face,i=o.proposal;else if("none"===o.kind){const i=pd(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this.host._gridPitch,epsilon:e});if("repair"===i.kind)return this.host._wallRepairDiagnostic=i.proposal,this.host._showToast(this.host._t("toast.wall_repair_too_large")),!0}}return!(!s||s.ring.length<3||this._contourSelfIntersects(s.ring)||this._overlapRoom(s.ring))&&(this._beginWallFaceBatch([{...s,existing:!i,repair:i}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),i=this.host._drawWallCm;if(null==i)return void this._showPhysicalRange(De,1);if(!this.host._curSpaceCfg||this._limitReached("column"))return;const s=this.host._spaceModel();if(!s)return;const o={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:Re(i),angle:0},a=(s.wall_columns||[]).find(t=>Le(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]/Qd,e[1]/Qd]}),this._commitPhysicalGeometry(this.host._t("history.column_add"),n)}_openPhysicalDialog(t,e){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:Ue(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:Ue(s.cm,this.host._imperial),shape:s.shape,angle:this.host._angleField("square"===s.shape?Ye(s.angle):0)})}}_physicalDown(t,e,i){const s=this.host._spaceModel();if(!s)return;t.stopPropagation(),ep(t);const o=this._svgPoint(t),a=[];for(const t of[...s.wall_columns].reverse())ai(o,ni(t,this.host._cellCm,this.host._gridPitch))&&a.push({kind:"column",id:t.id});for(const t of[...s.partitions].reverse()){const e=ri(t.a,t.b,t.cm,this.host._cellCm,this.host._gridPitch);e&&ai(o,e)&&a.push({kind:"partition",id:t.id})}a.some(t=>t.kind===e&&t.id===i)||a.unshift({kind:e,id:i});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===i));this.host._physicalPickCycle={signature:n,index:h,x:t.clientX,y:t.clientY,at:r},e=a[h].kind,i=a[h].id;const c="partition"===e?s.partitions.find(t=>t.id===i):s.wall_columns.find(t=>t.id===i);c&&(this.host._physicalSel={kind:e,id:i},this.host._physicalDrag={pid:t.pointerId,kind:e,id:i,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,i){const s="partition"===t?[e.a,e.b]:[e.center],o=s.map(t=>t[0]),a=s.map(t=>t[1]);return[Math.max(-ke*Qd-Math.min(...o),Math.min(ke*Qd-Math.max(...o),i[0])),Math.max(-ke*Qd-Math.min(...a),Math.min(ke*Qd-Math.max(...a),i[1]))]}_physicalMove(t){t.stopPropagation(),Er(this.host,"physical",()=>this._physicalMoveNow(t))}_physicalMoveNow(t){const e=this.host._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t),s="partition"===e.kind?e.base.a:e.base.center,o=this._snap([s[0]+i[0]-e.start[0],s[1]+i[1]-e.start[1]]),a=this._clampPhysicalDelta(e.kind,e.base,[o[0]-s[0],o[1]-s[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){Ar(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 i=this.host._spaceModel();if(!this.host._curSpaceCfg||!i)return;const s=this.host._curSpaceCfg;if("partition"===e.kind){const t=(s.partitions||[]).find(t=>t.id===e.id),i=e.base;if(t){const o={...i,a:[i.a[0]+e.delta[0],i.a[1]+e.delta[1]],b:[i.b[0]+e.delta[0],i.b[1]+e.delta[1]]};t.a=[o.a[0]/Qd,o.a[1]/Qd],t.b=[o.b[0]/Qd,o.b[1]/Qd];for(const t of s.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const i=H(t,[o],Qd,this.host._cellCm,this.host._gridPitch).resolved;i&&Object.assign(t,W(t,i,Qd))}}}else{const t=(s.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(i.wall_columns.some(t=>t.id!==e.id&&Le(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])/Qd,(o.center[1]+e.delta[1])/Qd])}this._commitPhysicalGeometry(this.host._t("history.physical_move"),e.before)}_registerPhysicalTap(t,e){const i=performance.now(),s=this.host._physicalLastTap?.kind===t&&this.host._physicalLastTap.id===e&&i-this.host._physicalLastTap.at<=360;this.host._physicalLastTap={kind:t,id:e,at:i},s&&(this.host._physicalLastTap=null,this._openPhysicalDialog(t,e))}_cancelPhysicalGesture(){Or(this.host,"physical"),Or(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(),ep(t);const i=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(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,baseAngle:Ye(e.angle),angle:Ye(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){t.preventDefault(),t.stopPropagation(),Er(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 i=this._svgPoint(t),s=180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,o=e.baseAngle+s-e.startAngle,a=Ye(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){Ar(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 i=this.host._spaceModel();if(!e.moved||!this.host._curSpaceCfg||!i)return;const s=i.wall_columns.find(t=>t.id===e.id);if(!s||"square"!==s.shape)return;const o={...s,angle:e.angle};if(i.wall_columns.some(t=>t.id!==e.id&&Le(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 i of e.rooms){const e=i.id?B(i):null;e&&t.push({id:i.id,poly:e,wall_ids:Array.isArray(i.wall_ids)?[...i.wall_ids]:void 0})}return i=t,s=Math.max(1e-12,1e-12*this.host._gridPitch),i.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 i=!0;for(;i&&e.length>3;){i=!1;for(let t=0;t<e.length;t++){const o=e[(t-1+e.length)%e.length],a=e[t],n=e[(t+1)%e.length],r=kl(a,o),l=kl(n,a),h=Cl(r),c=Cl(l);if(h<=s||c<=s)continue;const d=Math.abs(r[0]*l[1]-r[1]*l[0]),p=r[0]*l[0]+r[1]*l[1];if(d<=s*(h+c)&&p>0){e.splice(t,1),i=!0;break}}}return{...t,poly:e}});var i,s}_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 i of t.partitions||[])e.push({kind:"segment",a:[...i.a],b:[...i.b],half:X(i.cm,this.host._cellCm,this.host._gridPitch)/2});for(const i of t.wall_columns||[]){const t=X(i.cm,this.host._cellCm,this.host._gridPitch)/2;e.push({kind:"circle",center:[...i.center],radius:"square"===i.shape?t*Math.SQRT2:t})}return e}_rszOptsFor(t,e){const i=rt(this.host._spaceWalls,t,e,this.host._wallKeyPitch,Qd),s=this.host._spaceWalls.filter(t=>Array.isArray(t.a)&&Array.isArray(t.b)&&t.a.length>=2&&t.b.length>=2).map(t=>({wall:t,a:[t.a[0]*Qd,t.a[1]*this.host._spaceH],b:[t.b[0]*Qd,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=s.filter(i=>!!o&&("h"===o?!(Math.abs(i.a[1]-t[1])>.05*this.host._gridPitch||Math.abs(i.b[1]-t[1])>.05*this.host._gridPitch)&&Math.min(Math.max(t[0],e[0]),Math.max(i.a[0],i.b[0]))-Math.max(Math.min(t[0],e[0]),Math.min(i.a[0],i.b[0]))>.05*this.host._gridPitch:!(Math.abs(i.a[0]-t[0])>.05*this.host._gridPitch||Math.abs(i.b[0]-t[0])>.05*this.host._gridPitch)&&Math.min(Math.max(t[1],e[1]),Math.max(i.a[1],i.b[1]))-Math.max(Math.min(t[1],e[1]),Math.min(i.a[1],i.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:i>0?X(i,this.host._cellCm,this.host._gridPitch)/2:0,obstacles:this._rszObstacles(),thicknessConflict:n.size>1}}_rszResolution(t,e,i){const s=this.host._resize.snapshotIdentity||i||this._rszSnapshot(),o=`${this.host._space}|${this.host._cellCm}|${this.host._gridPitch}|${s}`,a=`${t}:${e}`;return this.host._resize.resolve(o,a,()=>{const i=[...this.host._resize.rooms||this._rszRooms()],s=i.find(e=>e.id===t),o=s?.poly?.[e]||[0,0],a=s?.poly?.[(e+1)%(s?.poly?.length||1)]||[0,0];return function(t,e,i,s,o){const{eps:a}=o,n=t.find(t=>t.id===i);if(!n||s<0||s>=(n.poly?.length||0)||n.poly.length<4||!Dl(n.poly))return{enabled:!1,reason:"invalid-geometry"};const r=n.poly[s],l=n.poly[(s+1)%n.poly.length],h=Fl(r,l,a);if(!h)return{enabled:!1,reason:"diagonal"};if(!Al(n.poly,s,h,a))return{enabled:!1,reason:"side-angle"};if(o.thicknessConflict)return{enabled:!1,reason:"thickness-conflict"};for(const t of o.obstacles||[])if(Hl(t,r,l,o))return{enabled:!1,reason:"duplicate-physical-wall"};const c=Cl(kl(l,r)),d=[],p=new Set;let u=!1,_=!1;for(const e of t)if(e.id!==i)for(let t=0;t<e.poly.length;t++){const i=e.poly[t],s=e.poly[(t+1)%e.poly.length],o=El(r,l,i,s,a);o<=a||(p.add(e.id),Nl(r,l,i,s,a)?d.push({room:e,edge:t}):o<c-a?u=!0:_=!0)}if(u)return{enabled:!1,reason:"partial-shared"};if(_)return{enabled:!1,reason:"unequal-shared"};if(p.size>1||d.length>1)return{enabled:!1,reason:"multiple-rooms"};const m={[i]:s},g=[i];if(1===d.length){const t=d[0];if(!Dl(t.room.poly))return{enabled:!1,reason:"invalid-geometry"};if(!Al(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(!(Pl([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 i=t.find(t=>t.id===e),s=m[e],o=(s-1+i.poly.length)%i.poly.length,n=(s+1)%i.poly.length,r=jl(t,e,o,1,a),l=jl(t,e,n,0,a);if(!r||!l)return{enabled:!1,reason:"partial-shared"};v.push(r,l)}const y={roomId:i,edge:s,a:[...r],b:[...l],n:Il(n.poly,s),roomIds:g,edgeByRoom:m,topology:b,movingOpeningIds:f,sideOwnership:v};if(!Zl(t,e,y,0,o))return{enabled:!1,reason:"invalid-geometry"};const w=Math.abs(Number(o.step));if(Number.isFinite(w)&&w>a){const i=[-w,w];if(!i.some(i=>Zl(t,e,y,i,o))){if(!i.some(i=>Kl(Vl(t,e,y,i),y,a)))return{enabled:!1,reason:"partial-shared"};const s={...o,obstacles:[]};return i.some(i=>Zl(t,e,y,i,s))?{enabled:!1,reason:"duplicate-physical-wall"}:e.length&&i.some(e=>Zl(t,[],y,e,o))?{enabled:!1,reason:"opening-conflict"}:{enabled:!1,reason:"invalid-geometry"}}}return{enabled:!0,plan:y}}(i,[...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,i,s,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","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,i]of Object.entries(e)){const e=r.rooms.find(e=>e.id===t);e&&(e.poly=i.map(t=>[t[0]/Qd,t[1]/l]),delete e.x,delete e.y,delete e.w,delete e.h)}for(const[t,e]of Object.entries(i)){const i=(r.openings||[]).find(e=>e.id===t);i&&(i.x=e[0]/Qd,i.y=e[1]/l)}const h=[],c=[];for(const t of s){const e=o.find(e=>e.id===t),i=r.rooms.find(e=>e.id===t);if(!e||!i?.poly)continue;const s=i.poly.map(t=>[t[0]*Qd,t[1]*l]);if(e.poly.length!==s.length)continue;const a=Array.isArray(e.wall_ids)?e.wall_ids:[];for(let t=0;t<e.poly.length;t++){h.push([e.poly[t],e.poly[(t+1)%e.poly.length]]),c.push([s[t],s[(t+1)%s.length]]);const i=a[t],o="string"==typeof i?(r.wall_segments||[]).find(t=>t.id===i):null;o&&(o.a=[s[t][0]/Qd,s[t][1]/Qd],o.b=[s[(t+1)%s.length][0]/Qd,s[(t+1)%s.length][1]/Qd])}}if(h.length&&Array.isArray(r.walls)&&r.walls.length){const t=li(r.walls,h,c,this.host._wallKeyPitch,Qd,"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=B(t);if(e&&!(e.length<2))for(let t=0;t<e.length;t++)d.push([[e[t][0]*Qd,e[t][1]*Qd],[e[(t+1)%e.length][0]*Qd,e[(t+1)%e.length][1]*Qd]])}const p=t=>JSON.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),i=u.get(e)||0;i?u.set(e,i-1):_.push(t)}if(hi(_,d,this.host._wallKeyPitch,Qd,n.walls||[]).length)return{ok:!1,reason:"wall-metadata"};const m=function(t,e,i=1e-8){const s=ah(t),o=new Set(e),a=s.flatMap(t=>{if(!o.has(String(t.id||"")))return[];const e=lh(rh(t));return e?[e]:[]});return s.flatMap(t=>{const e=String(t.id||""),s=lh(rh(t)),n=!!s&&a.some(t=>s.minX<=t.maxX+i&&s.maxX+i>=t.minX&&s.minY<=t.maxY+i&&s.maxY+i>=t.minY);return e&&(o.has(e)||n)?[e]:[]})}(r.rooms||[],s),g=hh(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=re(g.rooms,g.walls,[],A,this.host._cellCm,this.host._gridPitch,Qd)}catch{this._resizePreviewNodes=null}let b;try{const t=new Set(s),e=this.host._junctionLimitViolations(f,this.host._space,{status:"lightweight",multiWallNodes:this._resizePreviewNodes},t);b=oc(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 i=ci(e);if(!i)return;const s=`${this.host._space}|${this.host._cfgEpoch}|${t.sp.rooms.length}`;Object.defineProperty(i,"sourceFingerprint",{value:xt([t.sp,this.host._cellCm,this.host._gridPitch]),enumerable:!1});const o={key:s,value:i};Xd(this.host._wallUnionPool,s,o,8),this.host._wallUnionCache=o}_rszSpaceCandidateGeometry(t,e){if(!this.host._serverCfg)return{ok:!1,wallGeometry:null};const i={...this.host._serverCfg,spaces:this.host._serverCfg.spaces.map(i=>i.id===t?e:i)};let s=null;try{return{ok:this.host._checkSpacePhysicalGeometry(i,t,t=>{s=t}).ok,wallGeometry:s}}catch{return{ok:!1,wallGeometry:null}}}_rszSpaceCandidateRenderable(t,e){if(!this.host._serverCfg)return!1;try{const i={...this.host._serverCfg,spaces:this.host._serverCfg.spaces.map(i=>i.id===t?e:i)};return this.host._checkSpacePhysicalGeometry(i,t).ok}catch{return!1}}_rszCandidateRenderable(t){return!!t&&t.space===this.host._space&&this._rszSpaceCandidateRenderable(t.space,t.sp)}_rszEdgeDown(t,e,i){if("resize"!==this.host._tool||this.host._resize.dragging)return;this._resizeBaseFrameStable=!0,t.stopPropagation(),t.preventDefault();const s=this._rszRooms(),o=this._rszResolution(e,i);if(!o.enabled)return void this.host._showToast(this._rszReasonText(o.reason));ep(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}|${s.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:s,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(),Er(this.host,"resize",()=>this._rszMoveNow(t)))}_rszMoveNow(t){if(!this.host._resize.ownsPointer(t.pointerId))return;t.stopPropagation();const e=this._svgPoint(t),i=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,i,s,o)=>this._rszProjectPreview(t,e,i,s,o),publish:(t,e)=>this._rszAcceptPreview(t,e),measure:(t,e)=>this._rszEdgeLabels(t,e)});if("rejected"===i.kind)return i.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"===i.kind&&this.host.requestUpdate()}_rszUp(t){if(Ar(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 i=e.preview,s=this.host._serverCfg?.spaces.find(t=>t.id===i.space);s&&(s.rooms=i.sp.rooms,s.openings=i.sp.openings,Array.isArray(i.sp.walls)&&(i.sp.walls.length?s.walls=i.sp.walls:delete s.walls),Array.isArray(i.sp.wall_segments)&&(s.wall_segments=i.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){Or(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 i=`${this.host._space}|${this.host._cfgEpoch}|${t.rooms.length}`,s={key:i,value:e.restoreWallUnion};Xd(this.host._wallUnionPool,i,s,8),this.host._wallUnionCache=s}}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,i=this.host._resize.rooms){const s=i,o=[],a=t.polys[e.roomId]||s?.find(t=>t.id===e.roomId).poly;if(!a||!s)return o;const n=a.length,r=this._rszInnerSpanCms(e.roomId,a,t.polys);for(const t of function(t,e){const i=t.length;return[(e-1+i)%i,(e+1)%i]}(a,e.edge)){const e=a[t],i=a[(t+1)%n],s=r?.[t];o.push({kind:"length",x:(e[0]+i[0])/2,y:(e[1]+i[1])/2,text:null==s?this.host._fmtLen(e,i):pe(s,"mi"===this.host.hass?.config?.unit_system?.length),edge:{a:[e[0],e[1]],b:[i[0],i[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?di(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),w=this.host._t("room.settings_short"),$=y*(1.457+.66*Math.max(1,w.length)*.42);for(const i of h){const a=t.polys[i]||s.find(t=>t.id===i).poly,n=c.length&&f&&he(f.rooms,i,c,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd,null,this._resizePreviewNodes)||a,r=d.length?pi(ui(n,d))*Math.pow(this.host._cellCm/this.host._gridPitch,2)/1e4:_i(n,this.host._gridPitch,this.host._cellCm),h=mi(r,l),p=Lh({poly:a,edge:e.edgeByRoom[i],text:h,view:g,gearCenter:gi(a),gearWidthPx:$,gearHeightPx:y});o.push({kind:"area",roomId:i,x:p.anchor[0],y:p.anchor[1],text:h,placement:p})}return o}_rszInnerSpanCms(t,e,i){const s=Object.keys(i).length?Object.entries(i).map(([t,e])=>({id:t,poly:e})):this.host._spaceModel()?.rooms;if(!s?.length)return null;const o=this.host._spaceWalls;if(!o.length)return null;const a=this.host._openCuts(),n=fi(s,t,o,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd);if(!n||n.length!==e.length)return null;const r=this.host._cellCm/this.host._gridPitch;return e.map((t,i)=>bi(e,i,n)*r)}_renderResizeMeasurements(){const t=this.host._resize.liveLabels;if(!t?.length)return d;const e=t.filter(t=>"length"===t.kind),i=t.filter(t=>"area"===t.kind);return Tt`<g class="rszmeasurelayer" aria-hidden="true" pointer-events="none">
|
||
========
|
||
</hp-dialog>`}}const Md=(t,e)=>t[0]*e[1]-t[1]*e[0],Cd=(t,e)=>t[0]*e[0]+t[1]*e[1],Sd=(t,e)=>[t[0]-e[0],t[1]-e[1]],Pd=(t,e,s)=>[t[0]+e[0]*s,t[1]+e[1]*s];function Id(t,e,s){return Math.abs(Md(t,e))<=s}function Dd(t,e,s){return Math.abs(Md(Sd(t,e),s))}function Ld(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&&Id(l,[i/n,a/n],1e-6)))return[];if(Dd(e.a,t,l)>1.1*Math.max(s,o)||Dd(e.b,t,l)>1.1*Math.max(s,o))return[];return[[Cd(Sd(e.a,t),l),Cd(Sd(e.b,t),l)]]}),o).flatMap(([e,i])=>{const o=Pe({a:Pd(t,l,e),b:Pd(t,l,i),halfDepth:s});return o?[o]:[]})}function Td(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=kt(t.rooms,s.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!o||o.poly.length<3)continue;const a=Ce(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:Pd([t.x,t.y],s,-i),b:Pd([t.x,t.y],s,i)}}),a=[];for(const i of Se(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of Ld(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=X(e.cm,t.cellCm,t.gridPitch)/2;for(const t of Ld(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 Rd(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<t.length;s++){const i=t[s],o=t[(s+1)%t.length];e+=i[0]*o[1]-o[0]*i[1]}return e/2}(t)>=0?[-a/n,o/n]:[a/n,-o/n]}(t.profile.poly,e),n=Pd(s.center,a,o),r=[];for(let e=0;e<t.inner.length;e++){const o=t.inner[e],a=t.inner[(e+1)%t.inner.length],l=Sd(a,o),h=Math.hypot(l[0],l[1]);if(!(h>i&&Id(s.axis,[l[0]/h,l[1]/h],1e-6)))continue;if(Dd(o,n,s.axis)>i||Dd(a,n,s.axis)>i)continue;const c=Cd(Sd(o,n),s.axis),d=Cd(Sd(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=Pd(n,s.axis,-s.half),p=Pd(n,s.axis,s.half),u=Math.max(0,-s.half-h),_=Math.max(0,c-s.half),m=u>0?Pd(n,s.axis,h):d,g=_>0?Pd(n,s.axis,c):p,f=Cd(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 zd(t){const e=Pd(t.center,t.axis,-t.half),s=Pd(t.center,t.axis,t.half),i=Pd(t.center,t.axis,Math.min(-t.half,t.targetLo)),o=Pd(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 Fd(t,e,s,i){const o=Sd(s,e),a=Cd(o,o);if(!(a>i*i))return Math.hypot(...Sd(t,e))<=i;const n=Cd(Sd(t,e),o)/a;if(n<-i||n>1+i)return!1;const r=Pd(e,o,Math.max(0,Math.min(1,n)));return Math.hypot(...Sd(t,r))<=i}function Nd(t,e,s){let i=!1;for(let o=0,a=e.length-1;o<e.length;a=o++){if(Fd(t,e[a],e[o],s))return!0;const[n,r]=e[o],[l,h]=e[a];r>t[1]!=h>t[1]&&t[0]<(l-n)*(t[1]-r)/(h-r)+n&&(i=!i)}return i}function Ad(t,e,s,i,o,a){const n=Sd(i,s),r=Md(e,n);if(Math.abs(r)<=a)return null;const l=Sd(s,t),h=Md(l,n)/r,c=Md(l,e)/r;return h<-a||h>o+a||c<-a||c>1+a?null:Math.max(0,Math.min(o,h))}function Ed(t,e,s){const i=zd(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(Nd(t,r.body,a))return 0;for(let i=0;i<r.body.length;i++){const o=Ad(t,e,r.body[i],r.body[(i+1)%r.body.length],s,a);null!=o&&(null==n||o<n)&&(n=o)}}return n}(t.from,s,i,e.boundaries,o,e.epsilon);if(null==a)return t;const n=Pd(t.from,s,a);return{...t,to:n,label:[(t.from[0]+n[0])/2,(t.from[1]+n[1])/2],distance:a,source:"connected-face"}})}function Od(t,e){const s=function(t){const e=t.angle*Math.PI/180,s=[Math.cos(e),Math.sin(e)],i=[-s[1],s[0]],o=[t.x,t.y],a=[t.target.a,t.target.b].map(t=>Cd(Sd(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;t<i.poly.length;t++){if(!(i.kinds[t]&&i.offsets[t]>0))continue;const a=i.poly[t],n=i.poly[(t+1)%i.poly.length],r=Sd(n,a),l=Math.hypot(r[0],r[1]);if(!(l>s&&Id(e.axis,[r[0]/l,r[1]/l],1e-6)))continue;if(Dd(a,e.center,e.axis)>s||Dd(n,e.center,e.axis)>s)continue;const h=Cd(Sd(a,e.center),e.axis),c=Cd(Sd(n,e.center),e.axis),d=Math.min(h,c),p=Math.max(h,c);if(d>-e.half+s||p<e.half-s)continue;const u=Math.max(0,d>0?d:p<0?-p:0);(!o||u<o.offset-s||Math.abs(u-o.offset)<=s&&t<o.edge)&&(o={edge:t,offset:u})}return o?.edge??null}(t,s,e.epsilon);return null==i?[]:[{room:t,edge:i}]});if(i.length>2)return zd(s);if(i.length){const t=i.map(({room:t,edge:i})=>Rd(t,i,s,e.epsilon));if(t.some(t=>!t))return zd(s);const o=t;return[...o.map(t=>t.left),...o.map(t=>t.right)]}return Ed(t,e,s)}function Bd(t,e,s,i,o){const a=(n=t,JSON.parse(JSON.stringify(n)));var n;const r=[...new Set(i.filter(t=>"string"==typeof t&&t))],l={partitionsMerged:0,partitionsReconciled:0,openingsRehosted:0,changed:!1};if(!r.length||!Array.isArray(a?.partitions))return{space:a,report:l};const h=JSON.stringify(a),c=Qa(a.partitions,{pitch:o.pitch,seedIds:r,geometry:en(a)});c.merged&&(a.partitions=c.partitions);const d=Array.isArray(a.openings)?a.openings:[];c.merged&&tn(d,c.partitions,c.openingMoves,{coordScale:o.coordScale,cellCm:o.cellCm,gridPitch:o.gridPitch});const p=function(t,e,s){const i=new Set(t.map(t=>t.id)),o=new Map(s.map(t=>[t.fromId,t.toId]));return[...new Set(e.map(t=>o.get(t)||t).filter(t=>i.has(t)))].sort((t,e)=>t.localeCompare(e))}(c.partitions,r,c.openingMoves),u=gn(a,{rooms:e.rooms,wall_columns:e.wall_columns,partitions:c.partitions.map(t=>({...t,a:[t.a[0]*o.coordScale,t.a[1]*o.coordScale],b:[t.b[0]*o.coordScale,t.b[1]*o.coordScale]}))},a.walls,s,{...o,partitionIds:p});return u.partitionsReconciled&&(u.walls.length?a.walls=u.walls:delete a.walls,u.partitions.length?a.partitions=u.partitions:delete a.partitions,u.openings.length?a.openings=u.openings:delete a.openings),{space:a,report:{partitionsMerged:c.merged,partitionsReconciled:u.partitionsReconciled,openingsRehosted:u.openingsRehosted,changed:JSON.stringify(a)!==h}}}const Hd=t=>void 0===t?t:JSON.parse(JSON.stringify(t)),Wd=(t,e)=>!!t&&"object"==typeof t&&Object.prototype.hasOwnProperty.call(t,e);function jd(t,e){const s=e?new Set(e):null;return(t||[]).filter(t=>"string"==typeof t?.id&&(!s||s.has(t.id))).map(t=>{const e=t.vacuum;return{markerId:t.id,roomIdPresent:Wd(t,"room_id"),...Wd(t,"room_id")?{roomId:Hd(t.room_id)}:{},vacuumPresent:Wd(t,"vacuum"),segmentMapPresent:Wd(e,"segment_map"),...Wd(e,"segment_map")?{segmentMap:Hd(e?.segment_map)}:{}}}).sort((t,e)=>t.markerId.localeCompare(e.markerId))}function Gd(t,e){const s=Hd([...t||[]]),i=new Set;for(const t of s){if("string"!=typeof t?.id)continue;let s=!1;"delete"===e.kind?t.room_id===e.roomId&&(delete t.room_id,s=!0):t.room_id===e.dropId&&(t.room_id=e.keepId,s=!0);const o=t.vacuum?.segment_map;if(o&&"object"==typeof o&&!Array.isArray(o)){for(const t of Object.keys(o))"delete"===e.kind&&o[t]===e.roomId?(delete o[t],s=!0):"merge"===e.kind&&o[t]===e.dropId&&(o[t]=e.keepId,s=!0);"delete"===e.kind&&0===Object.keys(o).length&&(t.vacuum&&delete t.vacuum.segment_map,t.vacuum&&0===Object.keys(t.vacuum).length&&delete t.vacuum)}s&&i.add(t.id)}const o=[...i].sort((t,e)=>t.localeCompare(e));return{markers:s,before:jd(t,o),after:jd(s,o),changed:o.length}}const qd="1.78.0-beta.1";bo.adopt(aa,na);const Ud=2e3,Kd=(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)}},Vd=1e3,Jd=2e3,Zd=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}},Yd="7ec6b12023747a2dd1b234bf6f39993245f064a827fc3f6e3bf62c6817451c0c";class Xd{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();if(this.host._activeWallChainId&&this.host._wallChainRedo.length){const t=this.host._activeWallChainId,e=this.host._path.map(t=>[...t]),s=[...this.host._activeWallChainPartitionIds],i=[...this.host._wallChainSegmentCms],o=[...this.host._wallChainRedo],a=o[o.length-1],n=this.host._geometryHistory.redo();if(!n)return;return this._applyGeometryState(n.after,!0)?(this.host._activeWallChainId=t,this.host._path=[...e,[...a.point]],this.host._activeWallChainPartitionIds=[...s,a.id],this.host._wallChainSegmentCms=[...i,a.cm],this.host._wallChainRedo=o.slice(0,-1),this._clearPlanSnapHover(),void this.host._showToast(this.host._t("history.redone",{name:n.name}))):void this.host._geometryHistory.clear()}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=Mt(t.cm);if(null==i)return void this._showPhysicalRange("column"===t.kind?Ie:100,"column"===t.kind?1:0);const o=this.host._imperial?2.54*i:i,a="column"===t.kind?Ie:100,n="column"===t.kind?1:0;if(!Number.isFinite(o)||o<n||o>a)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=Mt(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&&De(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&&Le(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=Te(o),s.shape="circle"===t.shape?"circle":"square","square"===s.shape?s.angle=Mt(t.angle||"0"):delete s.angle)}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;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":"wall_columns";e[i]=(e[i]||[]).filter(e=>e.id!==t.id),e[i].length||delete e[i],this.host._activeWallChainPartitionIds.includes(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._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=td(j(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd).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>Jd)return void this.host._showToast(this.host._t("toast.physical_limit"));const l=this._geometrySnapshot(),h=Gd(this.host._serverCfg?.markers||[],{kind:"delete",roomId:e.roomId});l&&h.changed&&(l.roomReferences=h.before);const c=Re(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd);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])*Vd,Number(e.a?.[1])*Vd],i=[Number(e.b?.[0])*Vd,Number(e.b?.[1])*Vd];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]/Vd,a.interval.a[1]/Vd],b:[a.interval.b[0]/Vd,a.interval.b[1]/Vd],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]*Vd,i.a[1]*Vd],b:[i.b[0]*Vd,i.b[1]*Vd]};e.host={kind:"partition",id:i.id,t:ed([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),h.changed&&this.host._serverCfg&&(this.host._serverCfg.markers=h.markers),this.host._cfgEpoch++;const d=this.host._normalizeWalls(c,this.host._openCuts());d.length?s.walls=d: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=()=>{this.host._wallFaceBatch?this._decideWallFace(!1):this.host._contourClosed&&!this.host._pendingSplit&&this.host._curSpaceCfg&&this._finalizeWallChainPartitions(this.host._activeWallChainPartitionIds)&&(this.host._roomDialog=!1,this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host.requestUpdate())},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,glowRadiusInput:String(e),bgColor:Oe(this.host._settings,{bgColor:null})||null,northDeg:Ee(this.host._settings,{}),northDegInput:null===Ee(this.host._settings,{})?"":String(Ee(this.host._settings,{})),bgMode:Ae(this.host._settings,{}),sunRays:Ne(this.host._settings,{}),sunRayOrigin:Fe(this.host._settings),radarShowLive:!1!==this.host._settings.radar?.show_live,showRoomTooltip:ze(this.host._settings),zigbeeTopology:Ct(this.host._settings),busy:!1},function(t,e){u(t,"settings",Cr(e))}(this.host,this.host._settingsDialog)},this._openSupportDialog=()=>{this.host._norm&&this.host._canEdit&&(clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this._supportPreviewGeneration+=1,this.host._supportDialog={draftId:gd("draft"),idempotencyKey:gd("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:Be).map(t=>({...t}));this.host._rulesDialog={rules:e,test:"",busy:!1}},this._discoveryPreviewMemo=null,this._decorImages=new xd(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)}),this._radarSetup=new hc({hass:()=>t.hass,requestUpdate:()=>t.requestUpdate(),t:(e,s)=>t._t(e,s),configFromDraft:Ra,apply:e=>{t._markerDialog&&(t._markerDialog={...t._markerDialog,radar:e,radarEligible:!0,radarTouched:!0,radarRemove:!1})},confirmDiscard:()=>t._confirmDanger((t=>({key:"discard-radar-setup",kind:"warning",title:t("radar.discard_setup_title"),message:t("radar.discard_setup"),confirmLabel:t("btn.close"),cancelLabel:t("btn.cancel")}))(e=>t._t(e)))}),t._editorSecondary=new cd({root:()=>t.renderRoot,requestUpdate:()=>t.requestUpdate(),updateComplete:()=>t.updateComplete,clearTip:()=>{t._tip=null}}),t._resize=new th}_routeLiveEditorUpdate(t,e){const s=Gr(this.host,t,e);return!s&&this.host._resize.preview&&(this._resizeBaseFrameStable=!1),s}_commitLiveEditor(){!function(t){const e=t,s=Hr(t);s.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(s.raf),s.raf=0,Kr(s);const i=e.renderRoot?.querySelector("[data-hp-live-editor]");i&&Lt(d,i);const o=e.renderRoot?.querySelector("[data-hp-live-editor-html]");if(o){const t=e._viewOr(e._baseVb());Lt(e._renderLiveEditorMeasurements(t),o)}Wr(s,s.requestedRevision)}(this.host)}_disposeLiveEditor(){this._radarSetup.reset(),function(t){Nr(t);const e=Ar.get(t);e&&(e.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e.raf),Kr(e),Wr(e,e.requestedRevision),Ar.delete(t))}(this.host)}_cancelRadarSetup(){this._radarSetup.interrupt()}async _whenLiveEditorSettled(){await this.host.updateComplete,await function(t){const e=Ar.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){zr(this.host,t,e)}_flushPointerMove(t){Fr(this.host,t)}_cancelPointerMove(t){Nr(this.host,t)}_help(t){const e=`${t}.aria`,s=l(this.host.hass,this.host._config?.language);return He(s,t)&&He(s,e)?p`<hp-help data-help-key=${t}
|
||
.text=${Wt(s,t)} .ariaLabel=${Wt(s,e)}></hp-help>`:d}_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,w:"flat"===o?e?.w: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(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?We([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.host._saveNav()}_primeDrawWallField(){null===this.host._drawWallField&&(this.host._drawWallField=je(G,this.host._imperial))}_showPhysicalRange(t=this.host._drawWallMaxCm,e=0){this.host._showToast(this.host._t("toast.physical_range",{min:je(e,this.host._imperial),max:je(t,this.host._imperial),unit:this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_mergeSpacePartitions(t,e){const s=t?.partitions||[];if(s.length<2)return 0;const i=Qa(s,{pitch:E,seedIds:e,geometry:en(t)});return i.merged?(t.partitions=i.partitions,tn(t.openings,t.partitions,i.openingMoves,{coordScale:Vd,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch}),i.merged):0}_finalizeWallChainPartitions(t){if(!t.length)return!0;const e=this.host._curSpaceCfg,s=this.host._spaceModel(),i=this._geometrySnapshot();if(!e||!s||!i)return!1;const o=t.map(t=>$h(e,t)).find(Boolean)||null,a={path:this.host._path.map(t=>[...t]),chainId:this.host._activeWallChainId,ids:[...this.host._activeWallChainPartitionIds],cms:[...this.host._wallChainSegmentCms],redo:this.host._wallChainRedo.map(t=>({...t,point:[...t.point]})),closingCm:this.host._closingWallCm};let n;try{n=Bd(e,s,this.host._openCuts(),t,{pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Vd})}catch{return this.host._showToast(this.host._t("toast.geometry_unsafe")),!1}if(!n.report.changed)return!0;const r=this.host._serverCfg,l=r?.spaces?.findIndex(t=>t.id===i.spaceId)??-1;if(l<0)return!1;r.spaces[l]=n.space;const h=function(t,e,s,i){const{host:o}=t,a=o._serverCfg,n=()=>t._commitPhysicalGeometry(e,s,[],!1);if(!s||!a||!i||10!==Number(a.model_version||0))return n();let r;try{r=Qn(a).config}catch(e){return t._clearGeometryGesture(),t._restoreGeometryStateLocal(s),t._showWallModelMigrationBlocked(e),!1}const l=r.spaces.find(t=>t.id===s.spaceId),h=JSON.parse(JSON.stringify(a));if(!l||!t._restoreGeometryStateInConfig(h,s))return n();const c=h.spaces.find(t=>t.id===s.spaceId),d=kh(l,i),p=kh(c,i);if(!d||!p)return n();const u={...r,spaces:[d.space]},_={...h,spaces:[p.space]};let m=null,g=!1;try{const t=o._path.length>=2?o._path.map(t=>[t[0]/xh,t[1]/xh]):[];g=Ln(l)<=Ln(s,t)&&o._checkSpacePhysicalGeometry(u,s.spaceId,t=>{m=t}).ok}catch{g=!1}if(!g)return Mh(t,s);const f=t._junctionLimitsIntroduced(u,_,s.spaceId,m,d.roomIds);if(f.length)return t._clearGeometryGesture(),t._restoreGeometryStateLocal(s),o._showToast(t._junctionLimitLabel(f[0])),!1;er(a,r);const b=a.spaces.find(t=>t.id===s.spaceId),v=o._pendingPhysicalWrites.get(s.spaceId);return o._pendingPhysicalWrites.set(s.spaceId,{before:v?.before||s,fingerprint:ee(b)}),t._saveConfig(),!0}(this,this.host._t("history.wall_segment"),i,o);return!!h||(this.host._path=a.path,this.host._activeWallChainId=a.chainId,this.host._activeWallChainPartitionIds=a.ids,this.host._wallChainSegmentCms=a.cms,this.host._wallChainRedo=a.redo,this.host._closingWallCm=a.closingCm,!1)}_finishWallChain(){return!("draw"===this.host._tool&&!this.host._wallFaceBatch&&!this.host._roomDialog)||!!this._finalizeWallChainPartitions(this.host._activeWallChainPartitionIds)&&(this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],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,"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="partition"===t?(e.partitions||[]).length>=Jd:(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[Ge(qe(t[0],e)),Ge(qe(t[1],e))]}_snapDrawPoint(t,e=!1){const s=this.host._path[this.host._path.length-1],i=e&&s?Ue(s,t,this.host._gridPitch,fo):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=Y(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,t.rooms.length,t.partitions.length].join("|");if(this.host._planSnapGeometryCache?.key===e)return this.host._planSnapGeometryCache;const s=this.host._openCuts(),i=yc({space:t,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,t.rooms.length,t.partitions.length].join("|");if(this.host._hiddenWallDiagnosticCache?.key===e)return this.host._hiddenWallDiagnosticCache;const s=vc({space:t,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,t.rooms.length,t.partitions.length].join("|");if(this.host._planStructuralGeometryCache?.key===e)return this.host._planStructuralGeometryCache;const s=yc({space:t,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=this.host._path.length>1?this.host._path.slice(1):i?[i]:[],n={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this.host._gridPitch,excludePoints:a,extraEndpoints:o,epsilon:2e-4*this.host._gridPitch},r=e&&i?Cc(s.value,t,{...n,anchor:i}):function(t,e,s){if(!(dc(e)&&s.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const i=s.epsilon??cc,o=s.excludePoints||[],a=xc(kc(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=me([e[0],e[1]],t);if(r>s.tolerance)continue;const l=Mc(a,e,s.gridStep);!wc(l,o,i)&&$c(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,n),l="resolved"===r.kind?r.candidate:null,h=l?[...l.point]:this._snapDrawPoint(t,e),c=i?Ke(i,h):h;return{point:c,candidate:l&&nt(c,l.point)?l:null,conflicts:"ambiguous"===r.kind?r.conflicts:[],ambiguous:"ambiguous"===r.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 nt(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))<=$e);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:Te(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:Ve(t.angle)}})),e.wall_columns.length||delete e.wall_columns),Array.isArray(e.walls)){const t=Je($t({spaces:[e]}),e.id),s=t?Ze(e,t,Vd,.02*_t).contour.map(t=>t.map(t=>t/Vd)):et(e.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);e.walls=mt(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._adoption.refreshConfigFingerprint(),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),Ye(t)}_writeConfig(t=null){this.host._writesPending++,this.host._writeChain=Xe(this.host._writeChain,async()=>{if(!this.host._serverCfg)return;const e=xt(this.host._serverCfg),s=this._prepareConfigCandidate(this.host._serverCfg),i=xt(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=ee(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}this.host._adoption.stageConfigCandidate(s);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.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)&&(e.wallChainSeedIds&&(s.wallChainSeedIds=[...this.host._activeWallChainPartitionIds]),e.roomReferences&&(s.roomReferences=jd(this.host._serverCfg?.markers||[],e.roomReferences.map(t=>t.markerId))),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]));if(n("openings",e.openings),n("walls",e.walls),n("wall_segments",e.wall_segments),n("open_spans",e.open_spans),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["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||{})),e.roomReferences&&(t.markers||=[],function(t,e){const s=new Map((t||[]).map(t=>[t?.id,t]));for(const t of e){const e=s.get(t.markerId);e&&(t.roomIdPresent?e.room_id=Hd(t.roomId):delete e.room_id,t.segmentMapPresent?(e.vacuum&&"object"==typeof e.vacuum&&!Array.isArray(e.vacuum)||(e.vacuum={}),e.vacuum.segment_map=Hd(t.segmentMap)||{}):e.vacuum&&"object"==typeof e.vacuum&&!Array.isArray(e.vacuum)&&(delete e.vacuum.segment_map,t.vacuumPresent||0!==Object.keys(e.vacuum).length||delete e.vacuum))}}(t.markers,e.roomReferences)),!0}_canonicalWallChainHistoryState(t){if(this.host._activeWallChainId||!t.wallChainSeedIds?.length)return t;if(!this.host._serverCfg)return null;const e=JSON.parse(JSON.stringify(this.host._serverCfg));if(!this._restoreGeometryStateInConfig(e,t))return null;let s;try{s=Qn(e).config}catch{return null}const i=s.spaces?.find(e=>e.id===t.spaceId),o=Je($t(s),t.spaceId);if(!i||!o)return null;const a=Bd(i,o,Qe(i,o,_t,Vd),t.wallChainSeedIds,{pitch:E,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,gridPitch:_t,coordScale:Vd}),n=s.spaces.findIndex(e=>e.id===t.spaceId);let r;s.spaces[n]=a.space;try{r=Qn(s).config}catch{return null}const l=this._geometrySnapshotFromConfig(r,t.spaceId);return l?(l.wallChainSeedIds=[...t.wallChainSeedIds],t.roomReferences&&(l.roomReferences=JSON.parse(JSON.stringify(t.roomReferences))),l):null}_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 kn?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)});return e}_junctionLimitViolations(t,e,s,i){const o=(t?.spaces||[]).find(t=>t?.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=[...Uh(s),...Yh(s,n,E),...Qh(s,n,E)];let l=i?.multiWallNodes||null;if(!l)try{l=re(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=le(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=he(a.rooms||[],e,a.walls||[],[],E,n,E,1,d?null:c??void 0,l)}catch{s=null}r.push(...tc(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=ee(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)>=10?e:Qn(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 ec(c,d)}_commitPhysicalGeometry(t,e,s=[],i=!0){if(!e||!this.host._serverCfg)return!1;const o=this.host._serverCfg,a=t=>{const s=t?.spaces?.find(t=>t.id===e.spaceId);return s?{...t,spaces:[s]}:t},n=this._geometrySnapshotFromConfig(o,e.spaceId),r=o.spaces.find(t=>t.id===e.spaceId);if(!r||ee(e)===ee(r))return!1;let l,h=!1;try{h=this.host._checkSpacePhysicalGeometry(a(o),e.spaceId).ok}catch{h=!1}if(!h)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;let c=e;try{if(Number(o.model_version||0)<9){const t=JSON.parse(JSON.stringify(o));if(!this._restoreGeometryStateInConfig(t,e))throw new kn("invalid-room",e.spaceId);const s=Qn(t).config;c=this._geometrySnapshotFromConfig(s,e.spaceId)||e,c.wallChainSeedIds=e.wallChainSeedIds,c.roomReferences=e.roomReferences;const i=JSON.parse(JSON.stringify(s));if(!n||!this._restoreGeometryStateInConfig(i,n,!0))throw new kn("invalid-room",e.spaceId);const a=s.spaces.find(t=>t.id===e.spaceId),r=i.spaces.find(t=>t.id===e.spaceId);if(!Array.isArray(n.wall_segments)&&JSON.stringify(e.rooms)===JSON.stringify(n.rooms))for(const t of r?.wall_segments||[])t.cm=rt(n.walls,t.a,t.b,E,1);const h=((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}=Wn(s,Bn(t));for(const t of n){const e=a.get(t.id),n=o.get(t.id),r=B(e),l=(s.rooms||[]).find(e=>e.id===t.id),h=B(l),c=B(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<r.length;e++){const s=(t,e,s,i)=>{const o=[];for(let a=0;a<t.length;a++){const n=t[a],r=t[(a+1)%t.length];if(Rn(n,s,i)>$n||Rn(r,s,i)>$n)continue;const l=Tn(n,s,i),h=Tn(r,s,i);l<-1e-9||h>1+$n||h<=l+$n||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;t<o.length;t++){const e=i.get(a[t].id);if(e&&e!==o[t].id)throw new kn("duplicate-id",a[t].id);i.set(a[t].id,o[t].id)}}}return i})(a,e.rooms,r);l=Qn(i,{lineageHints:h,lineageSpaceId:e.spaceId}).config}else l=Qn(o).config}catch(t){return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this._showWallModelMigrationBlocked(t),!1}let d=!1;try{const t=l.spaces.find(t=>t.id===e.spaceId),i=this.host._path.length>=2?this.host._path.map(t=>[t[0]/Vd,t[1]/Vd]):[];i.push(...s.map(t=>[t[0],t[1]])),d=Ln(t)<=Ln(c,i)&&this.host._checkSpacePhysicalGeometry(a(l),e.spaceId).ok}catch{d=!1}if(!d)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;const p=JSON.parse(JSON.stringify(o));this._restoreGeometryStateInConfig(p,e);const u=this._junctionLimitsIntroduced(l,p,e.spaceId);if(u.length)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this._junctionLimitLabel(u[0])),!1;er(o,l),i&&this._recordGeometry(t,c);const _=o.spaces.find(t=>t.id===e.spaceId),m=this.host._pendingPhysicalWrites.get(e.spaceId);return this.host._pendingPhysicalWrites.set(e.spaceId,{before:m?.before||c,fingerprint:ee(_)}),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._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],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){const s=this._canonicalWallChainHistoryState(t);if(!s||!this.host._canCommitSpace(s.spaceId))return!1;const i=this._geometrySnapshot(s.spaceId);if(!i||!this._restoreGeometryStateLocal(s))return!1;const o=this.host._serverCfg,a=ee(i)!==ee(s);if(a){let t=!1;try{const i=o?this.host._checkSpacePhysicalGeometry(o,s.spaceId):null;t=!!i?.ok||!(!e||"wall-degraded-extra"!==i?.reason)}catch{t=!1}if(!t)return this._restoreGeometryStateLocal(i),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1}let n;try{n=Qn(o).config}catch(t){return this._restoreGeometryStateLocal(i),this._showWallModelMigrationBlocked(t),!1}if(a){let t=!1;try{const i=n?this.host._checkSpacePhysicalGeometry(n,s.spaceId):null;t=!!i?.ok||!(!e||"wall-degraded-extra"!==i?.reason)}catch{t=!1}if(!t)return this._restoreGeometryStateLocal(i),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;er(o,n);const a=o?.spaces.find(t=>t.id===s.spaceId),r=this.host._pendingPhysicalWrites.get(s.spaceId);this.host._pendingPhysicalWrites.set(s.spaceId,{before:r?.before||i,fingerprint:ee(a)})}else er(o,n);return this._clearGeometryGesture(),this.host._space!==s.spaceId&&(this.host._commitSpace(s.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=B(e);return!!s&&ts(t,s)})}_overlapRoom(t){return this.host._spaceModel()?.rooms.find(e=>{const s=B(e);return!!s&&Xt(t,s)})}_pointInRoom(t,e){return e.poly?es(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(!Sl(t))return!0;const e=t.length,s=.001;for(let i=0;i<e;i++){const o=t[i],a=t[(i+1)%e];for(let n=i+1;n<e;n++){if(n===i+1||0===i&&n===e-1)continue;const r=t[n],l=t[(n+1)%e],h=[r[0],r[1],l[0],l[1]],c=[o[0],o[1],a[0],a[1]];if(me(o,h)<=s||me(a,h)<=s||me(r,c)<=s||me(l,c)<=s)return!0}}return!1}_canAppendWallPoint(){if(null==this.host._drawWallCm)return this._showPhysicalRange(100),!1;if(this.host._path.length>=500)return this.host._showToast(this.host._t("toast.physical_limit")),!1;const t=this.host._curSpaceCfg;return!((t?.partitions||[]).length>=Jd)||(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=Ke(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;return this.host._activeWallChainId=`chain-${Date.now().toString(36)}`,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],void(this.host._path=[a])}const n=this.host._path[this.host._path.length-1];if(this._samePt(a,n))return;if(!this._canAppendWallPoint())return;const r=this.host._drawWallCm;if(null==r)return void this._showPhysicalRange(100);const l=this.host._curSpaceCfg;if(!l)return;const h=this.host._path.map(t=>[...t]),c=this.host._activeWallChainId,d=[...this.host._activeWallChainPartitionIds],p=[...this.host._wallChainSegmentCms],u=this._wallGraphSources([]),_=this._geometrySnapshot();_&&(_.wallChainSeedIds=[...d]);const m=`partition-${crypto.randomUUID?.()||`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}`;if(l.partitions||=[],l.partitions.push({id:m,a:[n[0]/Vd,n[1]/Vd],b:[a[0]/Vd,a[1]/Vd],cm:r}),this.host._path=[...this.host._path,a],this.host._wallChainSegmentCms=[...this.host._wallChainSegmentCms,r],this.host._activeWallChainPartitionIds=[...d,m],this.host._wallChainRedo=[],!Ch(this,this.host._t("history.wall_segment"),_))return this.host._activeWallChainId=c,this.host._activeWallChainPartitionIds=d,this.host._path=h,void(this.host._wallChainSegmentCms=p);this._offerWallFaces(h,h.length-1,u)}_activeWallSourceKey(t){const e=this.host._activeWallChainPartitionIds[t],s=e?this._planStructuralGeometrySnapshot().value.segments.find(t=>"partition"===t.sourceKind&&t.sourceId===e):null;return s?`static:${s.key}`:`active:${this.host._activeWallChainId||"session"}:${t}`}_wallGraphSources(t){return this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}))}_wallFaceGraph(t,e){const s=`${this.host._space}|${e}|${JSON.stringify(t)}`,i=this.host._wallFaceGraphCache.findIndex(t=>t.key===s);if(i>=0){const[t]=this.host._wallFaceGraphCache.splice(i,1);return this.host._wallFaceGraphCache.push(t),t.value}const o=Zc(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=ld(r,{requiredSourceKey:o,maxDistance:X(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=B(t);if(!t.id||!e)continue;const s=ss(e,this.host._path,.02*this.host._gridPitch);if(!s)continue;const[i,o]=s,a=te(i)>=te(o)?i:o,r=a===i?o:i,l=[...n].sort((t,e)=>Math.abs(t.area-te(r))-Math.abs(e.area-te(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._wallChainSegmentCms],activePartitionIds:[...this.host._activeWallChainPartitionIds]},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=Yc(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!i){const o=ld(this._wallGraphSources([]),{point:t,maxDistance:X(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=ld(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(Ie,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:Te(s),angle:0},a=(i.wall_columns||[]).find(t=>De(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]/Vd,e[1]/Vd]}),this._commitPhysicalGeometry(this.host._t("history.column_add"),n)}_openPhysicalDialog(t,e){const s=this.host._spaceModel();if(s)if("partition"===t){const i=s.partitions.find(t=>t.id===e);i&&(this.host._physicalDialog={kind:t,id:e,cm:je(i.cm,this.host._imperial),length:this.host._fmtLen(i.a,i.b)})}else if("column"===t){const i=s.wall_columns.find(t=>t.id===e);i&&(this.host._physicalDialog={kind:t,id:e,cm:je(i.cm,this.host._imperial),shape:i.shape,angle:this.host._angleField("square"===i.shape?Ve(i.angle):0)})}}_physicalDown(t,e,s){const i=this.host._spaceModel();if(!i)return;t.stopPropagation(),Zd(t);const o=this._svgPoint(t),a=[];for(const t of[...i.wall_columns].reverse())is(o,os(t,this.host._cellCm,this.host._gridPitch))&&a.push({kind:"column",id:t.id});for(const t of[...i.partitions].reverse()){const e=as(t.a,t.b,t.cm,this.host._cellCm,this.host._gridPitch);e&&is(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(-$e*Vd-Math.min(...o),Math.min($e*Vd-Math.max(...o),s[0])),Math.max(-$e*Vd-Math.min(...a),Math.min($e*Vd-Math.max(...a),s[1]))]}_physicalMove(t){t.stopPropagation(),zr(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){Fr(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]/Vd,o.a[1]/Vd],t.b=[o.b[0]/Vd,o.b[1]/Vd];for(const t of i.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const s=H(t,[o],Vd,this.host._cellCm,this.host._gridPitch).resolved;s&&Object.assign(t,W(t,s,Vd))}}}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&&De(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])/Vd,(o.center[1]+e.delta[1])/Vd])}this._commitPhysicalGeometry(this.host._t("history.physical_move"),e.before)}_registerPhysicalTap(t,e){const s=performance.now(),i=this.host._physicalLastTap?.kind===t&&this.host._physicalLastTap.id===e&&s-this.host._physicalLastTap.at<=360;this.host._physicalLastTap={kind:t,id:e,at:s},i&&(this.host._physicalLastTap=null,this._openPhysicalDialog(t,e))}_cancelPhysicalGesture(){Nr(this.host,"physical"),Nr(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(),Zd(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:Ve(e.angle),angle:Ve(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){t.preventDefault(),t.stopPropagation(),zr(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=Ve(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){Fr(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&&De(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?B(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;t<e.length;t++){const o=e[(t-1+e.length)%e.length],a=e[t],n=e[(t+1)%e.length],r=yl(a,o),l=yl(n,a),h=kl(r),c=kl(l);if(h<=i||c<=i)continue;const d=Math.abs(r[0]*l[1]-r[1]*l[0]),p=r[0]*l[0]+r[1]*l[1];if(d<=i*(h+c)&&p>0){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:X(s.cm,this.host._cellCm,this.host._gridPitch)/2});for(const s of t.wall_columns||[]){const t=X(s.cm,this.host._cellCm,this.host._gridPitch)/2;e.push({kind:"circle",center:[...s.center],radius:"square"===s.shape?t*Math.SQRT2:t})}return e}_rszOptsFor(t,e){const s=rt(this.host._spaceWalls,t,e,this.host._wallKeyPitch,Vd),i=this.host._spaceWalls.filter(t=>Array.isArray(t.a)&&Array.isArray(t.b)&&t.a.length>=2&&t.b.length>=2).map(t=>({wall:t,a:[t.a[0]*Vd,t.a[1]*this.host._spaceH],b:[t.b[0]*Vd,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?X(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||!Sl(n.poly))return{enabled:!1,reason:"invalid-geometry"};const r=n.poly[i],l=n.poly[(i+1)%n.poly.length],h=Ll(r,l,a);if(!h)return{enabled:!1,reason:"diagonal"};if(!Fl(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(El(t,r,l,o))return{enabled:!1,reason:"duplicate-physical-wall"};const c=kl(yl(l,r)),d=[],p=new Set;let u=!1,_=!1;for(const e of t)if(e.id!==s)for(let t=0;t<e.poly.length;t++){const s=e.poly[t],i=e.poly[(t+1)%e.poly.length],o=zl(r,l,s,i,a);o<=a||(p.add(e.id),Rl(r,l,s,i,a)?d.push({room:e,edge:t}):o<c-a?u=!0:_=!0)}if(u)return{enabled:!1,reason:"partial-shared"};if(_)return{enabled:!1,reason:"unequal-shared"};if(p.size>1||d.length>1)return{enabled:!1,reason:"multiple-rooms"};const m={[s]:i},g=[s];if(1===d.length){const t=d[0];if(!Sl(t.room.poly))return{enabled:!1,reason:"invalid-geometry"};if(!Fl(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(!(Ml([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=Hl(t,e,o,1,a),l=Hl(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:Cl(n.poly,i),roomIds:g,edgeByRoom:m,topology:b,movingOpeningIds:f,sideOwnership:v};if(!Vl(t,e,y,0,o))return{enabled:!1,reason:"invalid-geometry"};const w=Math.abs(Number(o.step));if(Number.isFinite(w)&&w>a){const s=[-w,w];if(!s.some(s=>Vl(t,e,y,s,o))){if(!s.some(s=>Gl(ql(t,e,y,s),y,a)))return{enabled:!1,reason:"partial-shared"};const i={...o,obstacles:[]};return s.some(s=>Vl(t,e,y,s,i))?{enabled:!1,reason:"duplicate-physical-wall"}:e.length&&s.some(e=>Vl(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","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]/Vd,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]/Vd,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]*Vd,t[1]*l]);if(e.poly.length!==i.length)continue;const a=Array.isArray(e.wall_ids)?e.wall_ids:[];for(let t=0;t<e.poly.length;t++){h.push([e.poly[t],e.poly[(t+1)%e.poly.length]]),c.push([i[t],i[(t+1)%i.length]]);const s=a[t],o="string"==typeof s?(r.wall_segments||[]).find(t=>t.id===s):null;o&&(o.a=[i[t][0]/Vd,i[t][1]/Vd],o.b=[i[(t+1)%i.length][0]/Vd,i[(t+1)%i.length][1]/Vd])}}if(h.length&&Array.isArray(r.walls)&&r.walls.length){const t=ns(r.walls,h,c,this.host._wallKeyPitch,Vd,"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=B(t);if(e&&!(e.length<2))for(let t=0;t<e.length;t++)d.push([[e[t][0]*Vd,e[t][1]*Vd],[e[(t+1)%e.length][0]*Vd,e[(t+1)%e.length][1]*Vd]])}const p=t=>JSON.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(rs(_,d,this.host._wallKeyPitch,Vd,n.walls||[]).length)return{ok:!1,reason:"wall-metadata"};const m=function(t,e,s=1e-8){const i=sh(t),o=new Set(e),a=i.flatMap(t=>{if(!o.has(String(t.id||"")))return[];const e=ah(oh(t));return e?[e]:[]});return i.flatMap(t=>{const e=String(t.id||""),i=ah(oh(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=nh(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=re(g.rooms,g.walls,[],E,this.host._cellCm,this.host._gridPitch,Vd)}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=ec(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=ls(e);if(!s)return;const i=`${this.host._space}|${this.host._cfgEpoch}|${t.sp.rooms.length}`;Object.defineProperty(s,"sourceFingerprint",{value:xt([t.sp,this.host._cellCm,this.host._gridPitch]),enumerable:!1});const o={key:i,value:s};Kd(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));Zd(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(),zr(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(Fr(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){Nr(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};Kd(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):pe(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?hs(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),w=this.host._t("room.settings_short"),$=y*(1.457+.66*Math.max(1,w.length)*.42);for(const s of h){const a=t.polys[s]||i.find(t=>t.id===s).poly,n=c.length&&f&&he(f.rooms,s,c,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd,null,this._resizePreviewNodes)||a,r=d.length?cs(ds(n,d))*Math.pow(this.host._cellCm/this.host._gridPitch,2)/1e4:ps(n,this.host._gridPitch,this.host._cellCm),h=us(r,l),p=Ph({poly:a,edge:e.edgeByRoom[s],text:h,view:g,gearCenter:_s(a),gearWidthPx:$,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=ms(i,t,o,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd);if(!n||n.length!==e.length)return null;const r=this.host._cellCm/this.host._gridPitch;return e.map((t,s)=>gs(e,s,n)*r)}_renderResizeMeasurements(){const t=this.host._resize.liveLabels;if(!t?.length)return d;const e=t.filter(t=>"length"===t.kind),s=t.filter(t=>"area"===t.kind);return Tt`<g class="rszmeasurelayer" aria-hidden="true" pointer-events="none">
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
${e.map((t,e)=>Tt`<g class="rszmeasuredge"
|
||
data-hp="resize-measured-edge" data-edge-index=${e}>
|
||
<line class="rszmeasurehalo" x1=${t.edge.a[0]} y1=${t.edge.a[1]}
|
||
x2=${t.edge.b[0]} y2=${t.edge.b[1]}></line>
|
||
<line class="rszmeasureink" x1=${t.edge.a[0]} y1=${t.edge.a[1]}
|
||
x2=${t.edge.b[0]} y2=${t.edge.b[1]}></line>
|
||
</g>`)}
|
||
${i.map(t=>Tt`<line class="rszleader" data-hp="resize-area-leader"
|
||
data-room=${t.roomId}
|
||
x1=${t.placement.leader.a[0]} y1=${t.placement.leader.a[1]}
|
||
x2=${t.placement.leader.b[0]} y2=${t.placement.leader.b[1]}></line>`)}
|
||
</g>`}_renderResizeLayer(t,e){const i=Math.max(.013*t.w,5),s=i/2,o=t=>t.toFixed(1),a=`M ${o(-.7*s)} 0 H ${o(.7*s)} M 0 ${o(-.22*s)} V ${o(-s)} M ${o(-.32*s)} ${o(-.6*s)} L 0 ${o(-s)} L ${o(.32*s)} ${o(-.6*s)} M 0 ${o(.22*s)} V ${o(s)} M ${o(-.32*s)} ${o(.6*s)} L 0 ${o(s)} L ${o(.32*s)} ${o(.6*s)}`,n=[],r=this._rszRooms(),l=this.host._resize.snapshotIdentity||this._rszSnapshot(),h=e?.length?new Set(e):null;for(const t of r)if(!h||h.has(t.id))for(let e=0;e<t.poly.length;e++){const s=t.poly[e],r=t.poly[(e+1)%t.poly.length];if(Math.hypot(r[0]-s[0],r[1]-s[1])<this.host._gridPitch)continue;const h=o((s[0]+r[0])/2),c=o((s[1]+r[1])/2),d=o(180*Math.atan2(r[1]-s[1],r[0]-s[0])/Math.PI),p=this._rszResolution(t.id,e,l),u=!p.enabled,_=u?this._rszReasonText(p.reason):this.host._t("title.markup_resize");n.push(Tt`<circle class="rszhandle ${u?"disabled":""}"
|
||
cx="${h}" cy="${c}" r="${o(i)}" tabindex="0" role="button"
|
||
aria-disabled="${u?"true":"false"}" aria-label="${_}"
|
||
@pointerdown=${i=>this._rszEdgeDown(i,t.id,e)}
|
||
@pointermove=${t=>this._rszMove(t)}
|
||
@pointerup=${t=>this._rszUp(t)}
|
||
@pointercancel=${t=>this._rszPointerCancel(t)}
|
||
@lostpointercapture=${t=>this._rszPointerCancel(t)}
|
||
@click=${u?t=>this._rszDisabledActivate(t,p.reason):null}
|
||
@keydown=${u?t=>this._rszDisabledKey(t,p.reason):null}>
|
||
<title>${_}</title>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</circle>`),n.push(Tt`<g class="rszicon ${u?"disabled":""}" transform="translate(${h} ${c}) rotate(${d})"><path class="rszhalo" d="${a}"></path><path class="rszink" d="${a}"></path></g>`)}return Tt`<g class="resize-layer">${n}</g>`}_partitionOpeningCuts(t=this.host._spaceModel(),e=()=>!0){if(!t)return[];const i=this.host._curSpaceCfg?.id===t.id?this.host._curSpaceCfg:null,s=vi(i,t,this.host._cellCm,this.host._gridPitch,Qd);return yi(s,e)}_decorSnapGeometry(t){const e=this.host._spaceModel();if(!e)return{points:[],segments:[]};const i=t||"",s=this.host._decorSnapCache;if(s&&s.epoch===this.host._cfgEpoch&&s.space===this.host._space&&s.height===this.host._decorH&&s.exclude===i)return s.geometry;const o=[];for(const e of this.host._decorList)if(e.id!==t)if("line"===e.kind){const t=[e.x1*Qd,e.y1*this.host._decorH],i=[e.x2*Qd,e.y2*this.host._decorH];o.push({points:[t,i,[(t[0]+i[0])/2,(t[1]+i[1])/2]],segments:[{a:t,b:i}]})}else if("text"===e.kind)o.push({points:[[e.x*Qd,e.y*this.host._decorH]],segments:[]});else{const t=this.host._decorBoxOf(e);t&&o.push(wi(t))}for(const t of e.rooms){const e=B(t);e?.length&&o.push({points:e.flatMap((t,i)=>{const s=e[(i+1)%e.length];return[t,[(t[0]+s[0])/2,(t[1]+s[1])/2]]}),segments:e.map((t,i)=>({a:t,b:e[(i+1)%e.length]}))})}const a=$i(o);return this.host._decorSnapCache={epoch:this.host._cfgEpoch,space:this.host._space,height:this.host._decorH,exclude:i,geometry:a},a}_decorSnap(t,e="mouse",i){const s=this.host._stageEl,o=this.host._viewOr(this.host._baseVb()),a="touch"===e||"pen"===e?14:8,n=s?o.w/Math.max(1,s.clientWidth)*a:this.host._gridPitch;return ki(t,this._decorSnapGeometry(i),n,t=>this._snap(t)).point}_replaceDecor(t,e){const i=this.host._curSpaceCfg;i&&(i.decor=this.host._decorList.map(i=>i.id===t?{...i,...e}:i),this.host.requestUpdate())}_cancelDecorGesture(){Or(this.host,"decor-transform"),Or(this.host,"decor-move"),Or(this.host,"backdrop");const t=this.host._decorMove?.before||this.host._dtDrag?.before||this.host._bdDrag?.before,e=t&&this.host._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(t&&e){const i=t=>JSON.parse(JSON.stringify(t));void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];Object.assign(e,i(t.plan_transform||{})),this.host._decorSnapCache=null}this.host._decorMove=null,this.host._dtDrag=null,this.host._bdDrag=null,t&&e&&"decor"===this.host._mode&&(this.host._terminalFrame=1),this.host.requestUpdate()}_decorPointerDown(t){const e=this.host._decorTool;if("mouse"===t.pointerType&&0!==t.button&&"select"!==e&&"erase"!==e)return!1;if("select"===e||"erase"===e?t.target.closest?.(".dshape"):null)return!0;if("line"===e||"rect"===e||"ellipse"===e){t.preventDefault();const i=this._decorSnap(this._svgPoint(t),t.pointerType);return this.host._decorDraft={kind:e,a:i,b:i,pid:t.pointerId},ep(t),!0}if("text"===e){const e=this._decorSnap(this._svgPoint(t),t.pointerType);return this.host._decorTextDialog={x:se(e[0]/Qd),y:se(e[1]/this.host._decorH),text:"",color:this.host._decorStyle.color,opacity:this.host._decorStyle.opacity,angle:"0",sizeCm:xi(bt,this.host._cellCm,this.host._gridPitch)},this.host._decorTextSelection={start:0,end:0},!0}if("furniture"===e||"image"===e){if("furniture"===e?!this.host._furnPalette:!this.host._decorImagePalette)return!1;t.preventDefault();const i=t.pointerType||"mouse";if("mouse"===i)return"furniture"===e?this._furnPlace(this._svgPoint(t),t.shiftKey,i):this._decorImagePlace(this._svgPoint(t),i),!0;const s=this.host._furnTouchPending;return s&&s.pid!==t.pointerId?(s.cancelled=!0,this.host._furnPreviewInput=null,!0):(this.host._furnTouchPending={pid:t.pointerId,sx:t.clientX,sy:t.clientY,pointerType:i,cancelled:!1},this.host._furnPreviewInput=null,ep(t),!0)}if("select"===e&&(this.host._decorSel=null),this.host._bdMovable){const e=this.host._bdRect,i=this._svgPoint(t),s=e.x+e.w/2,o=e.y+e.h/2,a=-Mi(e.angle)*Math.PI/180,n=i[0]-s,r=i[1]-o,l=[s+n*Math.cos(a)-r*Math.sin(a),o+n*Math.sin(a)+r*Math.cos(a)];if(l[0]>=e.x&&l[0]<=e.x+e.w&&l[1]>=e.y&&l[1]<=e.y+e.h)return t.preventDefault(),this._bdStart(t)}return!1}_decorCommitDraft(){const t=this.host._decorDraft;if(this.host._decorDraft=null,!t)return;const e=.5*this.host._gridPitch;if(!Ci(t.kind,t.a,t.b,e))return;const i=Qd,s=this.host._decorH,o=this.host._decorStyle,a=this._geometrySnapshot(),n="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),r=se;let l;if("line"===t.kind)l={id:n,kind:"line",x1:r(t.a[0]/i),y1:r(t.a[1]/s),x2:r(t.b[0]/i),y2:r(t.b[1]/s),...Si(o,!1)};else{const e=r(Math.min(t.a[0],t.b[0])/i),a=r(Math.min(t.a[1],t.b[1])/s),h=Math.abs(t.b[0]-t.a[0])/i,c=Math.abs(t.b[1]-t.a[1])/s;l={id:n,kind:t.kind,x:e,y:a,w:h,h:c,...Si(o,!0)}}this.host._curSpaceCfg.decor=[...this.host._decorList,l],this.host._decorSel=n,this._recordGeometry(this.host._t("history.decor_add"),a),this._saveConfig(),this.host.requestUpdate()}_decorShapeDown(t,e){if("decor"!==this.host._mode)return;const i=this.host._decorTool;if("text"===i){if("text"!==e.kind)return;return t.stopPropagation(),t.preventDefault(),void this._decorOpenText(e)}"select"!==i&&"erase"!==i||(t.stopPropagation(),t.preventDefault(),"erase"!==i?(this.host._decorSel=e.id,this.host._decorMove={id:e.id,start:this._svgPoint(t),orig:JSON.parse(JSON.stringify(e)),pid:t.pointerId,moved:!1,before:this._geometrySnapshot()},ep(t)):this.host._decorEraseConfirm={id:e.id,kind:e.kind})}_decorMoveUpdate(t){const e=this.host._decorMove;if(!e)return;if("furniture"===e.orig?.kind)return void this._furnMoveUpdate(t);const i=this._svgPoint(t),s=e.orig,o=("line"===s.kind?s.x1:s.x)*Qd,a=("line"===s.kind?s.y1:s.y)*this.host._decorH,n=this._decorSnap([o+(i[0]-e.start[0]),a+(i[1]-e.start[1])],t.pointerType,e.id);let r=(n[0]-o)/Qd,l=(n[1]-a)/this.host._decorH;const h=e.orig,c="line"===h.kind?Math.min(h.x1,h.x2):h.x,d="line"===h.kind?Math.min(h.y1,h.y2):h.y,p="line"===h.kind?Math.abs(h.x2-h.x1):h.w||0,u="line"===h.kind?Math.abs(h.y2-h.y1):h.h||0,_=ke;r=Math.max(-_-c,Math.min(_-c-p,r)),l=Math.max(-_-d,Math.min(_-d-u,l)),(r||l)&&(e.moved=!0);this.host._curSpaceCfg.decor=this.host._decorList.map(t=>{if(t.id!==e.id)return t;const i=e.orig;return"line"===t.kind?{...t,x1:i.x1+r,y1:i.y1+l,x2:i.x2+r,y2:i.y2+l}:{...t,x:i.x+r,y:i.y+l}}),this.host.requestUpdate()}_dmUp(){Ar(this.host,"decor-move");const t=this.host._decorMove;t?.moved&&(this._recordGeometry(this.host._t("history.decor_move"),t.before),this._saveConfig()),this.host._decorMove=null,this.host.requestUpdate()}_decorShapeDbl(t,e){"decor"===this.host._mode&&"select"===this.host._decorTool&&(t.preventDefault(),t.stopPropagation(),this.host._decorMove=null,this.host._decorSel=e.id,this._openDecorProperties(e))}_openDecorProperties(t){if("decor"!==this.host._mode||"select"!==this.host._decorTool)return;if("text"===t.kind)return void this._decorOpenText(t);if(!["line","rect","ellipse","furniture","image"].includes(t.kind))return;"image"===t.kind&&this._decorImageCatalogLoad();const e=this.host._decorResolvedStyle(t),i="line"===t.kind?t:null,s=this.host._decorBoxOf(t);this.host._decorShapeDialog={id:t.id,kind:t.kind,color:e.color,opacity:e.opacity,widthCm:e.widthCm,angle:this.host._angleField(Mi(i?Pi([i.x1*Qd,i.y1*this.host._decorH],[i.x2*Qd,i.y2*this.host._decorH]):t.angle)),...i?{lengthCm:xi(Math.hypot((i.x2-i.x1)*Qd,(i.y2-i.y1)*this.host._decorH),this.host._cellCm,this.host._gridPitch),lineStyle:"dashed"===i.line_style?"dashed":"solid"}:{},...s?{sizeWCm:xi(s.w,this.host._cellCm,this.host._gridPitch),sizeHCm:xi(s.h,this.host._cellCm,this.host._gridPitch)}:{},..."furniture"===t.kind?{symbol:t.symbol,flipH:!!t.flip_h,flipV:!!t.flip_v,sizeWField:xe(xi(s.w,this.host._cellCm,this.host._gridPitch),!!t.flip_h,this.host._imperial),sizeHField:xe(xi(s.h,this.host._cellCm,this.host._gridPitch),!!t.flip_v,this.host._imperial)}:{},..."image"===t.kind?{assetId:t.asset_id,flipH:!!t.flip_h,flipV:!!t.flip_v,sizeWField:xe(xi(s.w,this.host._cellCm,this.host._gridPitch),!!t.flip_h,this.host._imperial),sizeHField:xe(xi(s.h,this.host._cellCm,this.host._gridPitch),!!t.flip_v,this.host._imperial)}:{},..."rect"===t.kind||"ellipse"===t.kind?{fill:e.fill,fillColor:e.fillColor,fillOpacity:e.fillOpacity}:{}}}_decorOpenText(t){if("text"!==t.kind)return;let e=String(t.text??"");const i=[...e.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!yt(t[1])),s=String(t.unit??"").trim(),o="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,a=i||s?"":wt(t.entity,o),n=!(!String(t.entity??"").trim()||i||a&&!s);if(a&&!n){const t=e.indexOf("{}");e=t>=0?e.slice(0,t)+a+e.slice(t+2):`${e}${e?" ":""}${a}`}this.host._decorTextDialog={id:t.id,x:t.x,y:t.y,text:e,color:Bt(t.color,this.host._decorStyle.color),opacity:Ii(t.opacity,this.host._decorStyle.opacity),angle:this.host._angleField(t.angle),sizeCm:this.host._decorTextSizeCm(t),pickerEntity:t.entity||"",preserveLegacy:n||void 0},this.host._decorTextSelection={start:e.length,end:e.length}}_decorRememberTextSelection(t){this.host._decorTextSelection={start:t.selectionStart??t.value.length,end:t.selectionEnd??t.value.length}}_decorInsertLiveVariable(t){const e=this.host._decorTextDialog;if(!e)return;const i=wt(e.pickerEntity,t);if(!i)return;const s=e.text,o=Math.max(0,Math.min(s.length,this.host._decorTextSelection.start)),a=Math.max(o,Math.min(s.length,this.host._decorTextSelection.end));if(s.length-(a-o)+i.length>200)return;const n=s.slice(0,o)+i+s.slice(a),r=o+i.length;this.host._decorTextSelection={start:r,end:r},this.host._decorTextDialog={...e,text:n,preserveLegacy:void 0},this.host.updateComplete.then(()=>{const t=this.host.renderRoot.querySelector("textarea.dtarea");t&&(t.focus(),t.setSelectionRange(r,r))})}_decorSaveText(){const t=this.host._decorTextDialog,e=String(t?.text??"").replace(/\r\n?/g,"\n").trim();if(!t||!e)return void(this.host._decorTextDialog=null);const i=this._geometrySnapshot(),s=this.host._curSpaceCfg,o={color:t.color,opacity:Ii(t.opacity),size_cm:Number(Math.max(.1,Math.min(Zd,t.sizeCm)).toFixed(4)),...Mi(t.angle)?{angle:Mi(t.angle)}:{}};if(t.id)s.decor=this.host._decorList.map(i=>{if(i.id!==t.id)return i;if("text"!==i.kind)return i;if(t.preserveLegacy){const{angle:t,size:s,scale:a,...n}=i;return{...n,text:e,...o}}const{entity:s,attr:a,unit:n,...r}=i,{angle:l,size:h,scale:c,...d}=r;return{...d,text:e,...o}});else{const i="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);s.decor=[...this.host._decorList,{id:i,kind:"text",x:t.x,y:t.y,text:e,...o}],this.host._decorSel=i}this.host._decorTextDialog=null,this._recordGeometry(this.host._t(t.id?"history.decor_edit":"history.decor_add"),i),this._saveConfig(),this.host.requestUpdate()}_decorSaveShape(){const t=this.host._decorShapeDialog;if(!t)return;const e=this._geometrySnapshot(),i={color:t.color,opacity:Ii(t.opacity),widthCm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),fill:!!t.fill,fillColor:t.fillColor||t.color,fillOpacity:Ii(t.fillOpacity,.25)},s=this.host._curSpaceCfg,o="furniture"===t.kind||"image"===t.kind?$e(t.sizeWField,this.host._imperial,ke*this.host._cellCm):null,a="furniture"===t.kind||"image"===t.kind?$e(t.sizeHField,this.host._imperial,ke*this.host._cellCm):null;("furniture"!==t.kind&&"image"!==t.kind||null!==o&&null!==a)&&(s.decor=this.host._decorList.map(e=>{if(e.id!==t.id)return e;const s="rect"===t.kind||"ellipse"===t.kind,n=Si(i,s);if("line"===e.kind){const i=(e.x1+e.x2)/2*Qd,s=(e.y1+e.y2)/2*this.host._decorH,o=be(Math.max(.1,Number(t.lengthCm)||.1),this.host._cellCm,this.host._gridPitch),a=Mi(t.angle)*Math.PI/180,r=Math.cos(a)*o/2,l=Math.sin(a)*o/2,h=this._snap([i-r,s-l]),c=this._snap([i+r,s+l]),{width:d,line_style:p,...u}=e;return{...u,...n,x1:se(h[0]/Qd),y1:se(h[1]/this.host._decorH),x2:se(c[0]/Qd),y2:se(c[1]/this.host._decorH),..."dashed"===t.lineStyle?{line_style:"dashed"}:{}}}if("furniture"===e.kind){const i=e.w*Qd,s=e.h*this.host._decorH,r=be(Math.abs(o),this.host._cellCm,this.host._gridPitch),l=be(Math.abs(a),this.host._cellCm,this.host._gridPitch),h=e.x*Qd+i/2,c=e.y*this.host._decorH+s/2,d=Mi(t.angle),{width:p,angle:u,flip_h:_,flip_v:m,...g}=e;return{...g,...n,x:se((h-r/2)/Qd),y:se((c-l/2)/this.host._decorH),w:r/Qd,h:l/this.host._decorH,...t.symbol?{symbol:t.symbol}:{},...o<0?{flip_h:!0}:{},...a<0?{flip_v:!0}:{},...d?{angle:d}:{}}}if("image"===e.kind){const i=e.w*Qd,s=e.h*this.host._decorH,n=be(Math.abs(o),this.host._cellCm,this.host._gridPitch),r=be(Math.abs(a),this.host._cellCm,this.host._gridPitch),l=e.x*Qd+i/2,h=e.y*this.host._decorH+s/2,c=Mi(t.angle);return{id:e.id,kind:"image",asset_id:t.assetId||e.asset_id,x:se((l-n/2)/Qd),y:se((h-r/2)/this.host._decorH),w:n/Qd,h:r/this.host._decorH,opacity:Ii(t.opacity,1),...o<0?{flip_h:!0}:{},...a<0?{flip_v:!0}:{},...c?{angle:c}:{}}}if("rect"===e.kind||"ellipse"===e.kind){const i=e.w*Qd,s=e.h*this.host._decorH,o=Math.max(this.host._gridPitch,Ke(be(Number(t.sizeWCm),this.host._cellCm,this.host._gridPitch),this.host._gridPitch)),a=Math.max(this.host._gridPitch,Ke(be(Number(t.sizeHCm),this.host._cellCm,this.host._gridPitch),this.host._gridPitch)),r=e.x*Qd+i/2,l=e.y*this.host._decorH+s/2,h=Mi(t.angle),c=Di({x:r-o/2,y:l-a/2},h,t=>this._snap(t)),{width:d,angle:p,...u}=e;return{...u,...n,x:se(c[0]/Qd),y:se(c[1]/this.host._decorH),w:o/Qd,h:a/this.host._decorH,...h?{angle:h}:{}}}return e}),"image"!==t.kind&&this._updateDecorStyle({...i,fill:"rect"===t.kind||"ellipse"===t.kind?i.fill:this.host._decorStyle.fill,fillColor:"rect"===t.kind||"ellipse"===t.kind?i.fillColor:this.host._decorStyle.fillColor,fillOpacity:"rect"===t.kind||"ellipse"===t.kind?i.fillOpacity:this.host._decorStyle.fillOpacity}),this.host._decorShapeDialog=null,this._recordGeometry(this.host._t("history.decor_edit"),e),this._saveConfig(),this.host.requestUpdate())}_dtPivot(t){return"line"===t.kind?[(t.x1+t.x2)/2*Qd,(t.y1+t.y2)/2*this.host._decorH]:"furniture"===t.kind||"image"===t.kind||"rect"===t.kind||"ellipse"===t.kind?[(t.x+t.w/2)*Qd,(t.y+t.h/2)*this.host._decorH]:[t.x*Qd,t.y*this.host._decorH]}_dtApply(t,e){const i=this.host._curSpaceCfg;i&&(i.decor=this.host._decorList.map(i=>{if(i.id!==t)return i;const s={...i};"text"===i.kind&&void 0!==e.textSizeCm&&(delete s.size,delete s.scale);const o={...s};return void 0!==e.textSizeCm&&(o.size_cm=Number(Math.max(.1,Math.min(Zd,e.textSizeCm)).toFixed(4))),void 0!==e.angle&&(e.angle?o.angle=Number(e.angle.toFixed(2)):delete o.angle),o}),this.host._cfgEpoch++,this.host.requestUpdate())}_dtStart(t,e,i,s){const o=this.host._dtSel;if(!o)return;t.stopPropagation(),t.preventDefault();const[a,n]=this._dtPivot(o),r=this._svgPoint(t),l=this.host._decorBoxOf(o);this.host._dtDrag={id:o.id,kind:e,pid:t.pointerId,ax:a,ay:n,r0:Math.hypot(r[0]-a,r[1]-n),a0:180*Math.atan2(r[1]-n,r[0]-a)/Math.PI,textSizeCm0:"text"===o.kind?this.host._decorTextSizeCm(o):1,angle0:"line"===o.kind?0:Number(o.angle)||0,sgx:i?.[0],sgy:i?.[1],orig:l||void 0,origShape:JSON.parse(JSON.stringify(o)),before:this._geometrySnapshot(),lineEnd:s,moved:!1},ep(t)}_dtMove(t){const e=this.host._dtDrag;if(!e)return;const i=this._svgPoint(t);if(void 0!==e.lineEnd&&"line"===e.origShape.kind){const s=this._decorSnap(i,t.pointerType,e.id),o=se(s[0]/Qd),a=se(s[1]/this.host._decorH),n=e.origShape,r=0===e.lineEnd?n.x1:n.x2,l=0===e.lineEnd?n.y1:n.y2;return(Math.abs(o-r)>1e-9||Math.abs(a-l)>1e-9)&&(e.moved=!0),void this._replaceDecor(e.id,0===e.lineEnd?{x1:o,y1:a}:{x2:o,y2:a})}if("scale"===e.kind&&e.orig){if("furniture"===e.origShape.kind||"image"===e.origShape.kind){const s=Li({...e.orig,flip_h:e.origShape.flip_h,flip_v:e.origShape.flip_v},e.sgx??1,e.sgy??1,i[0],i[1],!t.shiftKey,be(.1,this.host._cellCm,this.host._gridPitch)),o=Math.abs(s.x-e.orig.x)>1e-9||Math.abs(s.y-e.orig.y)>1e-9||Math.abs(s.w-e.orig.w)>1e-9||Math.abs(s.h-e.orig.h)>1e-9||!!s.flip_h!=!!e.origShape.flip_h||!!s.flip_v!=!!e.origShape.flip_v;if(!o&&!e.moved)return;return e.moved||=o,void this._decorApplyFurnitureBox(e.id,s)}const s=Ti(e.orig,e.sgx??1,e.sgy??1,i[0],i[1],!t.shiftKey,this.host._gridPitch,this.host._gridPitch),o=Math.abs(s.x-e.orig.x)>1e-6||Math.abs(s.y-e.orig.y)>1e-6||Math.abs(s.w-e.orig.w)>1e-6||Math.abs(s.h-e.orig.h)>1e-6;if(!o&&!e.moved)return;return e.moved||=o,void this._decorApplyBox(e.id,s)}if("scale"===e.kind){const t=Math.hypot(i[0]-e.ax,i[1]-e.ay);if(e.r0<1e-6)return;const s=Math.max(.1,Math.min(Zd,e.textSizeCm0*(t/e.r0))),o=Math.abs(s-e.textSizeCm0)>1e-6;if(!o&&!e.moved)return;return e.moved||=o,void this._dtApply(e.id,{textSizeCm:s})}const s=180*Math.atan2(i[1]-e.ay,i[0]-e.ax)/Math.PI;let o;"furniture"===e.origShape.kind||"image"===e.origShape.kind?o=Ri(e.angle0,e.a0,s,t.shiftKey):(o=e.angle0+(s-e.a0),t.shiftKey||(o=5*Math.round(o/5)),o=(o%360+360)%360,o>180&&(o-=360));const a=Math.abs(o-e.angle0)>1e-6;(a||e.moved)&&(e.moved||=a,this._dtApply(e.id,{angle:o}))}_dtUp(){const t=this.host._dtDrag;this.host._dtDrag=null,t?.moved&&(this._recordGeometry(this.host._t("history.decor_transform"),t.before),this._saveConfig()),this.host.requestUpdate()}_dtMeasure(){!function(t){const e=t,i=e._dtSel;if(!i)return void(e._dtBox&&(e._dtBox=null,e.requestUpdate()));if("text"!==i.kind)return;const s=e.renderRoot.querySelector(`text.dtext[data-id="${i.id}"]`);if(!s||"function"!=typeof s.getBBox)return;let o;try{o=s.getBBox()}catch{return}if(!o||!o.width&&!o.height)return;const a={id:i.id,x:o.x,y:o.y,w:o.width,h:o.height},n=e._dtBox;n?.id===a.id&&Math.abs(n.x-a.x)<.01&&Math.abs(n.y-a.y)<.01&&Math.abs(n.w-a.w)<.01&&Math.abs(n.h-a.h)<.01||(e._dtBox=a,e.requestUpdate())}(this.host)}_deleteDecor(t){if(!this.host._decorList.some(e=>e.id===t))return;const e=this._geometrySnapshot();this.host._curSpaceCfg.decor=this.host._decorList.filter(e=>e.id!==t),this.host._decorSel===t&&(this.host._decorSel=null),this._recordGeometry(this.host._t("history.decor_delete"),e),this._saveConfig(),this.host.requestUpdate()}_decorDeleteSel(){this.host._decorSel&&this._deleteDecor(this.host._decorSel)}_confirmDecorErase(){const t=this.host._decorEraseConfirm;this.host._decorEraseConfirm=null,t&&this._deleteDecor(t.id)}_furnFieldValue(t){return Math.round(100*(this.host._imperial?t/30.48:t/100))/100}_furnFieldToCm(t){return Fi(this.host._imperial?30.48*t:100*t)}_furnShiftAttach(){this._furnShiftAttached||(this._furnShiftAttached=!0,window.addEventListener("keydown",this._furnShiftListener),window.addEventListener("keyup",this._furnShiftListener))}_furnShiftDetach(){this._furnShiftAttached&&(this._furnShiftAttached=!1,window.removeEventListener("keydown",this._furnShiftListener),window.removeEventListener("keyup",this._furnShiftListener))}_furnPick(t){const e=zi(t);this.host._furnPalette={symbol:t,w:e.w,h:e.h},this._furnShiftAttach()}get _furnWalls(){return function(t){const e=t._spaceModel();if(!e)return[];const i=[e.id,t._cfgEpoch,t._cellCm,t._gridPitch,t._wallKeyPitch].join("|"),s=Ah.get(t);if(s?.key===i)return s.value;const o=[...Nh(e.rooms,t._spaceWalls,t._openCuts(),t._wallKeyPitch,t._cellCm,t._gridPitch,pt),...Eh(t._rawPhysicalBodiesR())];return Ah.set(t,{key:i,value:o}),o}(this.host)}_resolveFurniturePlacement(t,e=!1,i="mouse"){const s=this.host._furnPalette,o=this.host._curSpaceCfg;if(!s||!o)return null;const a=this.host._decorH,n=this._decorSnap(t,i);return function(t){const{symbol:e,widthCm:i,depthCm:s,point:o,canvasW:a,canvasH:n,cellCm:r,gridPitch:l,walls:h,wallReach:c,free:d=!1,intentPoint:p=o,preferredNormal:u}=t;if(!(ie(e)&&n>0&&Number.isFinite(o[0])&&Number.isFinite(o[1])))return null;const _=Number.isFinite(p[0])&&Number.isFinite(p[1])?p:o,m=oe(ae(i,r,l,a)),g=oe(ae(s,r,l,a));let f=o[0],b=o[1],v=0;const y=d?null:Rh(f,b,g*n,h,c,l,_,u);return y&&(f=y.cx,b=y.cy,v=y.angle),{symbol:e,x:se(f/a-m/2),y:se(b/n-g/2),w:m,h:g,angle:Number(v.toFixed(2))}}({symbol:s.symbol,widthCm:s.w,depthCm:s.h,point:[n[0],n[1]],canvasW:1e3,canvasH:a,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,walls:this._furnWalls,wallReach:6*this.host._gridPitch,intentPoint:[t[0],t[1]],free:e})}_furniturePreviewPlacement(){const t=this.host._furnPreviewInput;return t&&"decor"===this.host._mode&&"furniture"===this.host._decorTool&&this.host._furnPalette&&this.host._pointerModality.hoverEnabled?this._resolveFurniturePlacement(t.raw,t.free,"mouse"):null}_renderFurniturePlacementPreview(t){const e=this._furniturePreviewPlacement();if(!e)return d;const i=Ce(e.symbol);if(!i)return d;const s=Ni(e,Qd,this.host._decorH,i.viewW,i.viewH),o=this.host._decorStyle,a=Ei(be(o.widthCm,this.host._cellCm,this.host._gridPitch),t);return Tt`<path class="furniture-placement-preview dfurn"
|
||
data-symbol=${e.symbol} d=${i.d} transform=${s}
|
||
stroke=${o.color} stroke-opacity=${o.opacity}
|
||
stroke-width=${a}
|
||
fill="none" stroke-linecap="round" stroke-linejoin="round"
|
||
vector-effect="non-scaling-stroke" aria-hidden="true" pointer-events="none"></path>`}_furnLive(){const t=this.host._dtDrag;if(!t||"scale"!==t.kind||!t.orig)return null;const e=this.host._decorList.find(e=>e.id===t.id);if(!e||"furniture"!==e.kind)return null;const i=e.w*Qd,s=e.h*this.host._decorH,o=Ai(e.x*Qd,e.y*this.host._decorH,i,s,Number(e.angle)||0),a=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],n=a(o[0],o[1]),r=a(o[0],o[3]);return[{x:n[0],y:n[1],text:this.host._fmtLen([0,0],[i,0])},{x:r[0],y:r[1],text:this.host._fmtLen([0,0],[0,s])}]}_furnPlace(t,e=!1,i="mouse"){const s=this._resolveFurniturePlacement(t,e,i);if(!s)return;const o=this.host._curSpaceCfg;if(!o)return;const a=this._geometrySnapshot(),n="df"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),r={id:n,kind:"furniture",symbol:s.symbol,x:s.x,y:s.y,w:s.w,h:s.h,...Si(this.host._decorStyle,!1)};s.angle&&(r.angle=s.angle),o.decor=[...this.host._decorList,r],this.host._decorSel=n,this.host._decorTool="select",this.host._furnPalette=null,this.host._furnCategory=null,this._furnShiftDetach(),this._clearFurniturePreview(),this._recordGeometry(this.host._t("history.decor_add"),a),this._saveConfig(),this.host.requestUpdate()}_clearFurniturePreview(){this.host._furnPreviewInput=null,this.host._furnTouchPending=null}_furnPointerMove(t,e){const i=this.host._furnTouchPending;if(i?.pid===t.pointerId)return Math.abs(t.clientX-i.sx)+Math.abs(t.clientY-i.sy)>8&&(i.cancelled=!0),this.host._furnPreviewInput=null,!0;const s="furniture"===this.host._decorTool?!!this.host._furnPalette:"image"===this.host._decorTool&&!!this.host._decorImagePalette;if("decor"!==this.host._mode||!s)return this._clearFurniturePreview(),!1;if("mouse"!==t.pointerType||!e)return this.host._furnPreviewInput=null,!1;const o=this._svgPoint(t);return this.host._furnPreviewInput={raw:[o[0],o[1]],free:t.shiftKey},!0}_furnPointerLeave(t){this.host._furnTouchPending?.pid===t.pointerId&&(this.host._furnTouchPending.cancelled=!0),this.host._furnPreviewInput=null}_furnPointerUp(t){const e=this.host._furnTouchPending;return!(!e||e.pid!==t.pointerId)&&(this.host._furnTouchPending=null,!e.cancelled&&"decor"===this.host._mode&&("furniture"===this.host._decorTool&&this.host._furnPalette||"image"===this.host._decorTool&&this.host._decorImagePalette)&&("furniture"===this.host._decorTool?this._furnPlace(this._svgPoint(t),t.shiftKey,e.pointerType):this._decorImagePlace(this._svgPoint(t),e.pointerType)),!0)}_furnMoveUpdate(t){const e=this.host._decorMove;if(!e)return;if("furniture"!==e.orig.kind)return;const i=e.orig,s=this.host._curSpaceCfg;if(!s)return;const o=Qd,a=this.host._decorH,n=this._svgPoint(t),r=(i.x+i.w/2)*o+(n[0]-e.start[0]),l=(i.y+i.h/2)*a+(n[1]-e.start[1]);let h,c,d=Number(i.angle)||0;const p=d*Math.PI/180,u=[-Math.sin(p),Math.cos(p)],_=t.shiftKey?null:Rh(r,l,i.h*a,this._furnWalls,6*this.host._gridPitch,this.host._gridPitch,[r,l],u);if(_)h=_.cx/o-i.w/2,c=_.cy/a-i.h/2,d=_.angle;else{const s=this._decorSnap([r-i.w/2*o,l-i.h/2*a],t.pointerType,e.id);h=s[0]/o,c=s[1]/a}h=se(h),c=se(c),(Math.abs(h-i.x)>1e-9||Math.abs(c-i.y)>1e-9||Math.abs(d-(Number(i.angle)||0))>1e-9)&&(e.moved=!0),s.decor=this.host._decorList.map(t=>{if(t.id!==e.id)return t;const i={...t,x:h,y:c};return d?i.angle=Number(d.toFixed(2)):delete i.angle,i}),this.host.requestUpdate()}_decorApplyBox(t,e){const i=this.host._curSpaceCfg;if(!i)return;const s=Qd,o=this.host._decorH;i.decor=this.host._decorList.map(i=>{if(i.id!==t)return i;const a=Di(e,i.angle,t=>this._snap(t));return{...i,x:se(a[0]/s),y:se(a[1]/o),w:Math.max(this.host._gridPitch/s,Math.min(2*ke,e.w/s)),h:Math.max(this.host._gridPitch/o,Math.min(2*ke,e.h/o))}}),this.host._cfgEpoch++,this.host.requestUpdate()}_decorApplyFurnitureBox(t,e){const i=this.host._curSpaceCfg;if(!i)return;const s=Qd,o=this.host._decorH,a=be(.1,this.host._cellCm,this.host._gridPitch);i.decor=this.host._decorList.map(i=>{if(i.id!==t||"furniture"!==i.kind&&"image"!==i.kind)return i;const{flip_h:n,flip_v:r,...l}=i;return{...l,x:se(e.x/s),y:se(e.y/o),w:Math.max(a/s,Math.min(2*ke,e.w/s)),h:Math.max(a/o,Math.min(2*ke,e.h/o)),...e.flip_h?{flip_h:!0}:{},...e.flip_v?{flip_v:!0}:{}}}),this.host._cfgEpoch++,this.host.requestUpdate()}_decorImagePlace(t,e="mouse"){this._decorImages.place(t,e)}_renderDecorImagePlacementPreview(){return this._decorImages.renderPlacementPreview()}_renderMissingDecorImage(t,e,i,s,o,a,n,r,l){return this._decorImages.renderMissing(t,e,i,s,o,a,n,r,l)}async _decorImageUpload(t,e=!1){await this._decorImages.uploadFromInput(t,e)}async _uploadDecorImage(t,e,i){await this._decorImages.upload(t,e,i)}async _decorImageDelete(t){await this._decorImages.delete(t)}async _decorImageCatalogLoad(){await this._decorImages.loadCatalog()}_renderDecorImagePalette(){return this._decorImages.renderImagePalette()}_renderFurnPalette(){return this._decorImages.renderFurniturePalette()}_openBackdropDialog(t){if(!this.host._bdMovable||!this.host._bdRect)return;t?.preventDefault(),t?.stopPropagation(),this.host._bdDrag=null;const e=this.host._bdRect;this.host._backdropDialog={widthCm:xi(e.w,this.host._cellCm,this.host._gridPitch),heightCm:xi(e.h,this.host._cellCm,this.host._gridPitch),angle:this.host._angleField(e.angle)}}_saveBackdropDialog(){const t=this.host._backdropDialog,e=this.host._bdBase,i=this.host._bdRect;if(!t||!e||!i)return;const s=Mi(t.angle),o=this._geometrySnapshot(),a=Math.min(e.w*ft,Math.max(e.w*gt,Ke(be(t.widthCm,this.host._cellCm,this.host._gridPitch),this.host._gridPitch))),n=Math.min(e.h*ft,Math.max(e.h*gt,Ke(be(t.heightCm,this.host._cellCm,this.host._gridPitch),this.host._gridPitch))),r=i.x+i.w/2,l=i.y+i.h/2,h=Di({x:r-a/2,y:l-n/2},s,t=>this._snap(t));this._bdApply((h[0]-e.x)/Qd,(h[1]-e.y)/Qd,a/e.w,n/e.h,s),this.host._backdropDialog=null,this._recordGeometry(this.host._t("history.backdrop_transform"),o),this._saveConfig()}_bdApply(t,e,i,s,o){const a=this.host._curSpaceCfg;if(!a)return;a.plan_x=Number(se(t).toFixed(6)),a.plan_y=Number(se(e).toFixed(6)),delete a.plan_scale,a.plan_scale_x=Number(Math.min(ft,Math.max(gt,i)).toFixed(6)),a.plan_scale_y=Number(Math.min(ft,Math.max(gt,s)).toFixed(6));const n=Mi(o);n?a.plan_angle=Number(n.toFixed(2)):delete a.plan_angle,this.host._cfgEpoch++,this.host.requestUpdate()}_bdStart(t,e,i=!1){const s=this.host._bdBase,o=this.host._bdRect;if(!s||!o)return!1;const a=this._svgPoint(t),n=e?e[0]:0,r=e?e[1]:0,l=n>0?o.x:o.x+o.w,h=r>0?o.y:o.y+o.h;return this.host._bdDrag={kind:i?"rotate":e?"scale":"move",pid:t.pointerId,sx:a[0],sy:a[1],base:s,p0:this.host._bdParams,fx:l,fy:h,sgx:n,sgy:r,rect0:{x:o.x,y:o.y,w:o.w,h:o.h,angle:o.angle},before:this._geometrySnapshot(),moved:!1},ep(t),!0}_bdMove(t){Er(this.host,"backdrop",()=>this._bdMoveNow(t))}_bdMoveNow(t){const e=this.host._bdDrag;if(!e)return;const i=this._svgPoint(t),s=e.base;if("move"===e.kind){const t=e.rect0.x,o=e.rect0.y,a=this._snap([t+(i[0]-e.sx),o+(i[1]-e.sy)]),n=Math.abs(a[0]-t)>1e-9||Math.abs(a[1]-o)>1e-9;if(!n&&!e.moved)return;return e.moved||=n,void this._bdApply((a[0]-s.x)/Qd,(a[1]-s.y)/Qd,e.p0.sx,e.p0.sy,e.p0.angle)}if("rotate"===e.kind){const s=e.rect0.x+e.rect0.w/2,o=e.rect0.y+e.rect0.h/2,a=180*Math.atan2(e.sy-o,e.sx-s)/Math.PI;let n=e.p0.angle+(180*Math.atan2(i[1]-o,i[0]-s)/Math.PI-a);t.shiftKey||(n=5*Math.round(n/5)),n=Mi(n);const r=Math.abs(n-e.p0.angle)>1e-9;if(!r&&!e.moved)return;return e.moved||=r,void this._bdApply(e.p0.dx,e.p0.dy,e.p0.sx,e.p0.sy,n)}const o=Ti(e.rect0,e.sgx,e.sgy,i[0],i[1],!t.shiftKey,this.host._gridPitch,Math.min(s.w,s.h)*gt),a=o.w/Math.max(1e-9,s.w),n=o.h/Math.max(1e-9,s.h),r=Math.abs(a-e.p0.sx)>1e-9||Math.abs(n-e.p0.sy)>1e-9||Math.abs(o.x-e.rect0.x)>1e-9||Math.abs(o.y-e.rect0.y)>1e-9;if(!r&&!e.moved)return;e.moved||=r;const l=Di(o,e.p0.angle,t=>this._snap(t));this._bdApply((l[0]-s.x)/Qd,(l[1]-s.y)/Qd,a,n,e.p0.angle)}_bdReset(){const t=this.host._curSpaceCfg;if(!t)return;const e=this._geometrySnapshot();delete t.plan_x,delete t.plan_y,delete t.plan_scale,delete t.plan_scale_x,delete t.plan_scale_y,delete t.plan_angle,this.host._bdDrag=null,this._recordGeometry(this.host._t("history.backdrop_transform"),e),this._saveConfig(),this.host._showToast(this.host._t("decor.backdrop_reset_done")),this.host.requestUpdate()}_bdUp(){Ar(this.host,"backdrop");const t=this.host._bdDrag;this.host._bdDrag=null,t?.moved&&(this._recordGeometry(this.host._t("history.backdrop_transform"),t.before),this._saveConfig()),this.host.requestUpdate()}_renderBackdropFrame(t){const e=this.host._bdRect;if(!this.host._bdActive||!e)return d;const i=.02*Math.max(t.w,t.h),s=i/4,o=e.x+e.w/2,a=e.y+e.h/2,n=Mi(e.angle),r=2.2*i;return Tt`<g class="bdframe" transform=${n?`rotate(${n} ${o} ${a})`:d}>
|
||
========
|
||
</circle>`),n.push(Tt`<g class="rszicon ${u?"disabled":""}" transform="translate(${h} ${c}) rotate(${d})"><path class="rszhalo" d="${a}"></path><path class="rszink" d="${a}"></path></g>`)}return Tt`<g class="resize-layer">${n}</g>`}_partitionOpeningCuts(t=this.host._spaceModel(),e=()=>!0){if(!t)return[];const s=this.host._curSpaceCfg?.id===t.id?this.host._curSpaceCfg:null,i=fs(s,t,this.host._cellCm,this.host._gridPitch,Vd);return bs(i,e)}_decorSnapGeometry(t){const e=this.host._spaceModel();if(!e)return{points:[],segments:[]};const s=t||"",i=this.host._decorSnapCache;if(i&&i.epoch===this.host._cfgEpoch&&i.space===this.host._space&&i.height===this.host._decorH&&i.exclude===s)return i.geometry;const o=[];for(const e of this.host._decorList)if(e.id!==t)if("line"===e.kind){const t=[e.x1*Vd,e.y1*this.host._decorH],s=[e.x2*Vd,e.y2*this.host._decorH];o.push({points:[t,s,[(t[0]+s[0])/2,(t[1]+s[1])/2]],segments:[{a:t,b:s}]})}else if("text"===e.kind)o.push({points:[[e.x*Vd,e.y*this.host._decorH]],segments:[]});else{const t=this.host._decorBoxOf(e);t&&o.push(vs(t))}for(const t of e.rooms){const e=B(t);e?.length&&o.push({points:e.flatMap((t,s)=>{const i=e[(s+1)%e.length];return[t,[(t[0]+i[0])/2,(t[1]+i[1])/2]]}),segments:e.map((t,s)=>({a:t,b:e[(s+1)%e.length]}))})}const a=ys(o);return this.host._decorSnapCache={epoch:this.host._cfgEpoch,space:this.host._space,height:this.host._decorH,exclude:s,geometry:a},a}_decorSnap(t,e="mouse",s){const i=this.host._stageEl,o=this.host._viewOr(this.host._baseVb()),a="touch"===e||"pen"===e?14:8,n=i?o.w/Math.max(1,i.clientWidth)*a:this.host._gridPitch;return ws(t,this._decorSnapGeometry(s),n,t=>this._snap(t)).point}_replaceDecor(t,e){const s=this.host._curSpaceCfg;s&&(s.decor=this.host._decorList.map(s=>s.id===t?{...s,...e}:s),this.host.requestUpdate())}_cancelDecorGesture(){Nr(this.host,"decor-transform"),Nr(this.host,"decor-move"),Nr(this.host,"backdrop");const t=this.host._decorMove?.before||this.host._dtDrag?.before||this.host._bdDrag?.before,e=t&&this.host._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(t&&e){const s=t=>JSON.parse(JSON.stringify(t));void 0!==t.decor?e.decor=s(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];Object.assign(e,s(t.plan_transform||{})),this.host._decorSnapCache=null}this.host._decorMove=null,this.host._dtDrag=null,this.host._bdDrag=null,t&&e&&"decor"===this.host._mode&&(this.host._terminalFrame=1),this.host.requestUpdate()}_decorPointerDown(t){const e=this.host._decorTool;if("mouse"===t.pointerType&&0!==t.button&&"select"!==e&&"erase"!==e)return!1;if("select"===e||"erase"===e?t.target.closest?.(".dshape"):null)return!0;if("line"===e||"rect"===e||"ellipse"===e){t.preventDefault();const s=this._decorSnap(this._svgPoint(t),t.pointerType);return this.host._decorDraft={kind:e,a:s,b:s,pid:t.pointerId},Zd(t),!0}if("text"===e){const e=this._decorSnap(this._svgPoint(t),t.pointerType);return this.host._decorTextDialog={x:ie(e[0]/Vd),y:ie(e[1]/this.host._decorH),text:"",color:this.host._decorStyle.color,opacity:this.host._decorStyle.opacity,angle:"0",sizeCm:$s(bt,this.host._cellCm,this.host._gridPitch)},this.host._decorTextSelection={start:0,end:0},!0}if("furniture"===e||"image"===e){if("furniture"===e?!this.host._furnPalette:!this.host._decorImagePalette)return!1;t.preventDefault();const s=t.pointerType||"mouse";if("mouse"===s)return"furniture"===e?this._furnPlace(this._svgPoint(t),t.shiftKey,s):this._decorImagePlace(this._svgPoint(t),s),!0;const i=this.host._furnTouchPending;return i&&i.pid!==t.pointerId?(i.cancelled=!0,this.host._furnPreviewInput=null,!0):(this.host._furnTouchPending={pid:t.pointerId,sx:t.clientX,sy:t.clientY,pointerType:s,cancelled:!1},this.host._furnPreviewInput=null,Zd(t),!0)}if("select"===e&&(this.host._decorSel=null),this.host._bdMovable){const e=this.host._bdRect,s=this._svgPoint(t),i=e.x+e.w/2,o=e.y+e.h/2,a=-ks(e.angle)*Math.PI/180,n=s[0]-i,r=s[1]-o,l=[i+n*Math.cos(a)-r*Math.sin(a),o+n*Math.sin(a)+r*Math.cos(a)];if(l[0]>=e.x&&l[0]<=e.x+e.w&&l[1]>=e.y&&l[1]<=e.y+e.h)return t.preventDefault(),this._bdStart(t)}return!1}_decorCommitDraft(){const t=this.host._decorDraft;if(this.host._decorDraft=null,!t)return;const e=.5*this.host._gridPitch;if(!xs(t.kind,t.a,t.b,e))return;const s=Vd,i=this.host._decorH,o=this.host._decorStyle,a=this._geometrySnapshot(),n="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),r=ie;let l;if("line"===t.kind)l={id:n,kind:"line",x1:r(t.a[0]/s),y1:r(t.a[1]/i),x2:r(t.b[0]/s),y2:r(t.b[1]/i),...Ms(o,!1)};else{const e=r(Math.min(t.a[0],t.b[0])/s),a=r(Math.min(t.a[1],t.b[1])/i),h=Math.abs(t.b[0]-t.a[0])/s,c=Math.abs(t.b[1]-t.a[1])/i;l={id:n,kind:t.kind,x:e,y:a,w:h,h:c,...Ms(o,!0)}}this.host._curSpaceCfg.decor=[...this.host._decorList,l],this.host._decorSel=n,this._recordGeometry(this.host._t("history.decor_add"),a),this._saveConfig(),this.host.requestUpdate()}_decorShapeDown(t,e){if("decor"!==this.host._mode)return;const s=this.host._decorTool;if("text"===s){if("text"!==e.kind)return;return t.stopPropagation(),t.preventDefault(),void this._decorOpenText(e)}"select"!==s&&"erase"!==s||(t.stopPropagation(),t.preventDefault(),"erase"!==s?(this.host._decorSel=e.id,this.host._decorMove={id:e.id,start:this._svgPoint(t),orig:JSON.parse(JSON.stringify(e)),pid:t.pointerId,moved:!1,before:this._geometrySnapshot()},Zd(t)):this.host._decorEraseConfirm={id:e.id,kind:e.kind})}_decorMoveUpdate(t){const e=this.host._decorMove;if(!e)return;if("furniture"===e.orig?.kind)return void this._furnMoveUpdate(t);const s=this._svgPoint(t),i=e.orig,o=("line"===i.kind?i.x1:i.x)*Vd,a=("line"===i.kind?i.y1:i.y)*this.host._decorH,n=this._decorSnap([o+(s[0]-e.start[0]),a+(s[1]-e.start[1])],t.pointerType,e.id);let r=(n[0]-o)/Vd,l=(n[1]-a)/this.host._decorH;const h=e.orig,c="line"===h.kind?Math.min(h.x1,h.x2):h.x,d="line"===h.kind?Math.min(h.y1,h.y2):h.y,p="line"===h.kind?Math.abs(h.x2-h.x1):h.w||0,u="line"===h.kind?Math.abs(h.y2-h.y1):h.h||0,_=$e;r=Math.max(-_-c,Math.min(_-c-p,r)),l=Math.max(-_-d,Math.min(_-d-u,l)),(r||l)&&(e.moved=!0);this.host._curSpaceCfg.decor=this.host._decorList.map(t=>{if(t.id!==e.id)return t;const s=e.orig;return"line"===t.kind?{...t,x1:s.x1+r,y1:s.y1+l,x2:s.x2+r,y2:s.y2+l}:{...t,x:s.x+r,y:s.y+l}}),this.host.requestUpdate()}_dmUp(){Fr(this.host,"decor-move");const t=this.host._decorMove;t?.moved&&(this._recordGeometry(this.host._t("history.decor_move"),t.before),this._saveConfig()),this.host._decorMove=null,this.host.requestUpdate()}_decorShapeDbl(t,e){"decor"===this.host._mode&&"select"===this.host._decorTool&&(t.preventDefault(),t.stopPropagation(),this.host._decorMove=null,this.host._decorSel=e.id,this._openDecorProperties(e))}_openDecorProperties(t){if("decor"!==this.host._mode||"select"!==this.host._decorTool)return;if("text"===t.kind)return void this._decorOpenText(t);if(!["line","rect","ellipse","furniture","image"].includes(t.kind))return;"image"===t.kind&&this._decorImageCatalogLoad();const e=this.host._decorResolvedStyle(t),s="line"===t.kind?t:null,i=this.host._decorBoxOf(t);this.host._decorShapeDialog={id:t.id,kind:t.kind,color:e.color,opacity:e.opacity,widthCm:e.widthCm,angle:this.host._angleField(ks(s?Cs([s.x1*Vd,s.y1*this.host._decorH],[s.x2*Vd,s.y2*this.host._decorH]):t.angle)),...s?{lengthCm:$s(Math.hypot((s.x2-s.x1)*Vd,(s.y2-s.y1)*this.host._decorH),this.host._cellCm,this.host._gridPitch),lineStyle:"dashed"===s.line_style?"dashed":"solid"}:{},...i?{sizeWCm:$s(i.w,this.host._cellCm,this.host._gridPitch),sizeHCm:$s(i.h,this.host._cellCm,this.host._gridPitch)}:{},..."furniture"===t.kind?{symbol:t.symbol,flipH:!!t.flip_h,flipV:!!t.flip_v,sizeWField:ke($s(i.w,this.host._cellCm,this.host._gridPitch),!!t.flip_h,this.host._imperial),sizeHField:ke($s(i.h,this.host._cellCm,this.host._gridPitch),!!t.flip_v,this.host._imperial)}:{},..."image"===t.kind?{assetId:t.asset_id,flipH:!!t.flip_h,flipV:!!t.flip_v,sizeWField:ke($s(i.w,this.host._cellCm,this.host._gridPitch),!!t.flip_h,this.host._imperial),sizeHField:ke($s(i.h,this.host._cellCm,this.host._gridPitch),!!t.flip_v,this.host._imperial)}:{},..."rect"===t.kind||"ellipse"===t.kind?{fill:e.fill,fillColor:e.fillColor,fillOpacity:e.fillOpacity}:{}}}_decorOpenText(t){if("text"!==t.kind)return;let e=String(t.text??"");const s=[...e.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!yt(t[1])),i=String(t.unit??"").trim(),o="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,a=s||i?"":wt(t.entity,o),n=!(!String(t.entity??"").trim()||s||a&&!i);if(a&&!n){const t=e.indexOf("{}");e=t>=0?e.slice(0,t)+a+e.slice(t+2):`${e}${e?" ":""}${a}`}this.host._decorTextDialog={id:t.id,x:t.x,y:t.y,text:e,color:Bt(t.color,this.host._decorStyle.color),opacity:Ss(t.opacity,this.host._decorStyle.opacity),angle:this.host._angleField(t.angle),sizeCm:this.host._decorTextSizeCm(t),pickerEntity:t.entity||"",preserveLegacy:n||void 0},this.host._decorTextSelection={start:e.length,end:e.length}}_decorRememberTextSelection(t){this.host._decorTextSelection={start:t.selectionStart??t.value.length,end:t.selectionEnd??t.value.length}}_decorInsertLiveVariable(t){const e=this.host._decorTextDialog;if(!e)return;const s=wt(e.pickerEntity,t);if(!s)return;const i=e.text,o=Math.max(0,Math.min(i.length,this.host._decorTextSelection.start)),a=Math.max(o,Math.min(i.length,this.host._decorTextSelection.end));if(i.length-(a-o)+s.length>200)return;const n=i.slice(0,o)+s+i.slice(a),r=o+s.length;this.host._decorTextSelection={start:r,end:r},this.host._decorTextDialog={...e,text:n,preserveLegacy:void 0},this.host.updateComplete.then(()=>{const t=this.host.renderRoot.querySelector("textarea.dtarea");t&&(t.focus(),t.setSelectionRange(r,r))})}_decorSaveText(){const t=this.host._decorTextDialog,e=String(t?.text??"").replace(/\r\n?/g,"\n").trim();if(!t||!e)return void(this.host._decorTextDialog=null);const s=this._geometrySnapshot(),i=this.host._curSpaceCfg,o={color:t.color,opacity:Ss(t.opacity),size_cm:Number(Math.max(.1,Math.min(Ud,t.sizeCm)).toFixed(4)),...ks(t.angle)?{angle:ks(t.angle)}:{}};if(t.id)i.decor=this.host._decorList.map(s=>{if(s.id!==t.id)return s;if("text"!==s.kind)return s;if(t.preserveLegacy){const{angle:t,size:i,scale:a,...n}=s;return{...n,text:e,...o}}const{entity:i,attr:a,unit:n,...r}=s,{angle:l,size:h,scale:c,...d}=r;return{...d,text:e,...o}});else{const s="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);i.decor=[...this.host._decorList,{id:s,kind:"text",x:t.x,y:t.y,text:e,...o}],this.host._decorSel=s}this.host._decorTextDialog=null,this._recordGeometry(this.host._t(t.id?"history.decor_edit":"history.decor_add"),s),this._saveConfig(),this.host.requestUpdate()}_decorSaveShape(){const t=this.host._decorShapeDialog;if(!t)return;const e=this._geometrySnapshot(),s={color:t.color,opacity:Ss(t.opacity),widthCm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),fill:!!t.fill,fillColor:t.fillColor||t.color,fillOpacity:Ss(t.fillOpacity,.25)},i=this.host._curSpaceCfg,o="furniture"===t.kind||"image"===t.kind?we(t.sizeWField,this.host._imperial,$e*this.host._cellCm):null,a="furniture"===t.kind||"image"===t.kind?we(t.sizeHField,this.host._imperial,$e*this.host._cellCm):null;("furniture"!==t.kind&&"image"!==t.kind||null!==o&&null!==a)&&(i.decor=this.host._decorList.map(e=>{if(e.id!==t.id)return e;const i="rect"===t.kind||"ellipse"===t.kind,n=Ms(s,i);if("line"===e.kind){const s=(e.x1+e.x2)/2*Vd,i=(e.y1+e.y2)/2*this.host._decorH,o=fe(Math.max(.1,Number(t.lengthCm)||.1),this.host._cellCm,this.host._gridPitch),a=ks(t.angle)*Math.PI/180,r=Math.cos(a)*o/2,l=Math.sin(a)*o/2,h=this._snap([s-r,i-l]),c=this._snap([s+r,i+l]),{width:d,line_style:p,...u}=e;return{...u,...n,x1:ie(h[0]/Vd),y1:ie(h[1]/this.host._decorH),x2:ie(c[0]/Vd),y2:ie(c[1]/this.host._decorH),..."dashed"===t.lineStyle?{line_style:"dashed"}:{}}}if("furniture"===e.kind){const s=e.w*Vd,i=e.h*this.host._decorH,r=fe(Math.abs(o),this.host._cellCm,this.host._gridPitch),l=fe(Math.abs(a),this.host._cellCm,this.host._gridPitch),h=e.x*Vd+s/2,c=e.y*this.host._decorH+i/2,d=ks(t.angle),{width:p,angle:u,flip_h:_,flip_v:m,...g}=e;return{...g,...n,x:ie((h-r/2)/Vd),y:ie((c-l/2)/this.host._decorH),w:r/Vd,h:l/this.host._decorH,...t.symbol?{symbol:t.symbol}:{},...o<0?{flip_h:!0}:{},...a<0?{flip_v:!0}:{},...d?{angle:d}:{}}}if("image"===e.kind){const s=e.w*Vd,i=e.h*this.host._decorH,n=fe(Math.abs(o),this.host._cellCm,this.host._gridPitch),r=fe(Math.abs(a),this.host._cellCm,this.host._gridPitch),l=e.x*Vd+s/2,h=e.y*this.host._decorH+i/2,c=ks(t.angle);return{id:e.id,kind:"image",asset_id:t.assetId||e.asset_id,x:ie((l-n/2)/Vd),y:ie((h-r/2)/this.host._decorH),w:n/Vd,h:r/this.host._decorH,opacity:Ss(t.opacity,1),...o<0?{flip_h:!0}:{},...a<0?{flip_v:!0}:{},...c?{angle:c}:{}}}if("rect"===e.kind||"ellipse"===e.kind){const s=e.w*Vd,i=e.h*this.host._decorH,o=Math.max(this.host._gridPitch,qe(fe(Number(t.sizeWCm),this.host._cellCm,this.host._gridPitch),this.host._gridPitch)),a=Math.max(this.host._gridPitch,qe(fe(Number(t.sizeHCm),this.host._cellCm,this.host._gridPitch),this.host._gridPitch)),r=e.x*Vd+s/2,l=e.y*this.host._decorH+i/2,h=ks(t.angle),c=Ps({x:r-o/2,y:l-a/2},h,t=>this._snap(t)),{width:d,angle:p,...u}=e;return{...u,...n,x:ie(c[0]/Vd),y:ie(c[1]/this.host._decorH),w:o/Vd,h:a/this.host._decorH,...h?{angle:h}:{}}}return e}),"image"!==t.kind&&this._updateDecorStyle({...s,fill:"rect"===t.kind||"ellipse"===t.kind?s.fill:this.host._decorStyle.fill,fillColor:"rect"===t.kind||"ellipse"===t.kind?s.fillColor:this.host._decorStyle.fillColor,fillOpacity:"rect"===t.kind||"ellipse"===t.kind?s.fillOpacity:this.host._decorStyle.fillOpacity}),this.host._decorShapeDialog=null,this._recordGeometry(this.host._t("history.decor_edit"),e),this._saveConfig(),this.host.requestUpdate())}_dtPivot(t){return"line"===t.kind?[(t.x1+t.x2)/2*Vd,(t.y1+t.y2)/2*this.host._decorH]:"furniture"===t.kind||"image"===t.kind||"rect"===t.kind||"ellipse"===t.kind?[(t.x+t.w/2)*Vd,(t.y+t.h/2)*this.host._decorH]:[t.x*Vd,t.y*this.host._decorH]}_dtApply(t,e){const s=this.host._curSpaceCfg;s&&(s.decor=this.host._decorList.map(s=>{if(s.id!==t)return s;const i={...s};"text"===s.kind&&void 0!==e.textSizeCm&&(delete i.size,delete i.scale);const o={...i};return void 0!==e.textSizeCm&&(o.size_cm=Number(Math.max(.1,Math.min(Ud,e.textSizeCm)).toFixed(4))),void 0!==e.angle&&(e.angle?o.angle=Number(e.angle.toFixed(2)):delete o.angle),o}),this.host._cfgEpoch++,this.host.requestUpdate())}_dtStart(t,e,s,i){const o=this.host._dtSel;if(!o)return;t.stopPropagation(),t.preventDefault();const[a,n]=this._dtPivot(o),r=this._svgPoint(t),l=this.host._decorBoxOf(o);this.host._dtDrag={id:o.id,kind:e,pid:t.pointerId,ax:a,ay:n,r0:Math.hypot(r[0]-a,r[1]-n),a0:180*Math.atan2(r[1]-n,r[0]-a)/Math.PI,textSizeCm0:"text"===o.kind?this.host._decorTextSizeCm(o):1,angle0:"line"===o.kind?0:Number(o.angle)||0,sgx:s?.[0],sgy:s?.[1],orig:l||void 0,origShape:JSON.parse(JSON.stringify(o)),before:this._geometrySnapshot(),lineEnd:i,moved:!1},Zd(t)}_dtMove(t){const e=this.host._dtDrag;if(!e)return;const s=this._svgPoint(t);if(void 0!==e.lineEnd&&"line"===e.origShape.kind){const i=this._decorSnap(s,t.pointerType,e.id),o=ie(i[0]/Vd),a=ie(i[1]/this.host._decorH),n=e.origShape,r=0===e.lineEnd?n.x1:n.x2,l=0===e.lineEnd?n.y1:n.y2;return(Math.abs(o-r)>1e-9||Math.abs(a-l)>1e-9)&&(e.moved=!0),void this._replaceDecor(e.id,0===e.lineEnd?{x1:o,y1:a}:{x2:o,y2:a})}if("scale"===e.kind&&e.orig){if("furniture"===e.origShape.kind||"image"===e.origShape.kind){const i=Is({...e.orig,flip_h:e.origShape.flip_h,flip_v:e.origShape.flip_v},e.sgx??1,e.sgy??1,s[0],s[1],!t.shiftKey,fe(.1,this.host._cellCm,this.host._gridPitch)),o=Math.abs(i.x-e.orig.x)>1e-9||Math.abs(i.y-e.orig.y)>1e-9||Math.abs(i.w-e.orig.w)>1e-9||Math.abs(i.h-e.orig.h)>1e-9||!!i.flip_h!=!!e.origShape.flip_h||!!i.flip_v!=!!e.origShape.flip_v;if(!o&&!e.moved)return;return e.moved||=o,void this._decorApplyFurnitureBox(e.id,i)}const i=Ds(e.orig,e.sgx??1,e.sgy??1,s[0],s[1],!t.shiftKey,this.host._gridPitch,this.host._gridPitch),o=Math.abs(i.x-e.orig.x)>1e-6||Math.abs(i.y-e.orig.y)>1e-6||Math.abs(i.w-e.orig.w)>1e-6||Math.abs(i.h-e.orig.h)>1e-6;if(!o&&!e.moved)return;return e.moved||=o,void this._decorApplyBox(e.id,i)}if("scale"===e.kind){const t=Math.hypot(s[0]-e.ax,s[1]-e.ay);if(e.r0<1e-6)return;const i=Math.max(.1,Math.min(Ud,e.textSizeCm0*(t/e.r0))),o=Math.abs(i-e.textSizeCm0)>1e-6;if(!o&&!e.moved)return;return e.moved||=o,void this._dtApply(e.id,{textSizeCm:i})}const i=180*Math.atan2(s[1]-e.ay,s[0]-e.ax)/Math.PI;let o;"furniture"===e.origShape.kind||"image"===e.origShape.kind?o=Ls(e.angle0,e.a0,i,t.shiftKey):(o=e.angle0+(i-e.a0),t.shiftKey||(o=5*Math.round(o/5)),o=(o%360+360)%360,o>180&&(o-=360));const a=Math.abs(o-e.angle0)>1e-6;(a||e.moved)&&(e.moved||=a,this._dtApply(e.id,{angle:o}))}_dtUp(){const t=this.host._dtDrag;this.host._dtDrag=null,t?.moved&&(this._recordGeometry(this.host._t("history.decor_transform"),t.before),this._saveConfig()),this.host.requestUpdate()}_dtMeasure(){!function(t){const e=t,s=e._dtSel;if(!s)return void(e._dtBox&&(e._dtBox=null,e.requestUpdate()));if("text"!==s.kind)return;const i=e.renderRoot.querySelector(`text.dtext[data-id="${s.id}"]`);if(!i||"function"!=typeof i.getBBox)return;let o;try{o=i.getBBox()}catch{return}if(!o||!o.width&&!o.height)return;const a={id:s.id,x:o.x,y:o.y,w:o.width,h:o.height},n=e._dtBox;n?.id===a.id&&Math.abs(n.x-a.x)<.01&&Math.abs(n.y-a.y)<.01&&Math.abs(n.w-a.w)<.01&&Math.abs(n.h-a.h)<.01||(e._dtBox=a,e.requestUpdate())}(this.host)}_deleteDecor(t){if(!this.host._decorList.some(e=>e.id===t))return;const e=this._geometrySnapshot();this.host._curSpaceCfg.decor=this.host._decorList.filter(e=>e.id!==t),this.host._decorSel===t&&(this.host._decorSel=null),this._recordGeometry(this.host._t("history.decor_delete"),e),this._saveConfig(),this.host.requestUpdate()}_decorDeleteSel(){this.host._decorSel&&this._deleteDecor(this.host._decorSel)}_confirmDecorErase(){const t=this.host._decorEraseConfirm;this.host._decorEraseConfirm=null,t&&this._deleteDecor(t.id)}_furnFieldValue(t){return Math.round(100*(this.host._imperial?t/30.48:t/100))/100}_furnFieldToCm(t){return Ts(this.host._imperial?30.48*t:100*t)}_furnShiftAttach(){this._furnShiftAttached||(this._furnShiftAttached=!0,window.addEventListener("keydown",this._furnShiftListener),window.addEventListener("keyup",this._furnShiftListener))}_furnShiftDetach(){this._furnShiftAttached&&(this._furnShiftAttached=!1,window.removeEventListener("keydown",this._furnShiftListener),window.removeEventListener("keyup",this._furnShiftListener))}_furnPick(t){const e=Rs(t);this.host._furnPalette={symbol:t,w:e.w,h:e.h},this._furnShiftAttach()}get _furnWalls(){return function(t){const e=t._spaceModel();if(!e)return[];const s=[e.id,t._cfgEpoch,t._cellCm,t._gridPitch,t._wallKeyPitch].join("|"),i=Fh.get(t);if(i?.key===s)return i.value;const o=[...Rh(e.rooms,t._spaceWalls,t._openCuts(),t._wallKeyPitch,t._cellCm,t._gridPitch,pt),...zh(t._rawPhysicalBodiesR())];return Fh.set(t,{key:s,value:o}),o}(this.host)}_resolveFurniturePlacement(t,e=!1,s="mouse"){const i=this.host._furnPalette,o=this.host._curSpaceCfg;if(!i||!o)return null;const a=this.host._decorH,n=this._decorSnap(t,s);return function(t){const{symbol:e,widthCm:s,depthCm:i,point:o,canvasW:a,canvasH:n,cellCm:r,gridPitch:l,walls:h,wallReach:c,free:d=!1,intentPoint:p=o,preferredNormal:u}=t;if(!(se(e)&&n>0&&Number.isFinite(o[0])&&Number.isFinite(o[1])))return null;const _=Number.isFinite(p[0])&&Number.isFinite(p[1])?p:o,m=oe(ae(s,r,l,a)),g=oe(ae(i,r,l,a));let f=o[0],b=o[1],v=0;const y=d?null:Dh(f,b,g*n,h,c,l,_,u);return y&&(f=y.cx,b=y.cy,v=y.angle),{symbol:e,x:ie(f/a-m/2),y:ie(b/n-g/2),w:m,h:g,angle:Number(v.toFixed(2))}}({symbol:i.symbol,widthCm:i.w,depthCm:i.h,point:[n[0],n[1]],canvasW:1e3,canvasH:a,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,walls:this._furnWalls,wallReach:6*this.host._gridPitch,intentPoint:[t[0],t[1]],free:e})}_furniturePreviewPlacement(){const t=this.host._furnPreviewInput;return t&&"decor"===this.host._mode&&"furniture"===this.host._decorTool&&this.host._furnPalette&&this.host._pointerModality.hoverEnabled?this._resolveFurniturePlacement(t.raw,t.free,"mouse"):null}_renderFurniturePlacementPreview(t){const e=this._furniturePreviewPlacement();if(!e)return d;const s=Me(e.symbol);if(!s)return d;const i=zs(e,Vd,this.host._decorH,s.viewW,s.viewH),o=this.host._decorStyle,a=Fs(fe(o.widthCm,this.host._cellCm,this.host._gridPitch),t);return Tt`<path class="furniture-placement-preview dfurn"
|
||
data-symbol=${e.symbol} d=${s.d} transform=${i}
|
||
stroke=${o.color} stroke-opacity=${o.opacity}
|
||
stroke-width=${a}
|
||
fill="none" stroke-linecap="round" stroke-linejoin="round"
|
||
vector-effect="non-scaling-stroke" aria-hidden="true" pointer-events="none"></path>`}_furnLive(){const t=this.host._dtDrag;if(!t||"scale"!==t.kind||!t.orig)return null;const e=this.host._decorList.find(e=>e.id===t.id);if(!e||"furniture"!==e.kind)return null;const s=e.w*Vd,i=e.h*this.host._decorH,o=Ns(e.x*Vd,e.y*this.host._decorH,s,i,Number(e.angle)||0),a=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],n=a(o[0],o[1]),r=a(o[0],o[3]);return[{x:n[0],y:n[1],text:this.host._fmtLen([0,0],[s,0])},{x:r[0],y:r[1],text:this.host._fmtLen([0,0],[0,i])}]}_furnPlace(t,e=!1,s="mouse"){const i=this._resolveFurniturePlacement(t,e,s);if(!i)return;const o=this.host._curSpaceCfg;if(!o)return;const a=this._geometrySnapshot(),n="df"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),r={id:n,kind:"furniture",symbol:i.symbol,x:i.x,y:i.y,w:i.w,h:i.h,...Ms(this.host._decorStyle,!1)};i.angle&&(r.angle=i.angle),o.decor=[...this.host._decorList,r],this.host._decorSel=n,this.host._decorTool="select",this.host._furnPalette=null,this.host._furnCategory=null,this._furnShiftDetach(),this._clearFurniturePreview(),this._recordGeometry(this.host._t("history.decor_add"),a),this._saveConfig(),this.host.requestUpdate()}_clearFurniturePreview(){this.host._furnPreviewInput=null,this.host._furnTouchPending=null}_furnPointerMove(t,e){const s=this.host._furnTouchPending;if(s?.pid===t.pointerId)return Math.abs(t.clientX-s.sx)+Math.abs(t.clientY-s.sy)>8&&(s.cancelled=!0),this.host._furnPreviewInput=null,!0;const i="furniture"===this.host._decorTool?!!this.host._furnPalette:"image"===this.host._decorTool&&!!this.host._decorImagePalette;if("decor"!==this.host._mode||!i)return this._clearFurniturePreview(),!1;if("mouse"!==t.pointerType||!e)return this.host._furnPreviewInput=null,!1;const o=this._svgPoint(t);return this.host._furnPreviewInput={raw:[o[0],o[1]],free:t.shiftKey},!0}_furnPointerLeave(t){this.host._furnTouchPending?.pid===t.pointerId&&(this.host._furnTouchPending.cancelled=!0),this.host._furnPreviewInput=null}_furnPointerUp(t){const e=this.host._furnTouchPending;return!(!e||e.pid!==t.pointerId)&&(this.host._furnTouchPending=null,!e.cancelled&&"decor"===this.host._mode&&("furniture"===this.host._decorTool&&this.host._furnPalette||"image"===this.host._decorTool&&this.host._decorImagePalette)&&("furniture"===this.host._decorTool?this._furnPlace(this._svgPoint(t),t.shiftKey,e.pointerType):this._decorImagePlace(this._svgPoint(t),e.pointerType)),!0)}_furnMoveUpdate(t){const e=this.host._decorMove;if(!e)return;if("furniture"!==e.orig.kind)return;const s=e.orig,i=this.host._curSpaceCfg;if(!i)return;const o=Vd,a=this.host._decorH,n=this._svgPoint(t),r=(s.x+s.w/2)*o+(n[0]-e.start[0]),l=(s.y+s.h/2)*a+(n[1]-e.start[1]);let h,c,d=Number(s.angle)||0;const p=d*Math.PI/180,u=[-Math.sin(p),Math.cos(p)],_=t.shiftKey?null:Dh(r,l,s.h*a,this._furnWalls,6*this.host._gridPitch,this.host._gridPitch,[r,l],u);if(_)h=_.cx/o-s.w/2,c=_.cy/a-s.h/2,d=_.angle;else{const i=this._decorSnap([r-s.w/2*o,l-s.h/2*a],t.pointerType,e.id);h=i[0]/o,c=i[1]/a}h=ie(h),c=ie(c),(Math.abs(h-s.x)>1e-9||Math.abs(c-s.y)>1e-9||Math.abs(d-(Number(s.angle)||0))>1e-9)&&(e.moved=!0),i.decor=this.host._decorList.map(t=>{if(t.id!==e.id)return t;const s={...t,x:h,y:c};return d?s.angle=Number(d.toFixed(2)):delete s.angle,s}),this.host.requestUpdate()}_decorApplyBox(t,e){const s=this.host._curSpaceCfg;if(!s)return;const i=Vd,o=this.host._decorH;s.decor=this.host._decorList.map(s=>{if(s.id!==t)return s;const a=Ps(e,s.angle,t=>this._snap(t));return{...s,x:ie(a[0]/i),y:ie(a[1]/o),w:Math.max(this.host._gridPitch/i,Math.min(2*$e,e.w/i)),h:Math.max(this.host._gridPitch/o,Math.min(2*$e,e.h/o))}}),this.host._cfgEpoch++,this.host.requestUpdate()}_decorApplyFurnitureBox(t,e){const s=this.host._curSpaceCfg;if(!s)return;const i=Vd,o=this.host._decorH,a=fe(.1,this.host._cellCm,this.host._gridPitch);s.decor=this.host._decorList.map(s=>{if(s.id!==t||"furniture"!==s.kind&&"image"!==s.kind)return s;const{flip_h:n,flip_v:r,...l}=s;return{...l,x:ie(e.x/i),y:ie(e.y/o),w:Math.max(a/i,Math.min(2*$e,e.w/i)),h:Math.max(a/o,Math.min(2*$e,e.h/o)),...e.flip_h?{flip_h:!0}:{},...e.flip_v?{flip_v:!0}:{}}}),this.host._cfgEpoch++,this.host.requestUpdate()}_decorImagePlace(t,e="mouse"){this._decorImages.place(t,e)}_renderDecorImagePlacementPreview(){return this._decorImages.renderPlacementPreview()}_renderMissingDecorImage(t,e,s,i,o,a,n,r,l){return this._decorImages.renderMissing(t,e,s,i,o,a,n,r,l)}async _decorImageUpload(t,e=!1){await this._decorImages.uploadFromInput(t,e)}async _uploadDecorImage(t,e,s){await this._decorImages.upload(t,e,s)}async _decorImageDelete(t){await this._decorImages.delete(t)}async _decorImageCatalogLoad(){await this._decorImages.loadCatalog()}_renderDecorImagePalette(){return this._decorImages.renderImagePalette()}_renderFurnPalette(){return this._decorImages.renderFurniturePalette()}_openBackdropDialog(t){if(!this.host._bdMovable||!this.host._bdRect)return;t?.preventDefault(),t?.stopPropagation(),this.host._bdDrag=null;const e=this.host._bdRect;this.host._backdropDialog={widthCm:$s(e.w,this.host._cellCm,this.host._gridPitch),heightCm:$s(e.h,this.host._cellCm,this.host._gridPitch),angle:this.host._angleField(e.angle)}}_saveBackdropDialog(){const t=this.host._backdropDialog,e=this.host._bdBase,s=this.host._bdRect;if(!t||!e||!s)return;const i=ks(t.angle),o=this._geometrySnapshot(),a=Math.min(e.w*ft,Math.max(e.w*gt,qe(fe(t.widthCm,this.host._cellCm,this.host._gridPitch),this.host._gridPitch))),n=Math.min(e.h*ft,Math.max(e.h*gt,qe(fe(t.heightCm,this.host._cellCm,this.host._gridPitch),this.host._gridPitch))),r=s.x+s.w/2,l=s.y+s.h/2,h=Ps({x:r-a/2,y:l-n/2},i,t=>this._snap(t));this._bdApply((h[0]-e.x)/Vd,(h[1]-e.y)/Vd,a/e.w,n/e.h,i),this.host._backdropDialog=null,this._recordGeometry(this.host._t("history.backdrop_transform"),o),this._saveConfig()}_bdApply(t,e,s,i,o){const a=this.host._curSpaceCfg;if(!a)return;a.plan_x=Number(ie(t).toFixed(6)),a.plan_y=Number(ie(e).toFixed(6)),delete a.plan_scale,a.plan_scale_x=Number(Math.min(ft,Math.max(gt,s)).toFixed(6)),a.plan_scale_y=Number(Math.min(ft,Math.max(gt,i)).toFixed(6));const n=ks(o);n?a.plan_angle=Number(n.toFixed(2)):delete a.plan_angle,this.host._cfgEpoch++,this.host.requestUpdate()}_bdStart(t,e,s=!1){const i=this.host._bdBase,o=this.host._bdRect;if(!i||!o)return!1;const a=this._svgPoint(t),n=e?e[0]:0,r=e?e[1]:0,l=n>0?o.x:o.x+o.w,h=r>0?o.y:o.y+o.h;return this.host._bdDrag={kind:s?"rotate":e?"scale":"move",pid:t.pointerId,sx:a[0],sy:a[1],base:i,p0:this.host._bdParams,fx:l,fy:h,sgx:n,sgy:r,rect0:{x:o.x,y:o.y,w:o.w,h:o.h,angle:o.angle},before:this._geometrySnapshot(),moved:!1},Zd(t),!0}_bdMove(t){zr(this.host,"backdrop",()=>this._bdMoveNow(t))}_bdMoveNow(t){const e=this.host._bdDrag;if(!e)return;const s=this._svgPoint(t),i=e.base;if("move"===e.kind){const t=e.rect0.x,o=e.rect0.y,a=this._snap([t+(s[0]-e.sx),o+(s[1]-e.sy)]),n=Math.abs(a[0]-t)>1e-9||Math.abs(a[1]-o)>1e-9;if(!n&&!e.moved)return;return e.moved||=n,void this._bdApply((a[0]-i.x)/Vd,(a[1]-i.y)/Vd,e.p0.sx,e.p0.sy,e.p0.angle)}if("rotate"===e.kind){const i=e.rect0.x+e.rect0.w/2,o=e.rect0.y+e.rect0.h/2,a=180*Math.atan2(e.sy-o,e.sx-i)/Math.PI;let n=e.p0.angle+(180*Math.atan2(s[1]-o,s[0]-i)/Math.PI-a);t.shiftKey||(n=5*Math.round(n/5)),n=ks(n);const r=Math.abs(n-e.p0.angle)>1e-9;if(!r&&!e.moved)return;return e.moved||=r,void this._bdApply(e.p0.dx,e.p0.dy,e.p0.sx,e.p0.sy,n)}const o=Ds(e.rect0,e.sgx,e.sgy,s[0],s[1],!t.shiftKey,this.host._gridPitch,Math.min(i.w,i.h)*gt),a=o.w/Math.max(1e-9,i.w),n=o.h/Math.max(1e-9,i.h),r=Math.abs(a-e.p0.sx)>1e-9||Math.abs(n-e.p0.sy)>1e-9||Math.abs(o.x-e.rect0.x)>1e-9||Math.abs(o.y-e.rect0.y)>1e-9;if(!r&&!e.moved)return;e.moved||=r;const l=Ps(o,e.p0.angle,t=>this._snap(t));this._bdApply((l[0]-i.x)/Vd,(l[1]-i.y)/Vd,a,n,e.p0.angle)}_bdReset(){const t=this.host._curSpaceCfg;if(!t)return;const e=this._geometrySnapshot();delete t.plan_x,delete t.plan_y,delete t.plan_scale,delete t.plan_scale_x,delete t.plan_scale_y,delete t.plan_angle,this.host._bdDrag=null,this._recordGeometry(this.host._t("history.backdrop_transform"),e),this._saveConfig(),this.host._showToast(this.host._t("decor.backdrop_reset_done")),this.host.requestUpdate()}_bdUp(){Fr(this.host,"backdrop");const t=this.host._bdDrag;this.host._bdDrag=null,t?.moved&&(this._recordGeometry(this.host._t("history.backdrop_transform"),t.before),this._saveConfig()),this.host.requestUpdate()}_renderBackdropFrame(t){const e=this.host._bdRect;if(!this.host._bdActive||!e)return d;const s=.02*Math.max(t.w,t.h),i=s/4,o=e.x+e.w/2,a=e.y+e.h/2,n=ks(e.angle),r=2.2*s;return Tt`<g class="bdframe" transform=${n?`rotate(${n} ${o} ${a})`:d}>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<rect class="bdbox" x="${e.x}" y="${e.y}" width="${e.w}" height="${e.h}"></rect>
|
||
<line class="dtstem" x1="${o}" y1="${e.y}" x2="${o}" y2="${e.y-r}"></line>
|
||
<circle class="bdhandle dtrot" cx="${o}" cy="${e.y-r}" r="${i.toFixed(1)}"
|
||
@pointerdown=${t=>{t.stopPropagation(),t.preventDefault(),this._bdStart(t,void 0,!0)}}></circle>
|
||
<circle class="bdknob" cx="${o}" cy="${e.y-r}" r="${s.toFixed(2)}"></circle>
|
||
${[[-1,-1,"nwse"],[1,-1,"nesw"],[1,1,"nwse"],[-1,1,"nesw"]].map(([t,o,a])=>{const n=t<0?e.x:e.x+e.w,r=o<0?e.y:e.y+e.h;return Tt`<circle
|
||
class="bdhandle bd-${a}" data-corner="${t+","+o}"
|
||
cx="${n}" cy="${r}" r="${i.toFixed(1)}"
|
||
@pointerdown=${e=>{e.stopPropagation(),e.preventDefault(),this._bdStart(e,[t,o])}}></circle><circle class="bdknob" cx="${n}" cy="${r}" r="${s.toFixed(2)}"></circle>`})}
|
||
</g>`}_renderEditorGroupLauncher(t){return this.host._editorSecondary.renderGroupLauncher(t,this.host._editorToolbarGroups,this.host._editorSecondaryCopy)}_runEditorContext(t,e){return this.host._editorSecondary.runContext(t,this.host._editorSecondaryContextId,e)}_renderEditorGroupModel(t){return this.host._editorSecondary.renderGroupModel(t,this.host._editorSecondaryContextId,this.host._editorSecondaryCopy)}_renderDrawWallControl(){const t="column"===this.host._tool?1:0;return p`<label class="drawwall ${null==this.host._drawWallCm?"invalid":""}">${this.host._t("wallthick.field")}
|
||
<input type="number" min=${Ue(t,this.host._imperial)}
|
||
max=${Ue(this.host._drawWallMaxCm,this.host._imperial)} step="any"
|
||
.value=${this.host._drawWallFieldValue}
|
||
@input=${t=>{this.host._drawWallField=t.target.value}}
|
||
title=${this.host._t("draw"===this.host._tool?"markup.draw_wall_title":"physical.column_size_title")} />
|
||
<span class="opl">${this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}</span>
|
||
<span class="rangehint">${this.host._t("physical.allowed_range",{min:Ue(t,this.host._imperial),max:Ue(this.host._drawWallMaxCm,this.host._imperial),unit:this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")})}</span>
|
||
</label>`}_renderPlanSecondary(){const t=this.host._editorSecondaryContextId,e=this.host._physicalSel;if(e){if(!("partition"===e.kind?!!this.host._curSpaceCfg.partitions?.some(t=>t.id===e.id):!!this.host._curSpaceCfg.wall_columns?.some(t=>t.id===e.id)))return null;const i="partition"===e.kind?this.host._t("markup.partition"):"column"===e.kind?this.host._t("markup.column"):this.host._t("markup.add");return{contextId:t,kind:"selection",ariaLabel:this.host._t("editor.context_actions",{object:i}),visibleLabel:i,content:p`
|
||
<button class="btn ghost" @click=${()=>this._runEditorContext(t,()=>{const t=this.host._physicalSel;t&&this._openPhysicalDialog(t.kind,t.id)})}><ha-icon icon="mdi:tune"></ha-icon>${this.host._t("btn.properties")}</button>
|
||
<button class="btn danger" @click=${()=>this._runEditorContext(t,()=>this._deletePhysicalSelection())}>
|
||
<ha-icon icon="mdi:delete-outline"></ha-icon>${this.host._t("btn.delete")}
|
||
</button>`}}const i="draw"===this.host._tool||"column"===this.host._tool,s="column"===this.host._tool?"markup.hint_column":"resize"===this.host._tool?"markup.hint_resize":"wallthick"===this.host._tool?"markup.hint_wallthick":null,o="draw"===this.host._tool?this.host._t(this.host._path.length?"markup.hint_points":"markup.hint_start",this.host._path.length?{n:this.host._path.length}:void 0):"";if(!i&&!s&&!o)return null;const a="draw"===this.host._tool&&this.host._path.length>0;return{contextId:t,kind:a?"operation":"tool",ariaLabel:this.host._t("editor.tool_options",{tool:this.host._t("draw"===this.host._tool?"markup.add":"column"===this.host._tool?"markup.column":"resize"===this.host._tool?"markup.resize":"markup.wallthick")}),content:p`
|
||
${i?this._renderDrawWallControl():d}
|
||
${o?p`<span class="hint">${o}</span>`:d}
|
||
${s?p`<span class="hint">${this.host._t(s)}</span>`:d}
|
||
${"draw"===this.host._tool&&this.host._path.length?p`<button class="btn ghost" @click=${()=>this._runEditorContext(t,()=>{this._finishWallChain()&&this.host.requestUpdate()})}>
|
||
${this.host._t("btn.reset")}
|
||
</button>`:d}`}}_renderDecorSecondary(){const t=this.host._editorSecondaryContextId;if("furniture"===this.host._decorTool)return{contextId:t,kind:"palette",ariaLabel:this.host._t("editor.palette",{tool:this.host._t("decor.furniture")}),launcherId:"furniture",dismissPolicy:this.host._furnPalette?"stay-open-on-canvas":"outside",dismiss:()=>{"furniture"===this.host._decorTool&&(this._clearFurniturePreview(),this.host._furnPalette=null,this._furnShiftDetach(),this.host._furnCategory=null,this.host._decorTool="select",this.host.requestUpdate())},content:this._renderFurnPalette()};if("image"===this.host._decorTool)return{contextId:t,kind:"palette",ariaLabel:this.host._t("editor.palette",{tool:this.host._t("decor.image")}),launcherId:"image",dismissPolicy:this.host._decorImagePalette?"stay-open-on-canvas":"outside",dismiss:()=>{"image"===this.host._decorTool&&(this._clearFurniturePreview(),this.host._decorImagePalette=null,this.host._decorTool="select",this.host.requestUpdate())},content:this._renderDecorImagePalette()};const e=this.host._dtSel;if(e){const i=this.host._t(`decor.${e.kind}`);return{contextId:t,kind:"selection",ariaLabel:this.host._t("editor.context_actions",{object:i}),visibleLabel:i,content:p`
|
||
<button class="btn ghost" @click=${()=>this._runEditorContext(t,()=>{const t=this.host._dtSel;t&&this._openDecorProperties(t)})}><ha-icon icon="mdi:tune"></ha-icon>${this.host._t("btn.properties")}</button>
|
||
<button class="btn danger" @click=${()=>this._runEditorContext(t,()=>this._decorDeleteSel())}>
|
||
<ha-icon icon="mdi:delete-outline"></ha-icon>${this.host._t("btn.delete")}
|
||
</button>`}}const i="line"===this.host._decorTool||"rect"===this.host._decorTool||"ellipse"===this.host._decorTool,s="rect"===this.host._decorTool||"ellipse"===this.host._decorTool,o="backdrop"===this.host._decorTool&&!!this.host._bdRect;return i||o?{contextId:t,kind:"tool",ariaLabel:this.host._t("editor.tool_options",{tool:this.host._t(i?`decor.${this.host._decorTool}`:"decor.backdrop")}),content:p`
|
||
${i?p`
|
||
<hp-color-opacity .label=${this.host._t("decor.color")} .color=${this.host._decorStyle.color}
|
||
.opacity=${this.host._decorStyle.opacity} .opacityLabel=${this.host._t("space.opacity")}
|
||
.pickerLabels=${this.host._colorPickerLabels}
|
||
@hp-color-opacity-change=${t=>this._updateDecorStyle({...this.host._decorStyle,...t.detail})}></hp-color-opacity>
|
||
<label class="drawwall">${this.host._t("decor.width")}
|
||
<input type="number" min=${this.host._decorSmallField(.1)}
|
||
max=${this.host._decorSmallField(100)} step="0.1"
|
||
.value=${String(this.host._decorSmallField(this.host._decorStyle.widthCm))}
|
||
@input=${t=>this._updateDecorStyle({...this.host._decorStyle,widthCm:this.host._decorSmallCm(Number(t.target.value))})} />
|
||
<span class="opl">${this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}</span>
|
||
</label>
|
||
${s?p`<label class="dfill"><input type="checkbox" .checked=${this.host._decorStyle.fill}
|
||
@change=${t=>this._updateDecorStyle({...this.host._decorStyle,fill:t.target.checked})} />${this.host._t("decor.fill")}</label>
|
||
<hp-color-opacity .label=${this.host._t("decor.fill_color")} .color=${this.host._decorStyle.fillColor}
|
||
.opacity=${this.host._decorStyle.fillOpacity} .opacityLabel=${this.host._t("space.opacity")}
|
||
.pickerLabels=${this.host._colorPickerLabels}
|
||
.disabled=${!this.host._decorStyle.fill}
|
||
@hp-color-opacity-change=${t=>this._updateDecorStyle({...this.host._decorStyle,fillColor:t.detail.color,fillOpacity:t.detail.opacity})}></hp-color-opacity>`:d}
|
||
`:d}
|
||
${o?p`<span class="bdhint">${this.host._t("decor.backdrop_hint")}</span>`:d}`}:null}_withBackdropReset(t){if(!this.host._bdMoved||this.host._bdDrag||"palette"===t?.kind)return t;const e=this.host._editorSecondaryContextId,i=p`<button class="btn bdreset" title=${this.host._t("decor.backdrop_reset")}
|
||
@click=${()=>this._runEditorContext(e,()=>this._bdReset())}>
|
||
<ha-icon icon="mdi:image-refresh-outline"></ha-icon>${this.host._t("decor.backdrop_reset")}
|
||
</button>`;return t?{...t,kind:"selection"===t.kind?"mixed":t.kind,content:p`${t.content}${i}`}:{contextId:e,kind:"tool",ariaLabel:this.host._t("editor.tool_options",{tool:this.host._t("decor.backdrop")}),content:i}}_renderEditorSecondary(){if(!this.host._editing)return d;const t=this.host._editorSecondary.activeGroup(this.host._editorToolbarGroups),e=t?this._renderEditorGroupModel(t):"plan"===this.host._mode?this._renderPlanSecondary():"decor"===this.host._mode?this._withBackdropReset(this._renderDecorSecondary()):null;return this.host._editorSecondary.render(e,this.host._editorSecondaryDialogBlocked)}_renderDecorBar(){const t=[["select","mdi:cursor-default-outline","decor.select"],...this.host._bdRect?[["backdrop","mdi:image-move","decor.backdrop"]]:[],["line","mdi:vector-line","decor.line"],["rect","mdi:rectangle-outline","decor.rect"],["ellipse","mdi:ellipse-outline","decor.ellipse"],["text","mdi:format-text","decor.text"],["furniture","mdi:sofa-outline","decor.furniture"],...this.host._haDecorAssetsApi===Oi?[["image","mdi:image-plus-outline","decor.image"]]:[],["erase","mdi:eraser","decor.erase"]],e=this.host._geometryHistory.undoName,i=this.host._geometryHistory.redoName;return p`<div class="editbar decorbar" data-hp="toolbar" data-kind="decor">
|
||
<div class="editbar-tools" tabindex="-1" ?inert=${this.host._modeTransitionBusy}>
|
||
${t.map(([t,e,i])=>p`<button class="btn dtool ${this.host._decorTool===t?"on":""}" data-hp="tool" data-tool=${t}
|
||
data-editor-palette=${"furniture"===t||"image"===t?t:d}
|
||
@click=${()=>{if(("furniture"===t||"image"===t)&&this.host._decorTool===t)return this._clearFurniturePreview(),this.host._furnPalette=null,this.host._decorImagePalette=null,this._furnShiftDetach(),this.host._furnCategory=null,void(this.host._decorTool="select");"furniture"!==t&&"image"!==t||this.host._editorSecondary.openPalette(),"image"===t&&this._decorImageCatalogLoad(),this.host._decorTool=t,this.host._decorDraft=null,"furniture"!==t?(this._clearFurniturePreview(),this.host._furnPalette=null,this._furnShiftDetach(),this.host._furnCategory=null):(this._clearFurniturePreview(),this.host._furnCategory=null),"image"!==t&&(this.host._decorImagePalette=null)}}
|
||
title=${this.host._t(i)}>
|
||
<ha-icon icon=${e}></ha-icon><span class="ml">${this.host._t(i)}</span>
|
||
</button>`)}
|
||
${this.host._editorToolbarGroups.map(t=>this._renderEditorGroupLauncher(t))}
|
||
<hp-color-opacity class="decor-default-color"
|
||
.label=${this.host._t("decor.color")}
|
||
.color=${this.host._decorStyle.color}
|
||
.opacity=${this.host._decorStyle.opacity}
|
||
.opacityLabel=${this.host._t("space.opacity")}
|
||
.pickerLabels=${this.host._colorPickerLabels}
|
||
@hp-color-opacity-change=${t=>this._updateDecorStyle({...this.host._decorStyle,...t.detail})}>
|
||
</hp-color-opacity>
|
||
<button class="btn ghost" @click=${()=>this._undoGeometry()} ?disabled=${!e}
|
||
title=${e?this.host._t("history.undo_named",{name:e}):this.host._t("history.undo_empty")}>
|
||
<ha-icon icon="mdi:undo-variant"></ha-icon>${this.host._t("history.undo")}
|
||
</button>
|
||
<button class="btn ghost" @click=${()=>this._redoGeometry()} ?disabled=${!i}
|
||
title=${i?this.host._t("history.redo_named",{name:i}):this.host._t("history.redo_empty")}>
|
||
<ha-icon icon="mdi:redo-variant"></ha-icon>${this.host._t("history.redo")}
|
||
</button>
|
||
</div>
|
||
<div class="editbar-end">
|
||
<button class="btn barclose" title=${this.host._t("title.close_editor")} data-hp="editor-close"
|
||
data-editor-navigation="view"
|
||
@click=${()=>this._setMode("view")}>
|
||
<ha-icon icon="mdi:close"></ha-icon>
|
||
</button>
|
||
</div>
|
||
</div>`}_renderDecorEraseConfirm(){const t=this.host._decorEraseConfirm,e=this.host._t(`decor.${t.kind}`);return p`<hp-dialog .hass=${this.host.hass} data-kind="confirm" .title=${this.host._t("decor.erase_confirm_title")}
|
||
icon="mdi:eraser" dismiss-on-scrim @hp-close=${()=>this.host._decorEraseConfirm=null}>
|
||
<div class="body"><p>${this.host._t("confirm.erase_decor",{kind:e})}</p></div>
|
||
<div class="row" slot="footer">
|
||
<span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._decorEraseConfirm=null}>
|
||
${this.host._t("btn.cancel")}
|
||
</button>
|
||
<button class="btn danger" data-hp="dialog-confirm" @click=${()=>this._confirmDecorErase()}>
|
||
<ha-icon icon="mdi:eraser"></ha-icon>${this.host._t("decor.erase")}
|
||
</button>
|
||
</div>
|
||
</hp-dialog>`}_renderDecorTextDialog(){const t=this.host._decorTextDialog,e=(t.pickerEntity||"").trim(),i=e?this.host.hass?.states?.[e]:null;return p`<hp-dialog .hass=${this.host.hass} data-kind="decor" .title=${this.host._t("decor.text_title")}
|
||
icon="mdi:format-text" dismiss-on-scrim @hp-close=${()=>this.host._decorTextDialog=null}>
|
||
<div class="body">
|
||
<label>${this.host._t("decor.text_label")}</label>
|
||
${""}
|
||
<textarea class="namein dtarea" rows="3" maxlength="200" .value=${t.text} autofocus
|
||
@input=${e=>{const i=e.target;this._decorRememberTextSelection(i),this.host._decorTextDialog={...t,text:i.value}}}
|
||
@click=${t=>this._decorRememberTextSelection(t.target)}
|
||
@keyup=${t=>this._decorRememberTextSelection(t.target)}
|
||
@select=${t=>this._decorRememberTextSelection(t.target)}
|
||
@blur=${t=>this._decorRememberTextSelection(t.target)}
|
||
@keydown=${t=>{t.stopPropagation(),"Enter"===t.key&&(t.ctrlKey||t.metaKey)&&this._decorSaveText()}}></textarea>
|
||
<hp-color-opacity .label=${this.host._t("decor.color")} .color=${t.color} .opacity=${t.opacity}
|
||
.opacityLabel=${this.host._t("space.opacity")} .pickerLabels=${this.host._colorPickerLabels}
|
||
@hp-color-opacity-change=${e=>this.host._decorTextDialog={...t,...e.detail}}></hp-color-opacity>
|
||
<label>${this.host._t("decor.text_size")}</label>
|
||
<div class="colorrow"><input class="namein" type="number" min="0.1"
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
max=${this.host._decorSmallField(Zd)} step="0.1"
|
||
========
|
||
max=${this.host._decorSmallField(Ud)} step="0.1"
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
.value=${String(this.host._decorSmallField(t.sizeCm))}
|
||
@input=${e=>this.host._decorTextDialog={...t,sizeCm:this.host._decorTextCm(Number(e.target.value))}} />
|
||
<span class="opl">${this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}</span></div>
|
||
<label>${this.host._t("decor.angle")}</label>
|
||
<input class="namein" type="number" min="-180" max="180" step="1" .value=${t.angle}
|
||
@input=${e=>this.host._decorTextDialog={...t,angle:e.target.value}} />
|
||
<label class="dispsection">${this.host._t("decor.live_group")}</label>
|
||
<label>${this.host._t("decor.live_entity")}</label>
|
||
<input class="namein" type="text" list="hp-dtext-ents" placeholder=${this.host._t("decor.live_entity_ph")}
|
||
.value=${t.pickerEntity||""}
|
||
@input=${e=>this.host._decorTextDialog={...t,pickerEntity:e.target.value}} />
|
||
<datalist id="hp-dtext-ents">
|
||
${Object.keys(this.host.hass?.states||{}).map(t=>p`<option value=${t}></option>`)}
|
||
</datalist>
|
||
${e?p`
|
||
<label>${this.host._t("decor.live_attr")}</label>
|
||
<select id="decor-live-attribute" class="namein" .value=${""}
|
||
@change=${t=>{const e=t.target.value;e&&this._decorInsertLiveVariable("__state__"===e?null:e)}}>
|
||
<option value="">${this.host._t("decor.live_attr_ph")}</option>
|
||
<option value="__state__">${this.host._t("decor.live_state")}</option>
|
||
${Object.keys(i?.attributes||{}).filter(t=>!!wt(e,t)).map(t=>p`<option value=${t}>${t}</option>`)}
|
||
</select>
|
||
`:d}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._decorTextDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<button class="btn primary" data-hp="dialog-confirm" ?disabled=${!t.text.trim()} @click=${()=>this._decorSaveText()}>${this.host._t("btn.save")}</button>
|
||
</div>
|
||
</hp-dialog>`}_renderDecorShapeDialog(){return this._decorImages.renderShapeDialog()}_renderBackdropDialog(){const t=this.host._backdropDialog,e=this.host._t(this.host._imperial?"gs.unit_ft":"gs.unit_m");return p`<hp-dialog .hass=${this.host.hass} data-kind="decor" .title=${this.host._t("decor.backdrop_properties")}
|
||
icon="mdi:image-edit-outline" dismiss-on-scrim @hp-close=${()=>this.host._backdropDialog=null}>
|
||
<div class="body">
|
||
<label>${this.host._t("decor.size")}</label>
|
||
<div class="colorrow"><input class="namein" type="number" min="0.01" step="0.01"
|
||
.value=${String(this.host._decorLargeField(t.widthCm))}
|
||
@input=${e=>this.host._backdropDialog={...t,widthCm:this.host._decorLargeCm(Number(e.target.value))}} />
|
||
<span>×</span><input class="namein" type="number" min="0.01" step="0.01"
|
||
.value=${String(this.host._decorLargeField(t.heightCm))}
|
||
@input=${e=>this.host._backdropDialog={...t,heightCm:this.host._decorLargeCm(Number(e.target.value))}} />
|
||
<span class="opl">${e}</span></div>
|
||
<label>${this.host._t("decor.angle")}</label>
|
||
<input class="namein" type="number" min="-180" max="180" step="1" .value=${t.angle}
|
||
@input=${e=>this.host._backdropDialog={...t,angle:e.target.value}} />
|
||
</div>
|
||
<div class="row" slot="footer"><span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._backdropDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<button class="btn primary" data-hp="dialog-confirm" @click=${()=>this._saveBackdropDialog()}>${this.host._t("btn.save")}</button>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}_cssPxToRender(t){const e=this.host._stageEl,i=this.host._viewOr(this.host._baseVb());return e?.clientWidth&&e.clientHeight?Math.max(i.w/e.clientWidth,i.h/e.clientHeight)*t:this.host._gridPitch/8*t}_deleteRoomClick(t){const e=this.host._spaceModel();if(!e)return;const i=[...e.rooms].reverse().find(e=>this._pointInRoom(t,e));i?i.id&&(this.host._roomDeleteDialog={roomId:i.id,name:i.name}):this.host._showToast(this.host._t("toast.delete_room_pick"))}_wallThickHit(t){const e=this.host._spaceModel();if(!e)return null;const i=6*this.host._gridPitch,s=this.host._openCuts();let o=null;const a=(t,e,s)=>{e>i||(!o||e<o.d-1e-9||s&&!o.independent&&e<=o.d+1e-9)&&(o={hit:t,d:e,independent:s})};for(const i of G(e.rooms,this.host._spaceWalls,s,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd))a({a:i.a,b:i.b,roomId:i.roomId,segs:[[i.a[0],i.a[1],i.b[0],i.b[1]]],open:i.open,cm:i.cm,source:{kind:"room"}},ge(t,[i.a[0],i.a[1],i.b[0],i.b[1]]),!1);for(const i of e.partitions||[]){const e=[i.a[0],i.a[1]],s=[i.b[0],i.b[1]];a({a:e,b:s,roomId:"",segs:[[e[0],e[1],s[0],s[1]]],open:!1,cm:Number(i.cm)||0,source:{kind:"partition",id:i.id}},ge(t,[e[0],e[1],s[0],s[1]]),!0)}return o?o.hit:null}_wallThickClick(t){const e=this._wallThickHit(t);if(!e)return void this.host._showToast(this.host._t("toast.wallthick_pick"));const i=e.cm,s=this.host._viewOr(this.host._baseVb()),o=(e.a[0]+e.b[0])/2,a=(e.a[1]+e.b[1])/2;this.host._wallDialog={a:e.a,b:e.b,value:Ue(i,this.host._imperial),roomId:e.roomId,source:e.source,sx:(o-s.x)/s.w*100,sy:(a-s.y)/s.h*100}}_wallThickApply(t){const e=this.host._wallDialog;if(!e)return;const i=this.host._curSpaceCfg,s=this.host._spaceModel();if(!i||!s)return;const o=e.value.trim(),a=o?Mt(o):null;if(null==a)return void this._showPhysicalRange(100);const n=this.host._imperial?2.54*a:a;if(!Number.isFinite(n)||n<0||n>100)return void this._showPhysicalRange(100);if("room"!==e.source.kind){const t=this._geometrySnapshot(),s=(i.partitions||[]).find(t=>t.id===e.source.id);if(!s)return;if(0===n&&Te(i.openings,{kind:"partition",id:s.id}))return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"));s.cm=n,this.host._wallDialog=null;return this._commitPhysicalGeometry(this.host._t("history.wall_thickness"),t)&&this.host._showToast(this.host._t("toast.wallthick_set")),void this.host.requestUpdate()}const r=this._geometrySnapshot(),l=n>0?n:null;if(0===n){const s=.02*this.host._gridPitch,o=[e.a[0],e.a[1],e.b[0],e.b[1]],a=(i.rooms||[]).find(t=>t.id===e.roomId),n=new Set(t&&a&&Array.isArray(a.wall_ids)?a.wall_ids:(i.wall_segments||[]).filter(t=>{const e=[Number(t.a?.[0])*Qd,Number(t.a?.[1])*Qd],i=[Number(t.b?.[0])*Qd,Number(t.b?.[1])*Qd];return ge(e,o)<=s&&ge(i,o)<=s}).map(t=>String(t.id))),r=(i.openings||[]).some(t=>{if("partition"===t.host?.kind)return!1;if("wall"===t.host?.kind&&n.has(t.host.id))return!0;if(t.host)return!1;const e=[Number(t.x)*Qd,Number(t.y)*Qd];return e.every(Number.isFinite)&&ge(e,o)<=s});if(r)return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"))}let h,c=this.host._openCuts();if(n>0&&c.length){const o=[];if(t&&e.roomId){const t=(i.rooms||[]).find(t=>t.id===e.roomId),a=new Set(Array.isArray(t?.wall_ids)?t.wall_ids:[]);for(const t of i.wall_segments||[])a.has(t.id)&&o.push([Number(t.a?.[0])*Qd,Number(t.a?.[1])*Qd,Number(t.b?.[0])*Qd,Number(t.b?.[1])*Qd]);if(!o.length){const t=s.rooms.find(t=>t.id===e.roomId),i=t?B(t):null;for(let t=0;i&&t<i.length;t++){const e=i[t],s=i[(t+1)%i.length];o.push([e[0],e[1],s[0],s[1]])}}}else o.push([e.a[0],e.a[1],e.b[0],e.b[1]]);const a=.02*this.host._gridPitch;c=c.filter(t=>!o.some(e=>ge([t[0],t[1]],e)<=a&&ge([t[2],t[3]],e)<=a&&ge([e[0],e[1]],t)<=a&&ge([e[2],e[3]],t)<=a))}h=t&&e.roomId?Bi(i.walls,s.rooms,e.roomId,l,this.host._wallKeyPitch,c,Qd):K(i.walls,e.a,e.b,l,this.host._wallKeyPitch,Qd),h=this.host._normalizeWalls(h,c);for(const t of i.wall_segments||[])t.cm=rt(h,t.a,t.b,A,1);h.length?i.walls=h:delete i.walls,this.host._wallDialog=null,this._commitPhysicalGeometry(this.host._t("history.wall_thickness"),r)&&this.host._showToast(this.host._t(0===n?"toast.wallthick_cleared":"toast.wallthick_set")),this.host.requestUpdate()}_wallHatchDefs(t){if(!this.host._spaceWalls.length&&!this.host._physicalBodiesR().length&&!this.host._markup)return Tt``;const e=Nt(this.host._cellCm);return Tt`<defs>
|
||
========
|
||
</hp-dialog>`}_cssPxToRender(t){const e=this.host._stageEl,s=this.host._viewOr(this.host._baseVb());return e?.clientWidth&&e.clientHeight?Math.max(s.w/e.clientWidth,s.h/e.clientHeight)*t:this.host._gridPitch/8*t}_deleteRoomClick(t){const e=this.host._spaceModel();if(!e)return;const s=[...e.rooms].reverse().find(e=>this._pointInRoom(t,e));s?s.id&&(this.host._roomDeleteDialog={roomId:s.id,name:s.name}):this.host._showToast(this.host._t("toast.delete_room_pick"))}_wallThickHit(t){const e=this.host._spaceModel();if(!e)return null;const s=6*this.host._gridPitch,i=this.host._openCuts();let o=null;const a=(t,e,i)=>{e>s||(!o||e<o.d-1e-9||i&&!o.independent&&e<=o.d+1e-9)&&(o={hit:t,d:e,independent:i})};for(const s of j(e.rooms,this.host._spaceWalls,i,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd))a({a:s.a,b:s.b,roomId:s.roomId,segs:[[s.a[0],s.a[1],s.b[0],s.b[1]]],open:s.open,cm:s.cm,source:{kind:"room"}},me(t,[s.a[0],s.a[1],s.b[0],s.b[1]]),!1);for(const s of e.partitions||[]){const e=[s.a[0],s.a[1]],i=[s.b[0],s.b[1]];a({a:e,b:i,roomId:"",segs:[[e[0],e[1],i[0],i[1]]],open:!1,cm:Number(s.cm)||0,source:{kind:"partition",id:s.id}},me(t,[e[0],e[1],i[0],i[1]]),!0)}return o?o.hit:null}_wallThickClick(t){const e=this._wallThickHit(t);if(!e)return void this.host._showToast(this.host._t("toast.wallthick_pick"));const s=e.cm,i=this.host._viewOr(this.host._baseVb()),o=(e.a[0]+e.b[0])/2,a=(e.a[1]+e.b[1])/2;this.host._wallDialog={a:e.a,b:e.b,value:je(s,this.host._imperial),roomId:e.roomId,source:e.source,sx:(o-i.x)/i.w*100,sy:(a-i.y)/i.h*100}}_wallThickApply(t){const e=this.host._wallDialog;if(!e)return;const s=this.host._curSpaceCfg,i=this.host._spaceModel();if(!s||!i)return;const o=e.value.trim(),a=o?Mt(o):null;if(null==a)return void this._showPhysicalRange(100);const n=this.host._imperial?2.54*a:a;if(!Number.isFinite(n)||n<0||n>100)return void this._showPhysicalRange(100);if("room"!==e.source.kind){const t=this._geometrySnapshot(),i=(s.partitions||[]).find(t=>t.id===e.source.id);if(!i)return;if(0===n&&Le(s.openings,{kind:"partition",id:i.id}))return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"));i.cm=n,this.host._wallDialog=null;return this._commitPhysicalGeometry(this.host._t("history.wall_thickness"),t)&&this.host._showToast(this.host._t("toast.wallthick_set")),void this.host.requestUpdate()}const r=this._geometrySnapshot(),l=n>0?n:null;if(0===n){const i=.02*this.host._gridPitch,o=[e.a[0],e.a[1],e.b[0],e.b[1]],a=(s.rooms||[]).find(t=>t.id===e.roomId),n=new Set(t&&a&&Array.isArray(a.wall_ids)?a.wall_ids:(s.wall_segments||[]).filter(t=>{const e=[Number(t.a?.[0])*Vd,Number(t.a?.[1])*Vd],s=[Number(t.b?.[0])*Vd,Number(t.b?.[1])*Vd];return me(e,o)<=i&&me(s,o)<=i}).map(t=>String(t.id))),r=(s.openings||[]).some(t=>{if("partition"===t.host?.kind)return!1;if("wall"===t.host?.kind&&n.has(t.host.id))return!0;if(t.host)return!1;const e=[Number(t.x)*Vd,Number(t.y)*Vd];return e.every(Number.isFinite)&&me(e,o)<=i});if(r)return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"))}let h,c=this.host._openCuts();if(n>0&&c.length){const o=[];if(t&&e.roomId){const t=(s.rooms||[]).find(t=>t.id===e.roomId),a=new Set(Array.isArray(t?.wall_ids)?t.wall_ids:[]);for(const t of s.wall_segments||[])a.has(t.id)&&o.push([Number(t.a?.[0])*Vd,Number(t.a?.[1])*Vd,Number(t.b?.[0])*Vd,Number(t.b?.[1])*Vd]);if(!o.length){const t=i.rooms.find(t=>t.id===e.roomId),s=t?B(t):null;for(let t=0;s&&t<s.length;t++){const e=s[t],i=s[(t+1)%s.length];o.push([e[0],e[1],i[0],i[1]])}}}else o.push([e.a[0],e.a[1],e.b[0],e.b[1]]);const a=.02*this.host._gridPitch;c=c.filter(t=>!o.some(e=>me([t[0],t[1]],e)<=a&&me([t[2],t[3]],e)<=a&&me([e[0],e[1]],t)<=a&&me([e[2],e[3]],t)<=a))}h=t&&e.roomId?Es(s.walls,i.rooms,e.roomId,l,this.host._wallKeyPitch,c,Vd):K(s.walls,e.a,e.b,l,this.host._wallKeyPitch,Vd),h=this.host._normalizeWalls(h,c);for(const t of s.wall_segments||[])t.cm=rt(h,t.a,t.b,E,1);h.length?s.walls=h:delete s.walls,this.host._wallDialog=null,this._commitPhysicalGeometry(this.host._t("history.wall_thickness"),r)&&this.host._showToast(this.host._t(0===n?"toast.wallthick_cleared":"toast.wallthick_set")),this.host.requestUpdate()}_wallHatchDefs(t){if(!this.host._spaceWalls.length&&!this.host._physicalBodiesR().length&&!this.host._markup)return Tt``;const e=Nt(this.host._cellCm);return Tt`<defs>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<pattern id="hp-wall-hatch" patternUnits="userSpaceOnUse"
|
||
width="${e}" height="${e}" patternTransform="rotate(45)">
|
||
<path d="M0 0 L0 ${e}" stroke="${t||"#607d8b"}" stroke-width="${e/uo*2}"></path>
|
||
</pattern>
|
||
</defs>`}_renderWallThickUi(){const t=this.host._wallThickHover;return t&&t.d?Tt`<path class="wallthick-hover ${t.open?"isopen":""}"
|
||
d="${t.d}"></path>`:Tt``}_renderWallThickDialog(){const t=this.host._wallDialog;return t?p`<div class="wallthick-dlg" style="left:${t.sx.toFixed(2)}%;top:${t.sy.toFixed(2)}%"
|
||
@click=${t=>t.stopPropagation()}>
|
||
<div class="row">
|
||
<label>${this.host._t("wallthick.field")}</label>
|
||
<input type="number" min="0" max="100" step="any" .value=${t.value}
|
||
@input=${e=>{this.host._wallDialog={...t,value:e.target.value}}}
|
||
@keydown=${t=>{"Enter"===t.key&&(t.preventDefault(),this._wallThickApply(!1))}} />
|
||
<span class="opl">${this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}</span>
|
||
</div>
|
||
<div class="row">
|
||
${"room"===t.source.kind?p`<button class="btn ghost"
|
||
@click=${()=>this._wallThickApply(!0)}>
|
||
${this.host._t("wallthick.apply_room")}
|
||
</button>`:d}
|
||
<span class="spacer"></span>
|
||
<button class="btn on" @click=${()=>this._wallThickApply(!1)}>
|
||
<ha-icon icon="mdi:check"></ha-icon>
|
||
</button>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</div>`:p``}_openingAt(t){if(!this.host._openingsR.length)return null;const e=this.host._openingsR.flatMap(e=>{const i=e.angle*Math.PI/180,s=t[0]-e.rx,o=t[1]-e.ry,a=s*Math.cos(i)+o*Math.sin(i);return Math.abs(a)>e.rlen/2+Et(12,this.host._cellCm)?[]:[{o:e,localY:-s*Math.sin(i)+o*Math.cos(i)}]});if(!e.length)return null;const i=this.host._spaceModel();if(!i)return null;const s=this.host._openCuts(),o=this.host._openingWallIndexFor(i,s).value;return e.find(({o:t,localY:e})=>{const i="gate"===t.type?!t.flip_v:t.flip_v,s=t.partitionHost||this.host._spaceWalls.length||"gate"===t.type?this.host._openingFace(t,o,!!i):{ox:0,oy:0,cm:0,side:-1},a=Hi({type:t.type,length:t.rlen,angle:t.angle,amount:this.host._openingAmt(t),flipH:!!t.flip_h,flipV:!!t.flip_v,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,face:s});return Math.abs(e)<=a.hitHalf})?.o||null}_resolveOpeningPlacement(t){const e=this.host._openingPreset;if("opening"!==this.host._tool||!e)return null;const i=this.host._spaceModel();if(!i)return null;const s=this.host._openCuts(),o=this.host._openingWallIndexFor(i,s),a=`${o.key}|partitions:${this.host._cfgEpoch}`;this.host._openingPlacementIntervalsCache&&this.host._openingPlacementIntervalsCache.key===a||(this.host._openingPlacementIntervalsCache={key:a,value:[...G(i.rooms,this.host._spaceWalls,s,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd),...Wi(i.partitions,this.host._cellCm,this.host._gridPitch)]}),this.host._openingDimensionContextCache&&this.host._openingDimensionContextCache.key===a||(this.host._openingDimensionContextCache={key:a,value:Ed({rooms:i.rooms,walls:this.host._spaceWalls,openCuts:s,partitions:i.partitions,roomOpenings:this.host._roomWallOpeningInputs(),partitionCuts:this._partitionOpeningCuts(i),pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Qd,epsilon:2e-4*this.host._gridPitch})});const n=Gi({pointer:[t[0],t[1]],preset:e,geometryRevision:this.host._cfgEpoch,renderedLength:this.host._cmToUnits(e.lengthCm),intervals:this.host._openingPlacementIntervalsCache.value,baseTolerance:1.5*this.host._gridPitch,bodyPointerPadding:this._cssPxToRender("touch"===this.host._pointerModality.modality||"pen"===this.host._pointerModality.modality?10:6),gridStep:this.host._gridPitch});this.host._openingJambBlockCm=n.jambBlockedTarget?n.jambBlockedTarget.physicalHalfWidth/this.host._gridPitch*this.host._cellCm:null;const r=n.candidate;if(!r)return null;const l="gate"===r.type?!r.flipV:r.flipV;let h;if(r.host){const t=H({id:"preview",type:r.type,x:r.x/Qd,y:r.y/Qd,angle:r.angle,length:r.renderedLength/Qd,host:r.host},i.partitions,Qd,this.host._cellCm,this.host._gridPitch).resolved;h=t?ji(t,l):{ox:0,oy:0,cm:0,side:-1}}else h=Ui(o.value,{x:r.x,y:r.y,angle:r.angle,length:r.renderedLength,flip_v:l});const c="mi"===this.host.hass?.config?.unit_system?.length,d=jd(r,this.host._openingDimensionContextCache.value).map(t=>({x:t.label[0],y:t.label[1],text:pe(t.distance/this.host._gridPitch*this.host._cellCm,c),dimension:t}));return{...r,face:h,measure:{labels:d,guide:r.measure.guide}}}_activateOpeningPlacement(t){this._activateMarkupTool("opening"),"opening"===this.host._tool&&(this.host._openingPreset=qi(t,++this.host._openingPresetRevision),this.host._openingHoverCandidate=null,this.host._cursorPt=null)}_clearOpeningPlacement(t){this.host._openingHoverCandidate=null,this.host._openingJambBlockCm=null,t&&(this.host._openingPreset=null,this.host._openingRebindId=null)}_openingClick(t){const e=this.host._spaceModel();if(!e)return;const i=this.host._openingRebindId?null:this._openingAt(t);if(i)return void this._editOpening(i);const s=this.host._openingPreset;if(!s)return;const o=this.host._openingHoverCandidate,a=o&&Ki(o,[t[0],t[1]],s.revision,this.host._cfgEpoch)?o:this._resolveOpeningPlacement(t);if(!a){if(null!=this.host._openingJambBlockCm)return void this.host._showToast(this.host._t("opening.partition_jamb_margin",{distance:pe(this.host._openingJambBlockCm,this.host._imperial)}));const i=1.5*this.host._gridPitch,s=E(t,e.rooms,i);return s&&Vi(s.x,s.y,s.angle,this.host._openCuts(),i)?void this.host._showToast(this.host._t("toast.opening_on_zero_wall")):void this.host._showToast(this.host._t("toast.opening_no_wall"))}const n=this.host._openingRebindId?this.host._curSpaceCfg?.openings?.find(t=>t.id===this.host._openingRebindId):null;this.host._openingDialog={...n?{id:n.id,type:n.type,lengthCm:Math.round(n.length*Qd/this.host._gridPitch*this.host._cellCm),lengthTouched:!1,contact:n.contact||"",lock:n.lock||"",invert:!!n.invert,flipH:!!n.flip_h,flipV:!!n.flip_v}:{type:a.type,lengthCm:a.lengthCm,contact:"",lock:"",invert:!1,flipH:a.flipH,flipV:a.flipV},...a.host?{host:a.host}:{},x:a.x,y:a.y,angle:a.angle},this.host._openingRebindId=null,this.host._openingHoverCandidate=null,this.host._cursorPt=null}_editOpening(t){this.host._openingDialog={id:t.id,type:t.type,lengthCm:Math.round(t.rlen/this.host._gridPitch*this.host._cellCm),lengthTouched:!1,contact:t.contact||"",lock:t.lock||"",invert:!!t.invert,flipH:!!t.flip_h,flipV:!!t.flip_v,..."partition"===t.host?.kind?{host:{...t.host}}:{},x:t.rx,y:t.ry,angle:t.angle}}_opPointerDown(t,e){if("plan"===this.host._mode&&this.host._spaceModel()&&"resize"!==this.host._tool){t.preventDefault(),t.stopPropagation();try{ep(t)}catch{}this.host._opDrag={id:e.id,moved:!1,sx:t.clientX,sy:t.clientY,dirty:!1,before:this._geometrySnapshot()}}}_opPointerMove(t,e){Er(this.host,"opening",()=>this._opPointerMoveNow(t,e))}_opPointerMoveNow(t,e){if(!this.host._opDrag||this.host._opDrag.id!==e.id)return;if(Math.abs(t.clientX-this.host._opDrag.sx)+Math.abs(t.clientY-this.host._opDrag.sy)<=3)return;const i=this.host._spaceModel();if(!i)return;const s=this._svgPoint(t),o=this.host._curSpaceCfg,a=o?.openings?.find(t=>t.id===e.id);if(!a)return;if("partition"===a.host?.kind){const t=i.partitions.find(t=>t.id===a.host.id);if(!t)return;const e=t.b[0]-t.a[0],o=t.b[1]-t.a[1],n=Math.hypot(e,o);if(!(n>1e-9))return;const r=e/n,l=o/n;if(Math.abs((s[0]-t.a[0])*l-(s[1]-t.a[1])*r)>4*this.host._gridPitch)return;const h=a.length*Qd/2+q(t,this.host._cellCm,this.host._gridPitch);let c=(s[0]-t.a[0])*r+(s[1]-t.a[1])*l;if(c=Math.round(c/this.host._gridPitch)*this.host._gridPitch,c=Math.max(h,Math.min(n-h,c)),n<2*h-1e-9)return;const d=c/n,p=(t.a[0]+r*c)/Qd,u=(t.a[1]+l*c)/this.host._spaceH;let _=180*Math.atan2(o,e)/Math.PI;_>=90?_-=180:_<-90&&(_+=180);const m=a.host.t!==d||a.x!==p||a.y!==u||a.angle!==_;return this.host._opDrag.moved=!0,m&&(this.host._opDrag.dirty=!0),a.host={...a.host,t:d},a.x=p,a.y=u,a.angle=_,this.host._opMeasure=null,m&&this.host._cfgEpoch++,void this.host.requestUpdate()}const n=E(s,i.rooms,4*this.host._gridPitch);if(!n)return;this.host._opDrag.moved=!0;const r=this._opRuler(n,a.length*Qd);this.host._opMeasure=r.measure;const l=r.x/Qd,h=r.y/this.host._spaceH,c=a.x!==l||a.y!==h||a.angle!==n.angle;if(c&&(this.host._opDrag.dirty=!0),a.x=l,a.y=h,a.angle=n.angle,Number(this.host._serverCfg?.model_version||0)>=9){const t=Kn(a,o?.wall_segments||[]);t?a.host=t:delete a.host}c&&this.host._cfgEpoch++,this.host.requestUpdate()}_opRuler(t,e){const i=this.host._spaceModel()?.rooms||[],s=this.host._gridPitch/2;let o=t.x,a=t.y,n=Ji([o,a],t.angle,e,i,s);if(n&&n.centered&&(o!==n.wallCenter[0]||a!==n.wallCenter[1]))[o,a]=n.wallCenter,n=Ji([o,a],t.angle,e,i,s);else if(n){const[r,l]=n.wallA,[h,c]=n.wallB,d=h-r,p=c-l,u=Math.hypot(d,p);if(u>0){const h=this.host._gridPitch,c=Math.min(e/2,u/2);let _=Math.round(((o-r)*d+(a-l)*p)/u/h)*h;_=Math.max(c,Math.min(u-c,_)),o=r+_/u*d,a=l+_/u*p,n=Ji([o,a],t.angle,e,i,s)||n}}if(!n)return{x:o,y:a,angle:t.angle,measure:null};const r="mi"===this.host.hass?.config?.unit_system?.length,l=(t,e)=>({x:e[0],y:e[1],text:pe(t/this.host._gridPitch*this.host._cellCm,r)});return{x:o,y:a,angle:t.angle,measure:{labels:[l(n.sideA,n.midA),l(n.sideB,n.midB)],guide:n.centered?{x:n.wallCenter[0],y:n.wallCenter[1],angle:t.angle}:null}}}_opPointerUp(t,e){if(!this.host._opDrag||this.host._opDrag.id!==e.id)return;Ar(this.host,"opening");const i=this.host._opDrag,s=i.moved;this.host._opMeasure=null,s&&i.dirty&&this._commitPhysicalGeometry(this.host._t("history.move_opening"),i.before);const o=()=>{this.host._opDrag=null,this.host.requestUpdate()};s?window.setTimeout(o,0):o()}_opClick(t,e){"plan"===this.host._mode&&"resize"===this.host._tool||(t.stopPropagation(),this.host._opDrag?.moved||"plan"===this.host._mode&&this._editOpening(e))}_saveOpening(){const t=this.host._openingDialog,e=this.host._curSpaceCfg,i=this.host._spaceModel();if(!t||!e||!i)return;const s=this._geometrySnapshot(),o=this.host._spaceH,a=(e.openings||[]).find(e=>e.id===t.id),n={...a||{},id:t.id||"o"+Date.now().toString(36),type:t.type,x:t.x/Qd,y:t.y/o,angle:t.angle,length:a&&!t.lengthTouched?a.length:this.host._cmToUnits(Math.max(20,t.lengthCm))/Qd,...t.host?{host:{...t.host}}:{}};if("partition"===n.host?.kind){const t=Yi(a,n)?J(n,i.partitions,Qd,this.host._cellCm,this.host._gridPitch):H(n,i.partitions,Qd,this.host._cellCm,this.host._gridPitch);if(!t.resolved){const e=i.partitions.find(t=>t.id===n.host.id);if("does-not-fit-jamb"===t.reason&&e){const t=q(e,this.host._cellCm,this.host._gridPitch);this.host._showToast(this.host._t("opening.partition_jamb_margin",{distance:pe(t/this.host._gridPitch*this.host._cellCm,this.host._imperial)}))}else this.host._showToast(this.host._t("opening.partition_orphan"));return}const s=(e.openings||[]).flatMap(t=>{if(!t.host||t.id===n.id)return[];const e=H(t,i.partitions,Qd,this.host._cellCm,this.host._gridPitch).resolved;return e?[e]:[]});if(Zi(t.resolved,s))return void this.host._showToast(this.host._t("toast.opening_no_wall"));Object.assign(n,W(n,t.resolved,Qd))}else if(Number(this.host._serverCfg?.model_version||0)>=9){const t=Kn(n,e.wall_segments||[]);if(!t)return void this.host._showToast(this.host._t("toast.opening_no_wall"));n.host=t}else delete n.host;"passage"===t.type?(delete n.contact,delete n.lock,delete n.invert,delete n.flip_h,delete n.flip_v):(n.contact=t.contact||null,n.lock=("door"===t.type||"gate"===t.type)&&t.lock||null,n.invert=t.invert||void 0,n.flip_h="gate"!==t.type&&t.flipH||void 0,n.flip_v=t.flipV||void 0),e.openings=e.openings||[];const r=e.openings.findIndex(t=>t.id===n.id);r>=0?e.openings[r]=n:e.openings.push(n),this._commitPhysicalGeometry(this.host._t(t.id?"history.edit_opening":"history.add_opening"),s),this.host._openingDialog=null,this.host.requestUpdate()}_deleteOpening(){const t=this.host._openingDialog,e=this.host._curSpaceCfg;if(!t?.id||!e?.openings)return;const i=this._geometrySnapshot();e.openings=e.openings.filter(e=>e.id!==t.id),this._commitPhysicalGeometry(this.host._t("history.delete_opening"),i),this.host._openingDialog=null,this.host.requestUpdate()}_contactCandidates(){const t=[];for(const e of Object.keys(this.host.hass.states)){if(!this.host._openingEntityAvailable(e))continue;const i=e.split(".")[0];if("binary_sensor"!==i&&"cover"!==i)continue;const s=this.host.hass.states[e],o=["door","window","opening","garage_door","garage"].includes(s?.attributes?.device_class||"");("cover"!==i||o)&&t.push([e,s?.attributes?.friendly_name||e,o?0:1])}return t.sort((t,e)=>t[2]-e[2]||t[1].localeCompare(e[1])).map(([t,e])=>({value:t,label:e}))}_lockCandidates(){return Object.keys(this.host.hass.states).filter(t=>t.startsWith("lock.")&&this.host._openingEntityAvailable(t)).map(t=>({value:t,label:this.host.hass.states[t]?.attributes?.friendly_name||t})).sort((t,e)=>t.label.localeCompare(e.label))}_toggleOpeningEntityPicker(t){const e=this.host._openingDialog;if(!e)return;const i="contact"===t?!e.contactOpen:!e.lockOpen;this.host._openingDialog={...e,contactOpen:"contact"===t&&i,lockOpen:"lock"===t&&i}}_filterOpeningEntities(t,e){const i=this.host._openingDialog;i&&(this.host._openingDialog="contact"===t?{...i,contactFilter:e}:{...i,lockFilter:e})}_selectOpeningEntity(t,e){const i=this.host._openingDialog;i&&(this.host._openingDialog="contact"===t?{...i,contact:e,contactOpen:!1,contactFilter:""}:{...i,lock:e,lockOpen:!1,lockFilter:""})}_mergeClick(t){const e=this.host._spaceModel();if(!e)return;const i=e.rooms,s=[...i].reverse().find(e=>this._pointInRoom(t,e));if(!s?.id)return;const o=s.id;if(!this.host._mergeSel||this.host._mergeSel===o)return void(this.host._mergeSel=this.host._mergeSel===o?null:o);const a=i.find(t=>t.id===this.host._mergeSel),n=a?B(a):null,r=B(s),l=n&&r?Xi(n,r):null;if(!l)return this.host._showToast(this.host._t("toast.merge_not_adjacent")),void(this.host._mergeSel=null);this.host._mergeDialog={aId:this.host._mergeSel,bId:o,poly:l,pick:"a"},this.host._mergeSel=null}_commitMerge(){const t=this.host._mergeDialog,e=this.host._curSpaceCfg;if(!t||!e||!this.host._spaceModel())return;const i=this._geometrySnapshot(),s=this.host._spaceH,o="a"===t.pick?t.aId:t.bId,a="a"===t.pick?t.bId:t.aId,n=Jd(this.host._serverCfg?.markers||[],{kind:"merge",dropId:a,keepId:o});i&&n.changed&&(i.roomReferences=n.before);const r=e.rooms.find(t=>t.id===o);if(!r)return void(this.host._mergeDialog=null);r.poly=t.poly.map(t=>[t[0]/Qd,t[1]/s]),delete r.x,delete r.y,delete r.w,delete r.h,e.rooms=e.rooms.filter(t=>t.id!==a),n.changed&&this.host._serverCfg&&(this.host._serverCfg.markers=n.markers);const l=this._commitPhysicalGeometry(this.host._t("history.merge_rooms"),i);this.host._mergeDialog=null,this.host._regSignature="",this.host._maybeRebuildDevices(),l&&this.host._showToast(this.host._t("toast.rooms_merged",{name:r.name||""}))}_splitClick(t){const e=this.host._spaceModel();if(!e)return;const i=e.rooms;if(!this.host._splitSel){const e=[...i].reverse().find(e=>this._pointInRoom(t,e));if(!e?.id)return;return void(this.host._splitSel={roomId:e.id,pts:[]})}const s=i.find(t=>t.id===this.host._splitSel.roomId),o=s?B(s):null;if(!s||!o)return void(this.host._splitSel=null);const a=.02*this.host._gridPitch,n=6*this.host._gridPitch,r=Qi(t,o),l=r&&ts(r,o,this.host._gridPitch)||r,h=r&&l&&Math.hypot(r[0]-t[0],r[1]-t[1])<=n?l:null,c=!!h&&es(h,o,a),d=this.host._splitSel.pts;if(!d.length)return c?void(this.host._splitSel={...this.host._splitSel,pts:[h]}):void this.host._showToast(this.host._t("toast.split_pick_wall"));if(!c){const e=this._snap(t);return ii(e,o,a)?void(this.host._splitSel={...this.host._splitSel,pts:[...d,e]}):void this.host._showToast(this.host._t("toast.split_pick_inside"))}const p=oi(o,[...d,h],a);if(!p)return void this.host._showToast(this.host._t("toast.split_bad_cut"));this._resetRoomDialogFields();const[u,_]=p,m=te(u)>=te(_)?u:_,g=m===u?_:u;this.host._pendingSplit={roomId:s.id,mainPoly:m,newPoly:g},this.host._cursorPt=null,this.host._nameSel="",this.host._areaSel="",this.host._roomDialog=!0}_markupMove(t){if(!this.host._markup)return;if("column"===this.host._tool)return void(this.host._cursorPt=this._snap(this._svgPoint(t)));if("opening"===this.host._tool||"wallthick"===this.host._tool)return void(this.host._cursorPt=this._svgPoint(t));const e="draw"===this.host._tool&&!this.host._contourClosed,i="split"===this.host._tool&&!!this.host._splitSel?.pts?.length;if(!e&&!i)return;const s=this._svgPoint(t);if(e){const e=this._resolvePlanDrawPoint(s,t.shiftKey);if(this.host._planSnapHover={contextKey:e.contextKey,candidate:e.candidate,conflicts:e.conflicts},this._syncPlanSnapConflictMarkers(e.conflicts),this._syncPlanSnapActiveMarker(e.candidate),!this.host._path.length)return;return void(this.host._cursorPt=e.point)}this.host._cursorPt=this._snap(s)}_saveRoom(){(this.host._areaSel||this.host._nameSel.trim())&&It(this.host._roomTempMin,this.host._roomTempMax).valid&&(this.host._wallFaceBatch?this._decideWallFace(!0):this._commitRoom())}_decideWallFace(t){const e=this.host._wallFaceBatch;if(!e)return;const i=e.candidates[e.index];if(!i)return;if(!t&&(i.existing||i.repair)&&1===e.candidates.length)return this.host._wallFaceBatch=null,this.host._roomDialog=!1,this.host._nameSel="",this.host._areaSel="",void this.host.requestUpdate();const s=t?{candidate:i,create:!0,name:this.host._nameSel.trim(),area:this.host._areaSel||null,settings:this._roomSettingsFromDialog()?JSON.parse(JSON.stringify(this._roomSettingsFromDialog())):null}:{candidate:i,create:!1},o=[...e.decisions,s],a=e.index+1;if(a<e.candidates.length)return this.host._wallFaceBatch={...e,decisions:o,index:a},this.host._nameSel="",this.host._areaSel="",this._resetRoomDialogFields(),void this.host.requestUpdate();this.host._wallFaceBatch={...e,decisions:o},this._applyWallFaceBatch()}_wallSourceCmAt(t,e,i){const s=t=>"number"==typeof t&&Number.isFinite(t)&&t>=0?t:null,o=.02*this.host._gridPitch,a=this.host._spaceModel();if(!a)return j;for(const e of this._planSnapGeometrySnapshot().value.segments)if(!("room"===e.sourceKind||ge(t,[e.a[0],e.a[1],e.b[0],e.b[1]])>o)&&"partition"===e.sourceKind)return s(a.partitions.find(t=>t.id===e.sourceId)?.cm)??j;const n=Tc(Math.max(0,e.length-1),i,this.host._drawWallCm,j);for(let i=0;i+1<e.length;i++){const s=e[i],a=e[i+1];if(ge(t,[s[0],s[1],a[0],a[1]])<=o)return n[i]??j}return j}_activePathWithRepair(t,e){const i=t.map(t=>[...t]);if(!e)return i;const s=this.host._activeWallChainPartitionIds.findIndex((t,i)=>this._activeWallSourceKey(i)===e.sourceKey),o=s>=0?s+("b"===e.endpoint?1:0):-1;return o>=0&&o<i.length&&(i[o]=[...e.to]),i}_validateWallRepair(t,e){const i=2e-4*this.host._gridPitch,s=this._wallGraphSources(e),o=s.find(e=>e.key===t.sourceKey),a=s.find(e=>e.key===t.targetSourceKey);if(!o||!a)return!1;const n="a"===t.endpoint?o.a:o.b;return!(Math.hypot(n[0]-t.from[0],n[1]-t.from[1])>i)&&(!(ge(t.to,[a.a[0],a.a[1],a.b[0],a.b[1]])>i)&&!function(t,e){if(!t.sourceKey.startsWith("static:partition|"))return!1;const i=t.sourceKey.slice(17).split("|")[0];return!!i&&e.some(t=>"partition"===t.host?.kind&&t.host.id===i)}(t,this.host._curSpaceCfg?.openings||[]))}_applyWallRepair(t,e){const i=this.host._curSpaceCfg;if(!i||!this._validateWallRepair(t,e.activePath))return!1;if(!t.sourceKey.startsWith("static:"))return!1;const[s,o]=t.sourceKey.slice(7).split("|");if("partition"===s){const s=(i.partitions||[]).find(t=>t.id===o);if(!s)return!1;const a=[s.a[0]*Qd,s.a[1]*Qd],n=[s.b[0]*Qd,s.b[1]*Qd],r=Math.hypot(a[0]-t.from[0],a[1]-t.from[1])<=2e-4*this.host._gridPitch?s.a:Math.hypot(n[0]-t.from[0],n[1]-t.from[1])<=2e-4*this.host._gridPitch?s.b:null;if(!r)return!1;(e=>{e[0]=t.to[0]/Qd,e[1]=t.to[1]/Qd})(r);const l=e.activePartitionIds.indexOf(o);if(l>=0){const i=l+("b"===t.endpoint?1:0);e.activePath[i]&&(e.activePath[i]=[...t.to])}return!0}return!1}_applyWallFaceBatch(){const t=this.host._wallFaceBatch,e=this.host._curSpaceCfg,i=this.host._spaceModel();if(!t||!e||!i)return;const s=(t,e)=>{this.host._showToast(this.host._t(t,e)),this._roomDialogCancel()},o=t.decisions.filter(t=>t.create),a=o.map(t=>t.candidate.ring),n=i.rooms;for(let t=0;t<a.length;t++){if(this._contourSelfIntersects(a[t])||te(a[t])<=1e-6)return void s("toast.contour_cannot_close");for(let e=t+1;e<a.length;e++)if(Xt(a[t],a[e]))return void s("toast.contour_cannot_close");const e=o[t].candidate.split?.roomId,i=n.find(i=>i.id!==e&&!!B(i)&&Xt(a[t],B(i)));if(i)return void s("toast.room_overlap",{name:i.name||""})}if((e.rooms||[]).length+o.length>400)return void s("toast.physical_limit");if(o.some(t=>t.candidate.split&&!e.rooms.some(e=>e.id===t.candidate.split.roomId)))return void s("toast.contour_cannot_close");const r=o.map(t=>t.candidate.repair).filter(t=>!!t);if(r.length>1||r[0]&&!this._validateWallRepair(r[0],t.activePath))return void s("toast.wall_repair_changed");if(!o.length){if(!this._finalizeWallChainPartitions(t.activePartitionIds))return;return this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host._wallFaceBatch=null,this.host._roomDialog=!1,this.host._nameSel="",this.host._areaSel="",this.host.requestUpdate(),void this.host._showToast(this.host._t("toast.wall_chain_saved"))}const l=new Set(t.activePartitionIds),h=2e-4*this.host._gridPitch,c=o.map(t=>t.candidate.ring.map((t,e,s)=>{const o=s[(e+1)%s.length],a=i.partitions.filter(e=>{const i=Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1]);if(!(i>h))return!1;const s=(e.b[0]-e.a[0])/i,a=(e.b[1]-e.a[1])/i,n=t=>(t[0]-e.a[0])*s+(t[1]-e.a[1])*a;return ge(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=h&&ge(o,[e.a[0],e.a[1],e.b[0],e.b[1]])<=h&&n(t)>=-h&&n(t)<=i+h&&n(o)>=-h&&n(o)<=i+h});return a.sort((t,e)=>Number(l.has(e.id))-Number(l.has(t.id))||Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])-Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])||t.id.localeCompare(e.id)),a[0]?.id||""})),d=this._geometrySnapshot();if(!d)return void s("toast.geometry_unsafe");const p=()=>{this._restoreGeometryStateLocal(d),s("toast.geometry_unsafe")};if(r[0]&&!this._applyWallRepair(r[0],t))return void s("toast.wall_repair_changed");const u=o.some(t=>!!t.candidate.split),_=u?Fe(i.rooms,e.walls,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd):null,m=u&&Array.isArray(e.walls)?e.walls:null;for(const t of o){const i=t.candidate.split;if(!i)continue;const s=e.rooms.find(t=>t.id===i.roomId);if(!s)return void p();s.poly=i.mainPoly.map(t=>[t[0]/Qd,t[1]/this.host._spaceH]),delete s.x,delete s.y,delete s.w,delete s.h}const g=Date.now().toString(36),f=[];if(o.forEach((t,i)=>{const s=t.area?this.host.hass.areas[t.area]?.name:"",o={id:`r${g}-${i}`,name:t.name||s||this.host._t("room.default_name"),area:t.area||null,poly:t.candidate.ring.map(t=>[t[0]/Qd,t[1]/this.host._spaceH]),...c[i].some(Boolean)?{wall_ids:c[i]}:{},...t.settings?{settings:JSON.parse(JSON.stringify(t.settings))}:{}};e.rooms.push(o),f.push({room:o,decision:t})}),u){const t=this.host._normalizeWalls(_,this.host._openCuts());t.length?e.walls=t:m?.length?e.walls=m:delete e.walls}if(f.length){this.host._cfgEpoch++;const i=this.host._openCuts(),s=this.host._spaceModel();if(!s)return void p();let o=e.walls;for(const{room:e,decision:a}of f){const n=a.candidate.ring,r=this._wallSourceCmAt(n[0],t.activePath,t.activeCms);o=is(o,s.rooms,e.id,r,this.host._wallKeyPitch,i,Qd);for(const a of G(s.rooms,o,i,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd)){if(a.roomId!==e.id||"outer"!==a.kind)continue;const i=[(a.a[0]+a.b[0])/2,(a.a[1]+a.b[1])/2];o=K(o,a.a,a.b,this._wallSourceCmAt(i,t.activePath,t.activeCms),this.host._wallKeyPitch,Qd)}}const a=this.host._normalizeWalls(o,i);a.length?e.walls=a:delete e.walls,this.host._cfgEpoch++;const n=this.host._spaceModel();if(!n)return void p();const r=vn(e,n,e.walls,i,{pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Qd,allowCoincidentPartitions:!0});r.walls.length?e.walls=r.walls:delete e.walls,r.partitions.length?e.partitions=r.partitions:delete e.partitions,r.openings.length?e.openings=r.openings:delete e.openings}if(!this._commitPhysicalGeometry(this.host._t("history.wall_face_batch"),d))return;this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host._wallFaceBatch=null,this.host._roomDialog=!1,this.host._nameSel="",this.host._areaSel="",this.host._regSignature="",this.host._maybeRebuildDevices();const b=new Set(o.map(t=>t.area).filter(t=>!!t));if(b.size){const t={...this.host._layout};for(const e of this.host._devices){if(!b.has(e.area||"")||e.space!==this.host._space)continue;if(this.host._layout[e.id])continue;const i=this.host._defPos[e.id];i&&(t[e.id]={s:this.host._space,x:i.x/Qd,y:i.y/Qd},this.host._dirtyPos.add(e.id))}this.host._layout=t,this.host._persistLayout()}this.host._showToast(this.host._t(o.length?"toast.wall_rooms_saved":"toast.wall_chain_saved",{n:o.length}))}_commitRoom(){const t=this.host._curSpaceCfg,e=this.host._spaceModel();if(!t||!e)return;const i=this._geometrySnapshot();if(!i)return;const s=()=>{this._restoreGeometryStateLocal(i),this.host._showToast(this.host._t("toast.geometry_unsafe"))},o=this.host._spaceH,a=!!this.host._pendingSplit,n=a?Fe(e.rooms,t.walls,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd):null,r=a&&Array.isArray(t.walls)?t.walls:null;let l;if(this.host._pendingSplit){const e=t.rooms.find(t=>t.id===this.host._pendingSplit.roomId);if(!e)return this.host._pendingSplit=null,this.host._splitSel=null,void(this.host._roomDialog=!1);e.poly=this.host._pendingSplit.mainPoly.map(t=>[t[0]/Qd,t[1]/o]),delete e.x,delete e.y,delete e.w,delete e.h,l=this.host._pendingSplit.newPoly}else{if(!this.host._contourClosed)return;l=this.host._path.slice(0,-1)}const h=this.host._areaSel?this.host.hass.areas[this.host._areaSel]?.name:"",c={id:"r"+Date.now().toString(36),name:this.host._nameSel||h||this.host._t("room.default_name"),area:this.host._areaSel||null,poly:l.map(t=>[t[0]/Qd,t[1]/o]),...this._roomSettingsFromDialog()?{settings:this._roomSettingsFromDialog()}:{}};if(t.rooms.push(c),a){const e=this.host._normalizeWalls(n,this.host._openCuts());e.length?t.walls=e:r?.length?t.walls=r:delete t.walls}if(!a){const e=Tc(l.length,[...this.host._wallChainSegmentCms,this.host._closingWallCm??void 0],this.host._drawWallCm,j),i=e[0];if(null!=i){this.host._cfgEpoch++;const o=this.host._openCuts(),a=this.host._spaceModel();if(!a)return void s();let n=is(t.walls,a.rooms,c.id,i,this.host._wallKeyPitch,o,Qd);for(const t of G(a.rooms,n,o,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd)){if(t.roomId!==c.id||"outer"!==t.kind)continue;const i=[(t.a[0]+t.b[0])/2,(t.a[1]+t.b[1])/2],s=l.findIndex((t,e)=>{const s=l[(e+1)%l.length];return ge(i,[t[0],t[1],s[0],s[1]])<=.02*this.host._gridPitch});s>=0&&(n=K(n,t.a,t.b,e[s],this.host._wallKeyPitch,Qd))}n=this.host._normalizeWalls(n,o),n.length?t.walls=n:delete t.walls;const r=this.host._spaceModel();if(!r)return void s();const h=vn(t,r,t.walls,o,{pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Qd,allowCoincidentPartitions:!0});h.walls.length?t.walls=h.walls:delete t.walls,h.partitions.length?t.partitions=h.partitions:delete t.partitions,h.openings.length?t.openings=h.openings:delete t.openings}}const d=this._commitPhysicalGeometry(this.host._t(a?"history.split_room":"history.add_room"),i);this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host._pendingSplit=null,this.host._splitSel=null;const p=this.host._areaSel;if(this.host._areaSel="",this.host._nameSel="",this.host._roomDialog=!1,this.host._regSignature="",this.host._maybeRebuildDevices(),!d)return;let u=0;if(p){const t=Qd,e={...this.host._layout};for(const i of this.host._devices){if(i.area!==p||i.space!==this.host._space)continue;if(u++,this.host._layout[i.id])continue;const s=this.host._defPos[i.id];s&&(e[i.id]={s:this.host._space,x:s.x/Qd,y:s.y/t},this.host._dirtyPos.add(i.id))}this.host._layout=e,this.host._persistLayout()}const _=this.host._model.find(t=>t.id===this.host._space)?.rooms.length||0;this.host._showToast(p?this.host._t("toast.room_saved",{n:_,added:u}):this.host._t("toast.room_saved_no_area",{n:_}))}_cancelPath(){this.host._wallRepairDiagnostic=null,this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this._clearPlanSnapHover(),this.host._roomDialog=!1,this.host._pendingSplit=null,this.host._wallFaceBatch=null,this.host._splitSel=null,this.host._mergeSel=null,this.host._mergeDialog=null,this.host._physicalSel=null,this.host._physicalDrag=null,this.host._physicalRotate=null,this._clearOpeningPlacement(!0)}_roomDialogCancel(){if(this.host._roomDialog=!1,this.host._roomEditId)return this.host._roomEditId=null,this.host._nameSel="",void(this.host._areaSel="");if(this.host._wallFaceBatch){const t=this.host._wallFaceBatch;return this.host._wallFaceBatch=null,this.host._path=t.activePath.map(t=>[...t]),this.host._wallChainSegmentCms=[...t.activeCms],this.host._activeWallChainPartitionIds=[...t.activePartitionIds],this.host._activeWallChainId||=`chain-${Date.now().toString(36)}`,this.host._nameSel="",this.host._areaSel="",void this.host.requestUpdate()}if(this.host._pendingSplit)return this.host._pendingSplit=null,void(this.host._splitSel=null);this.host._undoPoint()}_openDeviceInbox(){this.host._deviceInboxReturn=null,this.host._deviceInbox=this.host._deviceInbox||{tab:"on_plan",search:"",showEntities:!1,onlyNew:!1,limit:100}}_closeMarkerDialog(){this._radarSetup.isDirty()?this._closeMarkerDialogGuarded():(this._radarSetup.reset(),function(t){if(t._markerDialog=null,!t._deviceInboxReturn)return;const e={...t._deviceInboxReturn};t._deviceInbox=e,t._deviceInboxReturn=null,e.anchor&&t.updateComplete.then(()=>requestAnimationFrame(()=>{const i=`.device-inbox-row[data-binding="${CSS.escape(e.anchor)}"]`;t.renderRoot.querySelector(i)?.scrollIntoView({block:"nearest"})}))}(this.host))}async _closeMarkerDialogGuarded(){if(!await this._radarSetup.discardIfAllowed())return await this.host.updateComplete,void this.host.renderRoot.querySelector("#marker-dialog")?.rejectClose();this._closeMarkerDialog()}_deviceInboxCandidates(t){return nc({hass:this.host._planHass,devices:this.host._devices,markers:this.host._markers,showEntities:t,labels:{device:this.host._t("marker.sub_device"),z2mGroup:this.host._t("marker.sub_z2m_group"),group:this.host._t("marker.sub_group"),helper:this.host._t("marker.sub_helper"),entity:this.host._t("marker.sub_entity")}})}_deviceInboxRows(){const t=this.host._deviceInbox||this.host._deviceInboxReturn,e=!!t?.showEntities,i=[this.host._haRegistry.revision,this.host._cfgRev,this.host._cfgEpoch,this.host._regSignature,this.host._newSyncKey,e?1:0,this.host._showAll?1:0,l(this.host.hass,this.host._config?.language)].join("|");if(this.host._deviceInboxMemo?.key===i)return this.host._deviceInboxMemo.rows;const s=this._deviceInboxCandidates(e),o=new Set(s.map(t=>t.value));for(const t of this.host._markers)t.binding&&"virtual"!==t.binding&&o.add(t.binding);for(const t of this.host._devices)t.bindingKind&&"virtual"!==t.bindingKind&&t.bindingRef&&o.add(`${t.bindingKind}:${t.bindingRef}`);const a=new Map;for(const t of o)a.set(t,this.host._bindingStatus(t));const n=this.host._areaToSpace,r={};for(const[t,e]of Object.entries(this.host.hass?.areas||{}))r[t]=n[t]?.room?.name||e?.name||t;for(const[t,e]of Object.entries(n))r[t]=e.room.name||r[t]||t;const h=Object.fromEntries(this.host._model.map(t=>[t.id,t.title])),c=Object.fromEntries(Object.entries(n).map(([t,e])=>[t,e.space])),d={},p=new Map;for(const[t,e]of Object.entries(this.host._fullRegistryHass.entities||{})){const i=String(e?.platform||"").trim();if(i&&(d[`entity:${t}`]=i),i&&e?.device_id){const t=p.get(e.device_id)||new Set;t.add(i),p.set(e.device_id,t)}}for(const[t,e]of p)d[`device:${t}`]=[...e].sort().join(", ");const u={};for(const[t,e]of Object.entries(this.host._fullRegistryHass.devices||{})){const i=`device:${t}`,s=p.get(t)||new Set,o=Array.isArray(e?.identifiers?.[0])?String(e.identifiers[0][0]||""):"";o&&!d[i]&&(d[i]=o);const a=[o,...s].some(t=>this.host._excluded.has(t));"service"===e?.entry_type?u[i]="service_entry":a?u[i]="excluded_integration":"Group"===e?.model?u[i]="grouped_light":/scene/i.test(e?.model||"")?u[i]="excluded_domain":(/bridge/i.test(`${e?.model||""}${e?.name||""}`)||"myheat"===o&&e?.via_device_id)&&(u[i]="represented_by_parent")}const _=function(t){const{devices:e,markers:i,candidates:s,statuses:o,newDeviceIds:a,showHiddenOnPlan:n,areaNames:r={},spaceNames:l={},spaceByArea:h={},integrationByBinding:c={},reasonByBinding:d={}}=t,p=new Map;for(const t of e)!t.virtual&&t.bindingKind&&"virtual"!==t.bindingKind&&t.bindingRef&&p.set(`${t.bindingKind}:${t.bindingRef}`,t);const u=new Map,_=new Map;for(const t of i)t?.binding&&"virtual"!==t.binding&&(t.removed?_.set(t.binding,t):u.set(t.binding,t));const m=new Map(s.map(t=>[t.value,t])),g=new Set([...p.keys(),...u.keys(),...m.keys(),...[..._.keys()].filter(t=>m.has(t))]),f=[];for(const t of g){const e=p.get(t),i=u.get(t),s=i?void 0:_.get(t),g=m.get(t);let b;if(s&&g)b="readd";else if(!0===i?.hidden)b="hidden";else if(e||i)b="on_plan";else{if(!g)continue;b="available"}const v=e?.bindingStatus||o.get(t)||rc,y=i||s,w=lc(t),$=e?.area||g?.areaId||y?.area||"",k=e?.space||y?.space||h[$]||"",x=e?.name||y?.name||g?.label||t,M=e?.model||y?.model||g?.model||"",C=!!g?.parentDeviceId&&p.has(`device:${g.parentDeviceId}`),S="readd"===b?"removed":"hidden"===b?i&&hc(i)?d[t]||"automatic_hidden":"manual_hidden":"on_plan"===b?i?"visible_explicit":"visible_auto":d[t]||(C?"represented_by_parent":$&&k?"available":"no_bound_room"),P=!!e&&(!e.hidden||n),I="active"===v.kind,D=P&&(I||"ha_disabled"===v.kind&&n),L=[x,M,c[t],r[$],l[k],t,g?.sub].filter(Boolean).join(" ").toLocaleLowerCase();f.push({key:t,binding:t,category:b,status:v,reason:S,deviceId:e?.id,markerId:y?.id,name:x,icon:e?.icon||y?.icon||("entity"===w?"mdi:code-braces":"mdi:devices"),model:M,integration:c[t]||"",areaId:$,areaName:r[$]||"",spaceId:k,spaceName:l[k]||"",kind:w,isNew:!!e&&a.has(e.id),searchText:L,canFind:D,canEdit:!!e||!!i,canHide:"on_plan"===b&&I,canShow:"hidden"===b&&I,canAdd:("available"===b||"readd"===b)&&I})}const b=t=>"active"===t.status.kind?1:0;return f.sort((t,e)=>t.category.localeCompare(e.category)||Number(e.isNew)-Number(t.isNew)||b(t)-b(e)||t.name.localeCompare(e.name)||t.binding.localeCompare(e.binding))}({devices:this.host._devices,markers:this.host._markers,candidates:s,statuses:a,newDeviceIds:this.host._newIds,showHiddenOnPlan:this.host._showAll,areaNames:r,spaceNames:h,spaceByArea:c,integrationByBinding:d,reasonByBinding:u});return this.host._deviceInboxMemo={key:i,rows:_},_}_deviceForInboxRow(t){const e=t.deviceId?this.host._devices.find(e=>e.id===t.deviceId):null;if(e)return e;const i=t.markerId?this.host._markers.find(e=>e.id===t.markerId):null;return!i||i.removed?null:{id:i.id,name:t.name,model:t.model,area:t.areaId,space:t.spaceId||this.host._space,hidden:!0===i.hidden||"ha_disabled"===t.status.kind,userHidden:!0===i.hidden,bindingStatus:t.status,icon:t.icon,entities:"active"===t.status.kind?t.status.enabledEntityIds:[],allEntities:t.status.allEntityIds,primary:"active"===t.status.kind?t.status.enabledEntityIds[0]:void 0,marker:i,bindingKind:t.kind,bindingRef:t.binding.slice(t.binding.indexOf(":")+1),pdfs:i.pdfs||[]}}_openInboxMarker(t,e=!1){const i=this.host._deviceInbox;if(i){if(this.host._deviceInboxReturn={...i,anchor:t.key},this.host._deviceInbox=null,!e){const e=this._deviceForInboxRow(t);return void(e?this._openMarkerDialog(e):this._closeMarkerDialog())}this._openMarkerDialog(),this.host._markerDialog?this.host._markerDialog={...this.host._markerDialog,bindingMode:"ha",binding:t.binding,bindingOpen:!1,showEntities:"entity"===t.kind,name:""}:this._closeMarkerDialog()}}async _setInboxHidden(t,e){const i=this.host._deviceInbox,s=this.host._serverCfg;if(!i||!s||i.busy||"active"!==t.status.kind)return;const o=s.markers||[],a=o.find(e=>!e.removed&&e.binding===t.binding);if(!e&&!a)return;const n=a?.id||ss(t.binding,t.markerId,()=>`m_${Date.now().toString(36)}`),r=a?{...a,hidden:e}:{id:n,binding:t.binding,hidden:!0};s.markers=[...o.filter(e=>e.id!==n&&(e.binding!==t.binding||!0===e.removed)),r],this.host._deviceInbox={...i,busy:t.key,anchor:t.key};try{await this._saveConfigNow(),this.host._regSignature="",this.host._deviceInboxMemo=null,this.host._maybeRebuildDevices(),this.host._deviceInbox&&(this.host._deviceInbox={...this.host._deviceInbox,busy:void 0}),this.host._showToast(this.host._t("device_inbox.saved"))}catch(t){this.host._serverCfg===s&&(s.markers=o),this.host._deviceInbox&&(this.host._deviceInbox={...this.host._deviceInbox,busy:void 0}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}_findInboxDevice(t){if(!t.canFind)return;const e=this._deviceForInboxRow(t);if(!e)return;if(this.host._deviceInbox=null,e.space&&e.space!==this.host._space){if(!this.host._commitSpace(e.space))return;this.host._restoreZoom()}const i=()=>{const t=this.host._devices.find(t=>t.id===e.id)||e,i=this.host._pos(t);this.host._applyView(this.host._zoom,i.x,i.y),this.host._selId=t.id,this.host.requestUpdate(),window.setTimeout(()=>{this.host._selId===t.id&&(this.host._selId=null,this.host.requestUpdate())},1500)};requestAnimationFrame(()=>requestAnimationFrame(i))}_openMarkerDialog(t){if(this.host._vacAllCamerasFor=null,this.host._vacAllCameraCache=null,t&&this.host._ackNewDevice(t.id),this.host._norm){if(t){const e=t.marker,i=Object.prototype.hasOwnProperty.call(e||{},"is_light"),s=Object.prototype.hasOwnProperty.call(e||{},"light_entity"),o=Object.prototype.hasOwnProperty.call(e||{},"glow_color"),a=Object.prototype.hasOwnProperty.call(e||{},"value_badge"),n=Object.prototype.hasOwnProperty.call(e||{},"value_source"),r=Object.prototype.hasOwnProperty.call(e||{},"tap_action"),l=Object.prototype.hasOwnProperty.call(e||{},"toggle_entity"),h=os(e?.glow_color),c=this.host._devicePresentation(t,!0).valueBadge,d=y(this.host._planHass,t,this.host._devices),p=w(this.host._planHass,t,d),u=La(t,this.host._fullRegistryHass),_=this.host._spaceModelById(t.space)||this.host._spaceModel(),m=this.host._pos(t),g=_?Ra(t,_,[m.x,m.y],this.host._fullRegistryHass):null;this.host._markerDialog={devId:t.id,name:t.name,binding:"virtual"===t.bindingKind?"virtual":t.bindingKind+":"+t.bindingRef,bindingMode:"virtual"===t.bindingKind?"virtual":"ha",bindingOpen:!1,showEntities:"entity"===t.bindingKind&&!!this.host._fullRegistryHass.entities[t.bindingRef||""]?.device_id,bindingFilter:"",icon:t.marker?.icon||"",autoIcon:t.icon||"",display:L(t.marker?.display),rippleColor:Bt(t.marker?.ripple_color,""),rippleSize:Number(t.marker?.ripple_size)>0?Number(t.marker.ripple_size):1.5,size:Number(t.marker?.size)>0?Number(t.marker.size):1,angle:Number(t.marker?.angle)||0,tapAction:as(t.marker?.tap_action,t.primary?.split(".")[0]),tapActionTouched:!1,originalHasTapAction:r,originalTapAction:t.marker?.tap_action,tapHintAnnouncement:"",toggleEntity:e?.toggle_entity||"",toggleEntityTouched:!1,originalHasToggleEntity:l,originalToggleEntity:e?.toggle_entity,tapTarget:t.marker?.tap_target||"",tapConfirm:!0===t.marker?.tap_confirm,runFilter:"",controls:N(t.marker?.binding,t.marker?.controls,t.entities),controlsFilter:"",lightRole:!0===e?.is_light?"always":!1===e?.is_light?"never":"auto",lightRoleTouched:!1,originalHasIsLight:i,originalIsLight:e?.is_light,lightEntity:e?.light_entity||"",lightEntityTouched:!1,originalHasLightEntity:s,originalLightEntity:e?.light_entity,glowMode:null!=h?.bri?"fixed":h?"color":"auto",glowColor:h?.c||this.host._fillColors.glow_light.c,glowBrightness:Math.max(1,Math.round(100*(h?.bri??1))),glowColorDrafted:!!h,glowBrightnessDrafted:null!=h?.bri,glowTouched:!1,originalHasGlowColor:o&&(!!h||null===e?.glow_color),originalGlowColor:h||(null===e?.glow_color?null:void 0),valueBadgeEnabled:a?!0===e?.value_badge?.enabled:!!c,valueBadgeSource:e?.value_badge?.source||c?.source||p,valueBadgePosition:e?.value_badge?.position||c?.position||"right",valueBadgeTouched:!1,originalHasValueBadge:a,originalValueBadge:e?.value_badge,valueSource:e?.value_source||null,valueSourceTouched:!1,originalHasValueSource:n,originalValueSource:e?.value_source,useClimateTemp:!0===t.marker?.use_climate_temp,glowRadius:Number(t.marker?.glow_radius_cm)>0?String(this.host._imperial?Math.round(Number(t.marker.glow_radius_cm)/30.48*10)/10:Math.round(Number(t.marker.glow_radius_cm))/100):"",model:t.model||"",link:t.link||"",description:t.description||"",pdfs:[...t.pdfs||[]],room:t.marker?.room_id?t.space+"#@"+t.marker.room_id:t.space&&t.area?t.space+"#"+t.area:"",roomTouched:!1,radar:g,radarEligible:u.eligible,radarTouched:!1,radarRemove:!1,hideFromPlan:!0===t.marker?.hidden,busy:!1}}else this.host._markerDialog={name:"",binding:"virtual",bindingMode:"virtual",bindingOpen:!1,showEntities:!1,bindingFilter:"",icon:"",autoIcon:"",display:"badge",rippleColor:"",rippleSize:1.5,size:1,angle:0,tapAction:"info",tapActionTouched:!1,originalHasTapAction:!1,originalTapAction:void 0,tapHintAnnouncement:"",toggleEntity:"",toggleEntityTouched:!1,originalHasToggleEntity:!1,originalToggleEntity:void 0,tapTarget:"",tapConfirm:!1,runFilter:"",controls:[],controlsFilter:"",lightRole:"auto",lightRoleTouched:!1,originalHasIsLight:!1,originalIsLight:void 0,lightEntity:"",lightEntityTouched:!1,originalHasLightEntity:!1,originalLightEntity:void 0,glowMode:"auto",glowColor:this.host._fillColors.glow_light.c,glowBrightness:100,glowColorDrafted:!1,glowBrightnessDrafted:!1,glowTouched:!1,originalHasGlowColor:!1,originalGlowColor:void 0,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgePosition:"right",valueBadgeTouched:!1,originalHasValueBadge:!1,originalValueBadge:void 0,valueSource:null,valueSourceTouched:!1,originalHasValueSource:!1,originalValueSource:void 0,useClimateTemp:!1,glowRadius:"",model:"",link:"",description:"",pdfs:[],room:"",roomTouched:!1,radar:null,radarEligible:!1,radarTouched:!1,radarRemove:!1,hideFromPlan:!1,busy:!1,uploadId:"up_"+Date.now().toString(36)+Math.random().toString(36).slice(2,6)};this.host._markerDialog&&function(t,e){u(t,"marker",ka(e))}(this.host,this.host._markerDialog)}else this.host._showToast(this.host._t("toast.marker_needs_server"))}_runCandidates(){const t=[];for(const e of ns)for(const[i,s]of Object.entries(this.host.hass.states))i.startsWith(e+".")&&this.host._planEntityAvailable(i)&&t.push({value:i,label:s?.attributes?.friendly_name||i,sub:this.host._t("run."+e)});return t.sort((t,e)=>t.sub.localeCompare(e.sub)||t.label.localeCompare(e.label))}_bindingCandidates(){const t=nc({hass:this.host._planHass,devices:this.host._devices,markers:this.host._markers,showEntities:!!this.host._markerDialog?.showEntities,currentBinding:this.host._markerDialog?.binding,currentDeviceId:this.host._markerDialog?.devId,labels:{device:this.host._t("marker.sub_device"),z2mGroup:this.host._t("marker.sub_z2m_group"),group:this.host._t("marker.sub_group"),helper:this.host._t("marker.sub_helper"),entity:this.host._t("marker.sub_entity")}}),e=(this.host._markerDialog?.bindingFilter||"").toLowerCase().trim(),i=e?t.filter(t=>(t.label+" "+t.sub+" "+t.value).toLowerCase().includes(e)):t;return i.sort((t,e)=>t.label.localeCompare(e.label)),i.slice(0,200)}_backupErrorText(t){const e=t?.code??t?.error;if("string"==typeof e){const t=`backup.error.${e}`,i=this.host._t(t);if(i!==t)return i}return this.host._errText(t)}async _pickMarkerFiles(t){const e=t.target,i=e.files?[...e.files]:[];if(e.value="",!i.length||!this.host._markerDialog)return;const s=this.host._markerDialog.uploadId||this.host._markerDialog.devId||"new",o=[];for(const t of i)try{const e=new FormData;e.append("marker_id",s),e.append("file",t,t.name);const i=this.host.hass?.fetchWithAuth?await this.host.hass.fetchWithAuth("/api/houseplan/upload",{method:"POST",body:e}):await fetch("/api/houseplan/upload",{method:"POST",body:e,headers:this.host.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.host.hass.auth.data.access_token}`}:{}}),a=await i.json().catch(()=>({}));if(!i.ok||a.error){const t={too_large:this.host._t("err.too_large",{mb:a.max_mb||50}),bad_ext:this.host._t("err.bad_ext"),unauthorized:this.host._t("err.unauthorized")};throw new Error(t[a.error]||a.error||"HTTP "+i.status)}o.push({name:a.name||t.name,url:a.url})}catch(e){this.host._showToast(this.host._t("toast.file_failed",{name:t.name,err:this.host._errText(e)}))}o.length&&this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,pdfs:[...this.host._markerDialog.pdfs,...o]},this.host._showToast(this.host._t("toast.files_attached",{n:o.length})))}_removeMarkerPdf(t){this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,pdfs:this.host._markerDialog.pdfs.filter(e=>e.url!==t)})}_markerLightFields(t){const e={};if(t.lightRoleTouched?"always"===t.lightRole?e.is_light=!0:"never"===t.lightRole&&(e.is_light=!1):t.originalHasIsLight&&(e.is_light=t.originalIsLight??null),t.lightEntityTouched?t.lightEntity&&(e.light_entity=t.lightEntity):t.originalHasLightEntity&&(e.light_entity=t.originalLightEntity??null),t.glowTouched){if("auto"!==t.glowMode){const i={c:Bt(t.glowColor,this.host._fillColors.glow_light.c)};"fixed"===t.glowMode&&(i.bri=Math.max(.01,Math.min(1,Math.round(t.glowBrightness)/100))),e.glow_color=i}}else t.originalHasGlowColor&&(e.glow_color=t.originalGlowColor??null);return e}_markerTapActionFields(t){return t.tapActionTouched?{tap_action:t.tapAction||null}:t.originalHasTapAction?{tap_action:t.originalTapAction??null}:{}}_markerToggleEntityFields(t){return(e={touched:t.toggleEntityTouched,originalHas:t.originalHasToggleEntity,original:t.originalToggleEntity,value:t.toggleEntity}).touched?e.value?{toggle_entity:e.value}:{}:e.originalHas?{toggle_entity:e.original??null}:{};var e}async _saveMarker(){const t=this.host._markerDialog;if(!t||t.busy)return;const e=this._effectiveMarkerTapAction(t);if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return;if("virtual"===t.binding&&!t.name.trim())return;if("run"===e&&!t.tapTarget)return;if(t.valueBadgeTouched&&t.valueBadgeEnabled&&!t.valueBadgeSource)return;if("ha"===t.bindingMode){const e=this.host._bindingStatus(t.binding),i=t.devId?this.host._markers.find(e=>e.id===t.devId):null,s=!i||i.binding!==t.binding;if("active"!==e.kind&&s)return void this.host._showToast(this.host._t("ha_disabled"===e.kind?"toast.ha_disabled_add":"toast.ha_binding_unverified"));if("ha_disabled"===e.kind&&!0===i?.hidden&&!t.hideFromPlan)return this.host._markerDialog={...t,hideFromPlan:!0},void this.host._showToast(this.host._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device"))}const i=this.host._serverCfg;if(!i)return;const s=this.host._cfgRev,o=xt(i);let a=JSON.parse(JSON.stringify(i));const n=a.markers||[],r=ss(t.binding,t.devId,()=>"v_"+Date.now().toString(36)),l=t.devId,h=l?this.host._devices.find(t=>t.id===l):null,c=l?n.find(t=>t.id===l):null,d=!!c&&("string"==typeof c.area&&c.area.length>0||null===c.area&&!!c.space&&!!c.room_id),p="virtual"===t.binding||t.roomTouched||d,u="virtual"===t.binding||t.roomTouched?P(t.room):null;let _=d&&!t.roomTouched?c?.space||null:u?.space||null;const m=d&&!t.roomTouched?c?.area||null:u?.area||null,g=d&&!t.roomTouched?c?.room_id||null:u?.roomId||null,f=_||h?.space||null,b=f?this.host._spaceModelById(f):this.host._spaceModel();if(!b)return;const v=b.id;"virtual"!==t.binding||_||(_=v);let y={};if(t.radarTouched){if(t.radarRemove)y={radar:null};else if(t.radar){const e=Na(t.radar,b.cellCm||5);if(!e)return void this.host._showToast(this.host._t("radar.invalid"));y={radar:e}}}else c&&Object.prototype.hasOwnProperty.call(c,"radar")&&(y={radar:c.radar});this.host._markerDialog={...t,busy:!0};let w=null,$=!1;try{const c="virtual"===t.binding?[]:n.filter(e=>e.removed&&e.binding===t.binding).map(t=>t.id),d=c.length>0,u=N(t.binding,t.controls,this.host._bindingEntities(t.binding)),f=n.find(t=>t.id===r||t.id===l)?.vacuum||null,k={id:r,vacuum:f,...y,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?t.angle:null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===e&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:u.length?u:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),...this._markerValueSourceFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Mt(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};p&&(k.space=_,k.area=m,k.room_id=g);const x=h?.marker?.room_id??null,M=t.roomTouched&&null!=h&&(h.space!==_||h.area!==m||x!==g);let C=!1;const S=t.uploadId||l;if(S&&S!==r&&k.pdfs?.length)try{const t=await this.host.hass.callWS({type:"houseplan/files/migrate",from_id:S,to_id:r}),e=t?.mapping||{};k.pdfs=rs(k.pdfs,S,r,e),C=Object.keys(e).length>0}catch(t){this.host._showToast(this.host._t("toast.files_migrate_failed",{err:this.host._errText(t)}))}a.markers=n,l&&l!==r&&(a.markers=ls(a.markers,l,r)),l&&l!==r&&"derived_marker_state"===k.value_badge?.source?.kind&&k.value_badge.source.ref===`marker:${l}`&&(k.value_badge.source={kind:"derived_marker_state",ref:`marker:${r}`}),l&&l!==r&&"derived_marker_state"===k.value_source?.kind&&k.value_source.ref===`marker:${l}`&&(k.value_source={kind:"derived_marker_state",ref:`marker:${r}`}),a.markers=a.markers.filter(t=>t.id!==r&&t.id!==l&&("virtual"===k.binding||t.binding!==k.binding)),a.markers.push(k);const P=new Set(c);l&&l!==r&&P.add(l),P.delete(r),P.size&&a.settings?.marker_area_snapshot&&(a.settings={...a.settings,marker_area_snapshot:hs(a.settings.marker_area_snapshot,P)});let I=null;const D=l?this.host._layout[l]:null,L=D?{s:D.s||h?.space||this.host._space,x:D.x,y:D.y}:l&&h&&this.host._defPos[l]?this.host._normPos(h.space,this.host._defPos[l].x,this.host._defPos[l].y):null;if(!d&&L&&L.s===v)r===l&&this.host._layout[r]&&!M||(I={s:L.s,x:L.x,y:L.y});else if(d||!this.host._layout[r]||M){let t=b.vb[0]+b.vb[2]/2,e=b.vb[1]+b.vb[3]/2;const i=g?b.rooms.find(t=>t.id===g):m?b.rooms.find(t=>t.area===m):void 0;i&&([t,e]=this.host._roomCenter(i)),I=this.host._normPos(v,t,e)}if(this.host._serverCfg!==i||this.host._cfgRev!==s||xt(i)!==o)return this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,busy:!1}),void this.host._showToast(this.host._t("toast.conflict"));if(a=this._prepareConfigCandidate(a),w=this.host._adoption.beginOptimistic(i,a),this.host._serverCfg=a,this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate(),this.host._saveConfigDebounced.pending()&&this.host._saveConfigDebounced.cancel(),await this._saveConfigNow(w),$=!0,I){const t=cs(I);this.host._layout={...this.host._layout,[r]:t},this.host._noteLayoutRev(await this.host.hass.callWS({type:"houseplan/layout/update",device_id:r,pos:t}))}const T=new Set(c);l&&l!==r&&T.add(l),T.delete(r);for(const t of T)delete this.host._layout[t],await this.host.hass.callWS({type:"houseplan/layout/delete",device_id:t}).then(t=>this.host._noteLayoutRev(t)).catch(()=>{});C&&S&&await this.host.hass.callWS({type:"houseplan/files/cleanup",marker_id:S}).catch(()=>{}),xa(this.host),this._closeMarkerDialog(),this.host._cancelDeviceDrag(),this.host._devicePositionHistory.clear(),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("toast.marker_saved"))}catch(t){!$&&w&&(this.host._rollbackOptimistic(w),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate()),this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}async _deleteMarker(){const t=this.host._markerDialog;if(!t||t.busy||!t.devId)return;const e=t.devId?this.host._devices.find(e=>e.id===t.devId):null,i=this.host._markers.find(e=>e.id===t.devId);if(!e&&!i)return;const s=e?"virtual"===e.bindingKind?"virtual":e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:"":i.binding;if(!s)return;const o=t.name||this.host._t("device.fallback"),a=t.devId,n=await this.host._confirmDanger({key:"remove-marker",kind:"destructive",title:this.host._t("confirm.remove_marker_title"),message:this.host._t("confirm.remove_marker_body"),objectName:o,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),r=this.host._markerDialog;if(!n||!r||r.busy||r.devId!==a)return;const l=this.host._devices.find(t=>t.id===a),h=this.host._markers.find(t=>t.id===a);if(!l&&!h)return;const c=this.host._serverCfg;if(!c)return;c.markers=c.markers||[];const d=c.markers,p=l?"virtual"===l.bindingKind?"virtual":l.bindingKind&&l.bindingRef?`${l.bindingKind}:${l.bindingRef}`:"":h.binding;if(!p||p!==s)return;const u=ds(c.markers,a,p,"virtual"===p);c.markers=ps(u.markers,u.cleanupIds);const _=u.cleanupIds;_.size&&c.settings?.marker_area_snapshot&&(c.settings={...c.settings,marker_area_snapshot:hs(c.settings.marker_area_snapshot,_)}),this.host._markerDialog={...r,busy:!0};try{await this._saveConfigNow();for(const t of _){delete this.host._layout[t],delete this.host._defPos[t],this.host._dirtyPos.delete(t),this.host._sentPos.delete(t);const e=this.host._activityRt.get(t);e&&clearTimeout(e.timer),this.host._activityRt.delete(t),this.host._vacRt.delete(t),delete this.host._vacSrvTrails[t],await this.host.hass.callWS({type:"houseplan/layout/delete",device_id:t}).then(t=>this.host._noteLayoutRev(t)).catch(()=>{}),await this.host.hass.callWS({type:"houseplan/files/cleanup",marker_id:t}).catch(()=>{}),await this.host.hass.callWS({type:"houseplan/trail/delete",marker_id:t}).catch(()=>{})}this.host._deviceInboxReturn&&(this.host._deviceInboxReturn={...this.host._deviceInboxReturn,tab:"readd",anchor:p}),this._closeMarkerDialog(),this.host._cancelDeviceDrag(),this.host._devicePositionHistory.clear(),this.host._infoCard?.id===a&&this.host._closeInfoCard(),this.host._selId===a&&(this.host._selId=null),this.host._drag?.id===a&&(this.host._drag=null),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("toast.marker_removed"))}catch(t){this.host._serverCfg===c&&(c.markers=d),this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}_openSpaceDialog(t,e){if(this.host._serverStorage&&this.host._serverCfg){if("edit"===t){const i=this.host._serverCfg.spaces.find(t=>t.id===e);if(!i)return;const s=b(i),o=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?us(i.settings.custom_fill):null,a="none"===s.fill?{...o||_s,a:0}:o;this.host._spaceDialog={mode:t,spaceId:e,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:s.showBorders,showNames:s.showNames,zeroWallStyle:gs(i),displayTouched:!0,hideDecor:s.hideDecor,hideOpenings:s.hideOpenings,roomColor:s.color,roomOpacity:s.opacity,fillMode:"none"===s.fill?"custom":s.fill,customFill:a,glowEnabled:s.glow,bgColor:s.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:Oe({},i.settings),northDegInput:null===Oe({},i.settings)?"":String(Oe({},i.settings)),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:s.tempMin,tempMax:s.tempMax,tempMinInput:String(s.tempMin),tempMaxInput:String(s.tempMax),showLqi:s.showLqi??this.host._config?.show_signal??!0,cardFontScale:s.cardFontScale,labelTemp:s.labelTemp,labelHum:s.labelHum,labelLqi:s.labelLqi,labelLight:s.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:ms(Number(i.cell_cm)>0?Number(i.cell_cm):5,this.host._imperial),cellCmTouched:!1,busy:!1}}else this.host._spaceDialog={mode:t,title:"",planUrl:null,planFile:null,...$s(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:ys,roomOpacity:vs,fillMode:"custom",customFill:{..._s,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,northDegInput:"",sunRays:null,tempMin:bs,tempMax:fs,tempMinInput:String(bs),tempMaxInput:String(fs),showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:ws(this.host._imperial),cellCmInput:ms(ws(this.host._imperial),this.host._imperial),cellCmTouched:!1,busy:!1};this.host._spaceDialog&&Vo(this.host,this.host._spaceDialog)}else this.host._showToast(this.host._t("toast.integration_missing"))}async _pickPlanFile(t){const e=t.target,i=e.files?.[0];if(!i||!this.host._spaceDialog)return;e.value="",this._decorAssetGuardReplace=null;const s=await Ko(i);if("reject"===s.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===s.kind)return void(this.host._backdropGuard=s.state);const o=await Jo(i,s.ext,i.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:o})}_renderBackdropGuard(){const t=this._decorAssetGuardReplace;return null!==t?Yo(this.host,()=>{},()=>{this.host._backdropGuard=null,this._decorAssetGuardReplace=null},this.host.hass,(e,i)=>this._uploadDecorImage(e,i,t),(this.host._backdropGuard?.file.size||0)<=2097152)??d:Yo(this.host,t=>{this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:t})},()=>{this.host._backdropGuard=null},this.host.hass)??d}_useServerPlan(t){const e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this.host._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let e=0;e<40;e++){const e=this.host._display(t);if(e){const i=await new Promise(t=>{const i=new Image;i.onload=()=>t(i.naturalWidth&&i.naturalHeight?i.naturalWidth/i.naturalHeight:0),i.onerror=()=>t(0),i.src=e}),s=this.host._spaceDialog;return s&&s.planUrl===t&&Number.isFinite(i)&&i>0?(this.host._spaceDialog={...s,savedAspect:i},i):0}if(await new Promise(t=>setTimeout(t,150)),this.host._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){const e=this.host._spaceDialog,i=e?.saved?.find(e=>e.name===t);if(!e||!i||i.used_by.length||i.url===e.planUrl)return;const s=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")}),o=this.host._spaceDialog,a=o?.saved?.find(e=>e.name===t);if(s&&o&&a&&a.url===i.url&&a.modified===i.modified&&!a.used_by.length&&a.url!==o.planUrl)try{await this.host.hass.callWS({type:"houseplan/plans/delete",name:t});const e=this.host._spaceDialog;e?.saved&&(this.host._spaceDialog={...e,saved:e.saved.filter(e=>e.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 p`<div class="savedplans muted">${this.host._t("space.loading")}</div>`;const e=t.saved||[];if(!e.length)return p`<div class="savedplans muted">${this.host._t("space.no_saved")}</div>`;return p`<div class="savedplans">
|
||
========
|
||
</div>`:p``}_openingAt(t){if(!this.host._openingsR.length)return null;const e=this.host._openingsR.flatMap(e=>{const s=e.angle*Math.PI/180,i=t[0]-e.rx,o=t[1]-e.ry,a=i*Math.cos(s)+o*Math.sin(s);return Math.abs(a)>e.rlen/2+At(12,this.host._cellCm)?[]:[{o:e,localY:-i*Math.sin(s)+o*Math.cos(s)}]});if(!e.length)return null;const s=this.host._spaceModel();if(!s)return null;const i=this.host._openCuts(),o=this.host._openingWallIndexFor(s,i).value;return e.find(({o:t,localY:e})=>{const s="gate"===t.type?!t.flip_v:t.flip_v,i=t.partitionHost||this.host._spaceWalls.length||"gate"===t.type?this.host._openingFace(t,o,!!s):{ox:0,oy:0,cm:0,side:-1},a=Os({type:t.type,length:t.rlen,angle:t.angle,amount:this.host._openingAmt(t),flipH:!!t.flip_h,flipV:!!t.flip_v,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,face:i});return Math.abs(e)<=a.hitHalf})?.o||null}_resolveOpeningPlacement(t){const e=this.host._openingPreset;if("opening"!==this.host._tool||!e)return null;const s=this.host._spaceModel();if(!s)return null;const i=this.host._openCuts(),o=this.host._openingWallIndexFor(s,i),a=`${o.key}|partitions:${this.host._cfgEpoch}`;this.host._openingPlacementIntervalsCache&&this.host._openingPlacementIntervalsCache.key===a||(this.host._openingPlacementIntervalsCache={key:a,value:[...j(s.rooms,this.host._spaceWalls,i,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd),...Bs(s.partitions,this.host._cellCm,this.host._gridPitch)]}),this.host._openingDimensionContextCache&&this.host._openingDimensionContextCache.key===a||(this.host._openingDimensionContextCache={key:a,value:Td({rooms:s.rooms,walls:this.host._spaceWalls,openCuts:i,partitions:s.partitions,roomOpenings:this.host._roomWallOpeningInputs(),partitionCuts:this._partitionOpeningCuts(s),pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Vd,epsilon:2e-4*this.host._gridPitch})});const n=Hs({pointer:[t[0],t[1]],preset:e,geometryRevision:this.host._cfgEpoch,renderedLength:this.host._cmToUnits(e.lengthCm),intervals:this.host._openingPlacementIntervalsCache.value,baseTolerance:1.5*this.host._gridPitch,bodyPointerPadding:this._cssPxToRender("touch"===this.host._pointerModality.modality||"pen"===this.host._pointerModality.modality?10:6),gridStep:this.host._gridPitch});this.host._openingJambBlockCm=n.jambBlockedTarget?n.jambBlockedTarget.physicalHalfWidth/this.host._gridPitch*this.host._cellCm:null;const r=n.candidate;if(!r)return null;const l="gate"===r.type?!r.flipV:r.flipV;let h;if(r.host){const t=H({id:"preview",type:r.type,x:r.x/Vd,y:r.y/Vd,angle:r.angle,length:r.renderedLength/Vd,host:r.host},s.partitions,Vd,this.host._cellCm,this.host._gridPitch).resolved;h=t?Ws(t,l):{ox:0,oy:0,cm:0,side:-1}}else h=js(o.value,{x:r.x,y:r.y,angle:r.angle,length:r.renderedLength,flip_v:l});const c="mi"===this.host.hass?.config?.unit_system?.length,d=Od(r,this.host._openingDimensionContextCache.value).map(t=>({x:t.label[0],y:t.label[1],text:pe(t.distance/this.host._gridPitch*this.host._cellCm,c),dimension:t}));return{...r,face:h,measure:{labels:d,guide:r.measure.guide}}}_activateOpeningPlacement(t){this._activateMarkupTool("opening"),"opening"===this.host._tool&&(this.host._openingPreset=Gs(t,++this.host._openingPresetRevision),this.host._openingHoverCandidate=null,this.host._cursorPt=null)}_clearOpeningPlacement(t){this.host._openingHoverCandidate=null,this.host._openingJambBlockCm=null,t&&(this.host._openingPreset=null,this.host._openingRebindId=null)}_openingClick(t){const e=this.host._spaceModel();if(!e)return;const s=this.host._openingRebindId?null:this._openingAt(t);if(s)return void this._editOpening(s);const i=this.host._openingPreset;if(!i)return;const o=this.host._openingHoverCandidate,a=o&&qs(o,[t[0],t[1]],i.revision,this.host._cfgEpoch)?o:this._resolveOpeningPlacement(t);if(!a){if(null!=this.host._openingJambBlockCm)return void this.host._showToast(this.host._t("opening.partition_jamb_margin",{distance:pe(this.host._openingJambBlockCm,this.host._imperial)}));const s=1.5*this.host._gridPitch,i=A(t,e.rooms,s);return i&&Us(i.x,i.y,i.angle,this.host._openCuts(),s)?void this.host._showToast(this.host._t("toast.opening_on_zero_wall")):void this.host._showToast(this.host._t("toast.opening_no_wall"))}const n=this.host._openingRebindId?this.host._curSpaceCfg?.openings?.find(t=>t.id===this.host._openingRebindId):null;this.host._openingDialog={...n?{id:n.id,type:n.type,lengthCm:Math.round(n.length*Vd/this.host._gridPitch*this.host._cellCm),lengthTouched:!1,contact:n.contact||"",lock:n.lock||"",invert:!!n.invert,flipH:!!n.flip_h,flipV:!!n.flip_v}:{type:a.type,lengthCm:a.lengthCm,contact:"",lock:"",invert:!1,flipH:a.flipH,flipV:a.flipV},...a.host?{host:a.host}:{},x:a.x,y:a.y,angle:a.angle},this.host._openingRebindId=null,this.host._openingHoverCandidate=null,this.host._cursorPt=null}_editOpening(t){this.host._openingDialog={id:t.id,type:t.type,lengthCm:Math.round(t.rlen/this.host._gridPitch*this.host._cellCm),lengthTouched:!1,contact:t.contact||"",lock:t.lock||"",invert:!!t.invert,flipH:!!t.flip_h,flipV:!!t.flip_v,..."partition"===t.host?.kind?{host:{...t.host}}:{},x:t.rx,y:t.ry,angle:t.angle}}_opPointerDown(t,e){if("plan"===this.host._mode&&this.host._spaceModel()&&"resize"!==this.host._tool){t.preventDefault(),t.stopPropagation();try{Zd(t)}catch{}this.host._opDrag={id:e.id,moved:!1,sx:t.clientX,sy:t.clientY,dirty:!1,before:this._geometrySnapshot()}}}_opPointerMove(t,e){zr(this.host,"opening",()=>this._opPointerMoveNow(t,e))}_opPointerMoveNow(t,e){if(!this.host._opDrag||this.host._opDrag.id!==e.id)return;if(Math.abs(t.clientX-this.host._opDrag.sx)+Math.abs(t.clientY-this.host._opDrag.sy)<=3)return;const s=this.host._spaceModel();if(!s)return;const i=this._svgPoint(t),o=this.host._curSpaceCfg,a=o?.openings?.find(t=>t.id===e.id);if(!a)return;if("partition"===a.host?.kind){const t=s.partitions.find(t=>t.id===a.host.id);if(!t)return;const e=t.b[0]-t.a[0],o=t.b[1]-t.a[1],n=Math.hypot(e,o);if(!(n>1e-9))return;const r=e/n,l=o/n;if(Math.abs((i[0]-t.a[0])*l-(i[1]-t.a[1])*r)>4*this.host._gridPitch)return;const h=a.length*Vd/2+U(t,this.host._cellCm,this.host._gridPitch);let c=(i[0]-t.a[0])*r+(i[1]-t.a[1])*l;if(c=Math.round(c/this.host._gridPitch)*this.host._gridPitch,c=Math.max(h,Math.min(n-h,c)),n<2*h-1e-9)return;const d=c/n,p=(t.a[0]+r*c)/Vd,u=(t.a[1]+l*c)/this.host._spaceH;let _=180*Math.atan2(o,e)/Math.PI;_>=90?_-=180:_<-90&&(_+=180);const m=a.host.t!==d||a.x!==p||a.y!==u||a.angle!==_;return this.host._opDrag.moved=!0,m&&(this.host._opDrag.dirty=!0),a.host={...a.host,t:d},a.x=p,a.y=u,a.angle=_,this.host._opMeasure=null,m&&this.host._cfgEpoch++,void this.host.requestUpdate()}const n=A(i,s.rooms,4*this.host._gridPitch);if(!n)return;this.host._opDrag.moved=!0;const r=this._opRuler(n,a.length*Vd);this.host._opMeasure=r.measure;const l=r.x/Vd,h=r.y/this.host._spaceH,c=a.x!==l||a.y!==h||a.angle!==n.angle;if(c&&(this.host._opDrag.dirty=!0),a.x=l,a.y=h,a.angle=n.angle,Number(this.host._serverCfg?.model_version||0)>=9){const t=Gn(a,o?.wall_segments||[]);t?a.host=t:delete a.host}c&&this.host._cfgEpoch++,this.host.requestUpdate()}_opRuler(t,e){const s=this.host._spaceModel()?.rooms||[],i=this.host._gridPitch/2;let o=t.x,a=t.y,n=Ks([o,a],t.angle,e,s,i);if(n&&n.centered&&(o!==n.wallCenter[0]||a!==n.wallCenter[1]))[o,a]=n.wallCenter,n=Ks([o,a],t.angle,e,s,i);else if(n){const[r,l]=n.wallA,[h,c]=n.wallB,d=h-r,p=c-l,u=Math.hypot(d,p);if(u>0){const h=this.host._gridPitch,c=Math.min(e/2,u/2);let _=Math.round(((o-r)*d+(a-l)*p)/u/h)*h;_=Math.max(c,Math.min(u-c,_)),o=r+_/u*d,a=l+_/u*p,n=Ks([o,a],t.angle,e,s,i)||n}}if(!n)return{x:o,y:a,angle:t.angle,measure:null};const r="mi"===this.host.hass?.config?.unit_system?.length,l=(t,e)=>({x:e[0],y:e[1],text:pe(t/this.host._gridPitch*this.host._cellCm,r)});return{x:o,y:a,angle:t.angle,measure:{labels:[l(n.sideA,n.midA),l(n.sideB,n.midB)],guide:n.centered?{x:n.wallCenter[0],y:n.wallCenter[1],angle:t.angle}:null}}}_opPointerUp(t,e){if(!this.host._opDrag||this.host._opDrag.id!==e.id)return;Fr(this.host,"opening");const s=this.host._opDrag,i=s.moved;this.host._opMeasure=null,i&&s.dirty&&this._commitPhysicalGeometry(this.host._t("history.move_opening"),s.before);const o=()=>{this.host._opDrag=null,this.host.requestUpdate()};i?window.setTimeout(o,0):o()}_opClick(t,e){"plan"===this.host._mode&&"resize"===this.host._tool||(t.stopPropagation(),this.host._opDrag?.moved||"plan"===this.host._mode&&this._editOpening(e))}_saveOpening(){const t=this.host._openingDialog,e=this.host._curSpaceCfg,s=this.host._spaceModel();if(!t||!e||!s)return;const i=this._geometrySnapshot(),o=this.host._spaceH,a=(e.openings||[]).find(e=>e.id===t.id),n={...a||{},id:t.id||"o"+Date.now().toString(36),type:t.type,x:t.x/Vd,y:t.y/o,angle:t.angle,length:a&&!t.lengthTouched?a.length:this.host._cmToUnits(Math.max(20,t.lengthCm))/Vd,...t.host?{host:{...t.host}}:{}};if("partition"===n.host?.kind){const t=Vs(a,n)?J(n,s.partitions,Vd,this.host._cellCm,this.host._gridPitch):H(n,s.partitions,Vd,this.host._cellCm,this.host._gridPitch);if(!t.resolved){const e=s.partitions.find(t=>t.id===n.host.id);if("does-not-fit-jamb"===t.reason&&e){const t=U(e,this.host._cellCm,this.host._gridPitch);this.host._showToast(this.host._t("opening.partition_jamb_margin",{distance:pe(t/this.host._gridPitch*this.host._cellCm,this.host._imperial)}))}else this.host._showToast(this.host._t("opening.partition_orphan"));return}const i=(e.openings||[]).flatMap(t=>{if(!t.host||t.id===n.id)return[];const e=H(t,s.partitions,Vd,this.host._cellCm,this.host._gridPitch).resolved;return e?[e]:[]});if(Js(t.resolved,i))return void this.host._showToast(this.host._t("toast.opening_no_wall"));Object.assign(n,W(n,t.resolved,Vd))}else if(Number(this.host._serverCfg?.model_version||0)>=9){const t=Gn(n,e.wall_segments||[]);if(!t)return void this.host._showToast(this.host._t("toast.opening_no_wall"));n.host=t}else delete n.host;"passage"===t.type?(delete n.contact,delete n.lock,delete n.invert,delete n.flip_h,delete n.flip_v):(n.contact=t.contact||null,n.lock=("door"===t.type||"gate"===t.type)&&t.lock||null,n.invert=t.invert||void 0,n.flip_h="gate"!==t.type&&t.flipH||void 0,n.flip_v=t.flipV||void 0),e.openings=e.openings||[];const r=e.openings.findIndex(t=>t.id===n.id);r>=0?e.openings[r]=n:e.openings.push(n),this._commitPhysicalGeometry(this.host._t(t.id?"history.edit_opening":"history.add_opening"),i),this.host._openingDialog=null,this.host.requestUpdate()}_deleteOpening(){const t=this.host._openingDialog,e=this.host._curSpaceCfg;if(!t?.id||!e?.openings)return;const s=this._geometrySnapshot();e.openings=e.openings.filter(e=>e.id!==t.id),this._commitPhysicalGeometry(this.host._t("history.delete_opening"),s),this.host._openingDialog=null,this.host.requestUpdate()}_contactCandidates(){const t=[];for(const e of Object.keys(this.host.hass.states)){if(!this.host._openingEntityAvailable(e))continue;const s=e.split(".")[0];if("binary_sensor"!==s&&"cover"!==s)continue;const i=this.host.hass.states[e],o=["door","window","opening","garage_door","garage"].includes(i?.attributes?.device_class||"");("cover"!==s||o)&&t.push([e,i?.attributes?.friendly_name||e,o?0:1])}return t.sort((t,e)=>t[2]-e[2]||t[1].localeCompare(e[1])).map(([t,e])=>({value:t,label:e}))}_lockCandidates(){return Object.keys(this.host.hass.states).filter(t=>t.startsWith("lock.")&&this.host._openingEntityAvailable(t)).map(t=>({value:t,label:this.host.hass.states[t]?.attributes?.friendly_name||t})).sort((t,e)=>t.label.localeCompare(e.label))}_toggleOpeningEntityPicker(t){const e=this.host._openingDialog;if(!e)return;const s="contact"===t?!e.contactOpen:!e.lockOpen;this.host._openingDialog={...e,contactOpen:"contact"===t&&s,lockOpen:"lock"===t&&s}}_filterOpeningEntities(t,e){const s=this.host._openingDialog;s&&(this.host._openingDialog="contact"===t?{...s,contactFilter:e}:{...s,lockFilter:e})}_selectOpeningEntity(t,e){const s=this.host._openingDialog;s&&(this.host._openingDialog="contact"===t?{...s,contact:e,contactOpen:!1,contactFilter:""}:{...s,lock:e,lockOpen:!1,lockFilter:""})}_mergeClick(t){const e=this.host._spaceModel();if(!e)return;const s=e.rooms,i=[...s].reverse().find(e=>this._pointInRoom(t,e));if(!i?.id)return;const o=i.id;if(!this.host._mergeSel||this.host._mergeSel===o)return void(this.host._mergeSel=this.host._mergeSel===o?null:o);const a=s.find(t=>t.id===this.host._mergeSel),n=a?B(a):null,r=B(i),l=n&&r?Zs(n,r):null;if(!l)return this.host._showToast(this.host._t("toast.merge_not_adjacent")),void(this.host._mergeSel=null);this.host._mergeDialog={aId:this.host._mergeSel,bId:o,poly:l,pick:"a"},this.host._mergeSel=null}_commitMerge(){const t=this.host._mergeDialog,e=this.host._curSpaceCfg;if(!t||!e||!this.host._spaceModel())return;const s=this._geometrySnapshot(),i=this.host._spaceH,o="a"===t.pick?t.aId:t.bId,a="a"===t.pick?t.bId:t.aId,n=Gd(this.host._serverCfg?.markers||[],{kind:"merge",dropId:a,keepId:o});s&&n.changed&&(s.roomReferences=n.before);const r=e.rooms.find(t=>t.id===o);if(!r)return void(this.host._mergeDialog=null);r.poly=t.poly.map(t=>[t[0]/Vd,t[1]/i]),delete r.x,delete r.y,delete r.w,delete r.h,e.rooms=e.rooms.filter(t=>t.id!==a),n.changed&&this.host._serverCfg&&(this.host._serverCfg.markers=n.markers);const l=this._commitPhysicalGeometry(this.host._t("history.merge_rooms"),s);this.host._mergeDialog=null,this.host._regSignature="",this.host._maybeRebuildDevices(),l&&this.host._showToast(this.host._t("toast.rooms_merged",{name:r.name||""}))}_splitClick(t){const e=this.host._spaceModel();if(!e)return;const s=e.rooms;if(!this.host._splitSel){const e=[...s].reverse().find(e=>this._pointInRoom(t,e));if(!e?.id)return;return void(this.host._splitSel={roomId:e.id,pts:[]})}const i=s.find(t=>t.id===this.host._splitSel.roomId),o=i?B(i):null;if(!i||!o)return void(this.host._splitSel=null);const a=.02*this.host._gridPitch,n=6*this.host._gridPitch,r=Ys(t,o),l=r&&Xs(r,o,this.host._gridPitch)||r,h=r&&l&&Math.hypot(r[0]-t[0],r[1]-t[1])<=n?l:null,c=!!h&&Qs(h,o,a),d=this.host._splitSel.pts;if(!d.length)return c?void(this.host._splitSel={...this.host._splitSel,pts:[h]}):void this.host._showToast(this.host._t("toast.split_pick_wall"));if(!c){const e=this._snap(t);return ts(e,o,a)?void(this.host._splitSel={...this.host._splitSel,pts:[...d,e]}):void this.host._showToast(this.host._t("toast.split_pick_inside"))}const p=ss(o,[...d,h],a);if(!p)return void this.host._showToast(this.host._t("toast.split_bad_cut"));this._resetRoomDialogFields();const[u,_]=p,m=te(u)>=te(_)?u:_,g=m===u?_:u;this.host._pendingSplit={roomId:i.id,mainPoly:m,newPoly:g},this.host._cursorPt=null,this.host._nameSel="",this.host._areaSel="",this.host._roomDialog=!0}_markupMove(t){if(!this.host._markup)return;if("column"===this.host._tool)return void(this.host._cursorPt=this._snap(this._svgPoint(t)));if("opening"===this.host._tool||"wallthick"===this.host._tool)return void(this.host._cursorPt=this._svgPoint(t));const e="draw"===this.host._tool&&!this.host._contourClosed,s="split"===this.host._tool&&!!this.host._splitSel?.pts?.length;if(!e&&!s)return;const i=this._svgPoint(t);if(e){const e=this._resolvePlanDrawPoint(i,t.shiftKey);if(this.host._planSnapHover={contextKey:e.contextKey,candidate:e.candidate,conflicts:e.conflicts},this._syncPlanSnapConflictMarkers(e.conflicts),this._syncPlanSnapActiveMarker(e.candidate),!this.host._path.length)return;return void(this.host._cursorPt=e.point)}this.host._cursorPt=this._snap(i)}_saveRoom(){(this.host._areaSel||this.host._nameSel.trim())&&It(this.host._roomTempMin,this.host._roomTempMax).valid&&(this.host._wallFaceBatch?this._decideWallFace(!0):this._commitRoom())}_decideWallFace(t){const e=this.host._wallFaceBatch;if(!e)return;const s=e.candidates[e.index];if(!s)return;if(!t&&(s.existing||s.repair)&&1===e.candidates.length)return this.host._wallFaceBatch=null,this.host._roomDialog=!1,this.host._nameSel="",this.host._areaSel="",void this.host.requestUpdate();const i=t?{candidate:s,create:!0,name:this.host._nameSel.trim(),area:this.host._areaSel||null,settings:this._roomSettingsFromDialog()?JSON.parse(JSON.stringify(this._roomSettingsFromDialog())):null}:{candidate:s,create:!1},o=[...e.decisions,i],a=e.index+1;if(a<e.candidates.length)return this.host._wallFaceBatch={...e,decisions:o,index:a},this.host._nameSel="",this.host._areaSel="",this._resetRoomDialogFields(),void this.host.requestUpdate();this.host._wallFaceBatch={...e,decisions:o},this._applyWallFaceBatch()}_wallSourceCmAt(t,e,s){const i=t=>"number"==typeof t&&Number.isFinite(t)&&t>=0?t:null,o=.02*this.host._gridPitch,a=this.host._spaceModel();if(!a)return G;for(const e of this._planSnapGeometrySnapshot().value.segments)if(!("room"===e.sourceKind||me(t,[e.a[0],e.a[1],e.b[0],e.b[1]])>o)&&"partition"===e.sourceKind)return i(a.partitions.find(t=>t.id===e.sourceId)?.cm)??G;const n=Pc(Math.max(0,e.length-1),s,this.host._drawWallCm,G);for(let s=0;s+1<e.length;s++){const i=e[s],a=e[s+1];if(me(t,[i[0],i[1],a[0],a[1]])<=o)return n[s]??G}return G}_activePathWithRepair(t,e){const s=t.map(t=>[...t]);if(!e)return s;const i=this.host._activeWallChainPartitionIds.findIndex((t,s)=>this._activeWallSourceKey(s)===e.sourceKey),o=i>=0?i+("b"===e.endpoint?1:0):-1;return o>=0&&o<s.length&&(s[o]=[...e.to]),s}_validateWallRepair(t,e){const s=2e-4*this.host._gridPitch,i=this._wallGraphSources(e),o=i.find(e=>e.key===t.sourceKey),a=i.find(e=>e.key===t.targetSourceKey);if(!o||!a)return!1;const n="a"===t.endpoint?o.a:o.b;return!(Math.hypot(n[0]-t.from[0],n[1]-t.from[1])>s)&&(!(me(t.to,[a.a[0],a.a[1],a.b[0],a.b[1]])>s)&&!function(t,e){if(!t.sourceKey.startsWith("static:partition|"))return!1;const s=t.sourceKey.slice(17).split("|")[0];return!!s&&e.some(t=>"partition"===t.host?.kind&&t.host.id===s)}(t,this.host._curSpaceCfg?.openings||[]))}_applyWallRepair(t,e){const s=this.host._curSpaceCfg;if(!s||!this._validateWallRepair(t,e.activePath))return!1;if(!t.sourceKey.startsWith("static:"))return!1;const[i,o]=t.sourceKey.slice(7).split("|");if("partition"===i){const i=(s.partitions||[]).find(t=>t.id===o);if(!i)return!1;const a=[i.a[0]*Vd,i.a[1]*Vd],n=[i.b[0]*Vd,i.b[1]*Vd],r=Math.hypot(a[0]-t.from[0],a[1]-t.from[1])<=2e-4*this.host._gridPitch?i.a:Math.hypot(n[0]-t.from[0],n[1]-t.from[1])<=2e-4*this.host._gridPitch?i.b:null;if(!r)return!1;(e=>{e[0]=t.to[0]/Vd,e[1]=t.to[1]/Vd})(r);const l=e.activePartitionIds.indexOf(o);if(l>=0){const s=l+("b"===t.endpoint?1:0);e.activePath[s]&&(e.activePath[s]=[...t.to])}return!0}return!1}_applyWallFaceBatch(){const t=this.host._wallFaceBatch,e=this.host._curSpaceCfg,s=this.host._spaceModel();if(!t||!e||!s)return;const i=(t,e)=>{this.host._showToast(this.host._t(t,e)),this._roomDialogCancel()},o=t.decisions.filter(t=>t.create),a=o.map(t=>t.candidate.ring),n=s.rooms;for(let t=0;t<a.length;t++){if(this._contourSelfIntersects(a[t])||te(a[t])<=1e-6)return void i("toast.contour_cannot_close");for(let e=t+1;e<a.length;e++)if(Xt(a[t],a[e]))return void i("toast.contour_cannot_close");const e=o[t].candidate.split?.roomId,s=n.find(s=>s.id!==e&&!!B(s)&&Xt(a[t],B(s)));if(s)return void i("toast.room_overlap",{name:s.name||""})}if((e.rooms||[]).length+o.length>400)return void i("toast.physical_limit");if(o.some(t=>t.candidate.split&&!e.rooms.some(e=>e.id===t.candidate.split.roomId)))return void i("toast.contour_cannot_close");const r=o.map(t=>t.candidate.repair).filter(t=>!!t);if(r.length>1||r[0]&&!this._validateWallRepair(r[0],t.activePath))return void i("toast.wall_repair_changed");if(!o.length){if(!this._finalizeWallChainPartitions(t.activePartitionIds))return;return this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host._wallFaceBatch=null,this.host._roomDialog=!1,this.host._nameSel="",this.host._areaSel="",this.host.requestUpdate(),void this.host._showToast(this.host._t("toast.wall_chain_saved"))}const l=new Set(t.activePartitionIds),h=2e-4*this.host._gridPitch,c=o.map(t=>t.candidate.ring.map((t,e,i)=>{const o=i[(e+1)%i.length],a=s.partitions.filter(e=>{const s=Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1]);if(!(s>h))return!1;const i=(e.b[0]-e.a[0])/s,a=(e.b[1]-e.a[1])/s,n=t=>(t[0]-e.a[0])*i+(t[1]-e.a[1])*a;return me(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=h&&me(o,[e.a[0],e.a[1],e.b[0],e.b[1]])<=h&&n(t)>=-h&&n(t)<=s+h&&n(o)>=-h&&n(o)<=s+h});return a.sort((t,e)=>Number(l.has(e.id))-Number(l.has(t.id))||Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])-Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])||t.id.localeCompare(e.id)),a[0]?.id||""})),d=this._geometrySnapshot();if(!d)return void i("toast.geometry_unsafe");const p=()=>{this._restoreGeometryStateLocal(d),i("toast.geometry_unsafe")};if(r[0]&&!this._applyWallRepair(r[0],t))return void i("toast.wall_repair_changed");const u=o.some(t=>!!t.candidate.split),_=u?Re(s.rooms,e.walls,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd):null,m=u&&Array.isArray(e.walls)?e.walls:null;for(const t of o){const s=t.candidate.split;if(!s)continue;const i=e.rooms.find(t=>t.id===s.roomId);if(!i)return void p();i.poly=s.mainPoly.map(t=>[t[0]/Vd,t[1]/this.host._spaceH]),delete i.x,delete i.y,delete i.w,delete i.h}const g=Date.now().toString(36),f=[];if(o.forEach((t,s)=>{const i=t.area?this.host.hass.areas[t.area]?.name:"",o={id:`r${g}-${s}`,name:t.name||i||this.host._t("room.default_name"),area:t.area||null,poly:t.candidate.ring.map(t=>[t[0]/Vd,t[1]/this.host._spaceH]),...c[s].some(Boolean)?{wall_ids:c[s]}:{},...t.settings?{settings:JSON.parse(JSON.stringify(t.settings))}:{}};e.rooms.push(o),f.push({room:o,decision:t})}),u){const t=this.host._normalizeWalls(_,this.host._openCuts());t.length?e.walls=t:m?.length?e.walls=m:delete e.walls}if(f.length){this.host._cfgEpoch++;const s=this.host._openCuts(),i=this.host._spaceModel();if(!i)return void p();let o=e.walls;for(const{room:e,decision:a}of f){const n=a.candidate.ring,r=this._wallSourceCmAt(n[0],t.activePath,t.activeCms);o=ti(o,i.rooms,e.id,r,this.host._wallKeyPitch,s,Vd);for(const a of j(i.rooms,o,s,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd)){if(a.roomId!==e.id||"outer"!==a.kind)continue;const s=[(a.a[0]+a.b[0])/2,(a.a[1]+a.b[1])/2];o=K(o,a.a,a.b,this._wallSourceCmAt(s,t.activePath,t.activeCms),this.host._wallKeyPitch,Vd)}}const a=this.host._normalizeWalls(o,s);a.length?e.walls=a:delete e.walls,this.host._cfgEpoch++;const n=this.host._spaceModel();if(!n)return void p();const r=gn(e,n,e.walls,s,{pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Vd,allowCoincidentPartitions:!0});r.walls.length?e.walls=r.walls:delete e.walls,r.partitions.length?e.partitions=r.partitions:delete e.partitions,r.openings.length?e.openings=r.openings:delete e.openings}if(!this._commitPhysicalGeometry(this.host._t("history.wall_face_batch"),d))return;this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host._wallFaceBatch=null,this.host._roomDialog=!1,this.host._nameSel="",this.host._areaSel="",this.host._regSignature="",this.host._maybeRebuildDevices();const b=new Set(o.map(t=>t.area).filter(t=>!!t));if(b.size){const t={...this.host._layout};for(const e of this.host._devices){if(!b.has(e.area||"")||e.space!==this.host._space)continue;if(this.host._layout[e.id])continue;const s=this.host._defPos[e.id];s&&(t[e.id]={s:this.host._space,x:s.x/Vd,y:s.y/Vd},this.host._dirtyPos.add(e.id))}this.host._layout=t,this.host._persistLayout()}this.host._showToast(this.host._t(o.length?"toast.wall_rooms_saved":"toast.wall_chain_saved",{n:o.length}))}_commitRoom(){const t=this.host._curSpaceCfg,e=this.host._spaceModel();if(!t||!e)return;const s=this._geometrySnapshot();if(!s)return;const i=()=>{this._restoreGeometryStateLocal(s),this.host._showToast(this.host._t("toast.geometry_unsafe"))},o=this.host._spaceH,a=!!this.host._pendingSplit,n=a?Re(e.rooms,t.walls,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd):null,r=a&&Array.isArray(t.walls)?t.walls:null;let l;if(this.host._pendingSplit){const e=t.rooms.find(t=>t.id===this.host._pendingSplit.roomId);if(!e)return this.host._pendingSplit=null,this.host._splitSel=null,void(this.host._roomDialog=!1);e.poly=this.host._pendingSplit.mainPoly.map(t=>[t[0]/Vd,t[1]/o]),delete e.x,delete e.y,delete e.w,delete e.h,l=this.host._pendingSplit.newPoly}else{if(!this.host._contourClosed)return;l=this.host._path.slice(0,-1)}const h=this.host._areaSel?this.host.hass.areas[this.host._areaSel]?.name:"",c={id:"r"+Date.now().toString(36),name:this.host._nameSel||h||this.host._t("room.default_name"),area:this.host._areaSel||null,poly:l.map(t=>[t[0]/Vd,t[1]/o]),...this._roomSettingsFromDialog()?{settings:this._roomSettingsFromDialog()}:{}};if(t.rooms.push(c),a){const e=this.host._normalizeWalls(n,this.host._openCuts());e.length?t.walls=e:r?.length?t.walls=r:delete t.walls}if(!a){const e=Pc(l.length,[...this.host._wallChainSegmentCms,this.host._closingWallCm??void 0],this.host._drawWallCm,G),s=e[0];if(null!=s){this.host._cfgEpoch++;const o=this.host._openCuts(),a=this.host._spaceModel();if(!a)return void i();let n=ti(t.walls,a.rooms,c.id,s,this.host._wallKeyPitch,o,Vd);for(const t of j(a.rooms,n,o,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd)){if(t.roomId!==c.id||"outer"!==t.kind)continue;const s=[(t.a[0]+t.b[0])/2,(t.a[1]+t.b[1])/2],i=l.findIndex((t,e)=>{const i=l[(e+1)%l.length];return me(s,[t[0],t[1],i[0],i[1]])<=.02*this.host._gridPitch});i>=0&&(n=K(n,t.a,t.b,e[i],this.host._wallKeyPitch,Vd))}n=this.host._normalizeWalls(n,o),n.length?t.walls=n:delete t.walls;const r=this.host._spaceModel();if(!r)return void i();const h=gn(t,r,t.walls,o,{pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Vd,allowCoincidentPartitions:!0});h.walls.length?t.walls=h.walls:delete t.walls,h.partitions.length?t.partitions=h.partitions:delete t.partitions,h.openings.length?t.openings=h.openings:delete t.openings}}const d=this._commitPhysicalGeometry(this.host._t(a?"history.split_room":"history.add_room"),s);this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host._pendingSplit=null,this.host._splitSel=null;const p=this.host._areaSel;if(this.host._areaSel="",this.host._nameSel="",this.host._roomDialog=!1,this.host._regSignature="",this.host._maybeRebuildDevices(),!d)return;let u=0;if(p){const t=Vd,e={...this.host._layout};for(const s of this.host._devices){if(s.area!==p||s.space!==this.host._space)continue;if(u++,this.host._layout[s.id])continue;const i=this.host._defPos[s.id];i&&(e[s.id]={s:this.host._space,x:i.x/Vd,y:i.y/t},this.host._dirtyPos.add(s.id))}this.host._layout=e,this.host._persistLayout()}const _=this.host._model.find(t=>t.id===this.host._space)?.rooms.length||0;this.host._showToast(p?this.host._t("toast.room_saved",{n:_,added:u}):this.host._t("toast.room_saved_no_area",{n:_}))}_cancelPath(){this.host._wallRepairDiagnostic=null,this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this._clearPlanSnapHover(),this.host._roomDialog=!1,this.host._pendingSplit=null,this.host._wallFaceBatch=null,this.host._splitSel=null,this.host._mergeSel=null,this.host._mergeDialog=null,this.host._physicalSel=null,this.host._physicalDrag=null,this.host._physicalRotate=null,this._clearOpeningPlacement(!0)}_roomDialogCancel(){if(this.host._roomDialog=!1,this.host._roomEditId)return this.host._roomEditId=null,this.host._nameSel="",void(this.host._areaSel="");if(this.host._wallFaceBatch){const t=this.host._wallFaceBatch;return this.host._wallFaceBatch=null,this.host._path=t.activePath.map(t=>[...t]),this.host._wallChainSegmentCms=[...t.activeCms],this.host._activeWallChainPartitionIds=[...t.activePartitionIds],this.host._activeWallChainId||=`chain-${Date.now().toString(36)}`,this.host._nameSel="",this.host._areaSel="",void this.host.requestUpdate()}if(this.host._pendingSplit)return this.host._pendingSplit=null,void(this.host._splitSel=null);this.host._undoPoint()}_openDeviceInbox(){this.host._deviceInboxReturn=null,this.host._deviceInbox=this.host._deviceInbox||{tab:"on_plan",search:"",showEntities:!1,onlyNew:!1,limit:100}}_closeMarkerDialog(){this._radarSetup.isDirty()?this._closeMarkerDialogGuarded():(this._radarSetup.reset(),function(t){if(t._markerDialog=null,!t._deviceInboxReturn)return;const e={...t._deviceInboxReturn};t._deviceInbox=e,t._deviceInboxReturn=null,e.anchor&&t.updateComplete.then(()=>requestAnimationFrame(()=>{const s=`.device-inbox-row[data-binding="${CSS.escape(e.anchor)}"]`;t.renderRoot.querySelector(s)?.scrollIntoView({block:"nearest"})}))}(this.host))}async _closeMarkerDialogGuarded(){if(!await this._radarSetup.discardIfAllowed())return await this.host.updateComplete,void this.host.renderRoot.querySelector("#marker-dialog")?.rejectClose();this._closeMarkerDialog()}_deviceInboxCandidates(t){return ic({hass:this.host._planHass,devices:this.host._devices,markers:this.host._markers,showEntities:t,labels:{device:this.host._t("marker.sub_device"),z2mGroup:this.host._t("marker.sub_z2m_group"),group:this.host._t("marker.sub_group"),helper:this.host._t("marker.sub_helper"),entity:this.host._t("marker.sub_entity")}})}_deviceInboxRows(){const t=this.host._deviceInbox||this.host._deviceInboxReturn,e=!!t?.showEntities,s=[this.host._haRegistry.revision,this.host._cfgRev,this.host._cfgEpoch,this.host._regSignature,this.host._newSyncKey,e?1:0,this.host._showAll?1:0,l(this.host.hass,this.host._config?.language)].join("|");if(this.host._deviceInboxMemo?.key===s)return this.host._deviceInboxMemo.rows;const i=this._deviceInboxCandidates(e),o=new Set(i.map(t=>t.value));for(const t of this.host._markers)t.binding&&"virtual"!==t.binding&&o.add(t.binding);for(const t of this.host._devices)t.bindingKind&&"virtual"!==t.bindingKind&&t.bindingRef&&o.add(`${t.bindingKind}:${t.bindingRef}`);const a=new Map;for(const t of o)a.set(t,this.host._bindingStatus(t));const n=this.host._areaToSpace,r={};for(const[t,e]of Object.entries(this.host.hass?.areas||{}))r[t]=n[t]?.room?.name||e?.name||t;for(const[t,e]of Object.entries(n))r[t]=e.room.name||r[t]||t;const h=Object.fromEntries(this.host._model.map(t=>[t.id,t.title])),c=Object.fromEntries(Object.entries(n).map(([t,e])=>[t,e.space])),d={},p=new Map;for(const[t,e]of Object.entries(this.host._fullRegistryHass.entities||{})){const s=String(e?.platform||"").trim();if(s&&(d[`entity:${t}`]=s),s&&e?.device_id){const t=p.get(e.device_id)||new Set;t.add(s),p.set(e.device_id,t)}}for(const[t,e]of p)d[`device:${t}`]=[...e].sort().join(", ");const u={};for(const[t,e]of Object.entries(this.host._fullRegistryHass.devices||{})){const s=`device:${t}`,i=p.get(t)||new Set,o=Array.isArray(e?.identifiers?.[0])?String(e.identifiers[0][0]||""):"";o&&!d[s]&&(d[s]=o);const a=[o,...i].some(t=>this.host._excluded.has(t));"service"===e?.entry_type?u[s]="service_entry":a?u[s]="excluded_integration":"Group"===e?.model?u[s]="grouped_light":/scene/i.test(e?.model||"")?u[s]="excluded_domain":(/bridge/i.test(`${e?.model||""}${e?.name||""}`)||"myheat"===o&&e?.via_device_id)&&(u[s]="represented_by_parent")}const _=function(t){const{devices:e,markers:s,candidates:i,statuses:o,newDeviceIds:a,showHiddenOnPlan:n,areaNames:r={},spaceNames:l={},spaceByArea:h={},integrationByBinding:c={},reasonByBinding:d={}}=t,p=new Map;for(const t of e)!t.virtual&&t.bindingKind&&"virtual"!==t.bindingKind&&t.bindingRef&&p.set(`${t.bindingKind}:${t.bindingRef}`,t);const u=new Map,_=new Map;for(const t of s)t?.binding&&"virtual"!==t.binding&&(t.removed?_.set(t.binding,t):u.set(t.binding,t));const m=new Map(i.map(t=>[t.value,t])),g=new Set([...p.keys(),...u.keys(),...m.keys(),...[..._.keys()].filter(t=>m.has(t))]),f=[];for(const t of g){const e=p.get(t),s=u.get(t),i=s?void 0:_.get(t),g=m.get(t);let b;if(i&&g)b="readd";else if(!0===s?.hidden)b="hidden";else if(e||s)b="on_plan";else{if(!g)continue;b="available"}const v=e?.bindingStatus||o.get(t)||oc,y=s||i,w=ac(t),$=e?.area||g?.areaId||y?.area||"",k=e?.space||y?.space||h[$]||"",x=e?.name||y?.name||g?.label||t,M=e?.model||y?.model||g?.model||"",C=!!g?.parentDeviceId&&p.has(`device:${g.parentDeviceId}`),S="readd"===b?"removed":"hidden"===b?s&&nc(s)?d[t]||"automatic_hidden":"manual_hidden":"on_plan"===b?s?"visible_explicit":"visible_auto":d[t]||(C?"represented_by_parent":$&&k?"available":"no_bound_room"),P=!!e&&(!e.hidden||n),I="active"===v.kind,D=P&&(I||"ha_disabled"===v.kind&&n),L=[x,M,c[t],r[$],l[k],t,g?.sub].filter(Boolean).join(" ").toLocaleLowerCase();f.push({key:t,binding:t,category:b,status:v,reason:S,deviceId:e?.id,markerId:y?.id,name:x,icon:e?.icon||y?.icon||("entity"===w?"mdi:code-braces":"mdi:devices"),model:M,integration:c[t]||"",areaId:$,areaName:r[$]||"",spaceId:k,spaceName:l[k]||"",kind:w,isNew:!!e&&a.has(e.id),searchText:L,canFind:D,canEdit:!!e||!!s,canHide:"on_plan"===b&&I,canShow:"hidden"===b&&I,canAdd:("available"===b||"readd"===b)&&I})}const b=t=>"active"===t.status.kind?1:0;return f.sort((t,e)=>t.category.localeCompare(e.category)||Number(e.isNew)-Number(t.isNew)||b(t)-b(e)||t.name.localeCompare(e.name)||t.binding.localeCompare(e.binding))}({devices:this.host._devices,markers:this.host._markers,candidates:i,statuses:a,newDeviceIds:this.host._newIds,showHiddenOnPlan:this.host._showAll,areaNames:r,spaceNames:h,spaceByArea:c,integrationByBinding:d,reasonByBinding:u});return this.host._deviceInboxMemo={key:s,rows:_},_}_deviceForInboxRow(t){const e=t.deviceId?this.host._devices.find(e=>e.id===t.deviceId):null;if(e)return e;const s=t.markerId?this.host._markers.find(e=>e.id===t.markerId):null;return!s||s.removed?null:{id:s.id,name:t.name,model:t.model,area:t.areaId,space:t.spaceId||this.host._space,hidden:!0===s.hidden||"ha_disabled"===t.status.kind,userHidden:!0===s.hidden,bindingStatus:t.status,icon:t.icon,entities:"active"===t.status.kind?t.status.enabledEntityIds:[],allEntities:t.status.allEntityIds,primary:"active"===t.status.kind?t.status.enabledEntityIds[0]:void 0,marker:s,bindingKind:t.kind,bindingRef:t.binding.slice(t.binding.indexOf(":")+1),pdfs:s.pdfs||[]}}_openInboxMarker(t,e=!1){const s=this.host._deviceInbox;if(s){if(this.host._deviceInboxReturn={...s,anchor:t.key},this.host._deviceInbox=null,!e){const e=this._deviceForInboxRow(t);return void(e?this._openMarkerDialog(e):this._closeMarkerDialog())}this._openMarkerDialog(),this.host._markerDialog?this.host._markerDialog={...this.host._markerDialog,bindingMode:"ha",binding:t.binding,bindingOpen:!1,showEntities:"entity"===t.kind,name:""}:this._closeMarkerDialog()}}async _setInboxHidden(t,e){const s=this.host._deviceInbox,i=this.host._serverCfg;if(!s||!i||s.busy||"active"!==t.status.kind)return;const o=i.markers||[],a=o.find(e=>!e.removed&&e.binding===t.binding);if(!e&&!a)return;const n=a?.id||ei(t.binding,t.markerId,()=>`m_${Date.now().toString(36)}`),r=a?{...a,hidden:e}:{id:n,binding:t.binding,hidden:!0};i.markers=[...o.filter(e=>e.id!==n&&(e.binding!==t.binding||!0===e.removed)),r],this.host._deviceInbox={...s,busy:t.key,anchor:t.key};try{await this._saveConfigNow(),this.host._regSignature="",this.host._deviceInboxMemo=null,this.host._maybeRebuildDevices(),this.host._deviceInbox&&(this.host._deviceInbox={...this.host._deviceInbox,busy:void 0}),this.host._showToast(this.host._t("device_inbox.saved"))}catch(t){this.host._serverCfg===i&&(i.markers=o),this.host._deviceInbox&&(this.host._deviceInbox={...this.host._deviceInbox,busy:void 0}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}_findInboxDevice(t){if(!t.canFind)return;const e=this._deviceForInboxRow(t);if(!e)return;if(this.host._deviceInbox=null,e.space&&e.space!==this.host._space){if(!this.host._commitSpace(e.space))return;this.host._restoreZoom()}const s=()=>{const t=this.host._devices.find(t=>t.id===e.id)||e,s=this.host._pos(t);this.host._applyView(this.host._zoom,s.x,s.y),this.host._selId=t.id,this.host.requestUpdate(),window.setTimeout(()=>{this.host._selId===t.id&&(this.host._selId=null,this.host.requestUpdate())},1500)};requestAnimationFrame(()=>requestAnimationFrame(s))}_openMarkerDialog(t){if(this.host._vacAllCamerasFor=null,this.host._vacAllCameraCache=null,t&&this.host._ackNewDevice(t.id),this.host._norm){if(t){const e=t.marker,s=Object.prototype.hasOwnProperty.call(e||{},"is_light"),i=Object.prototype.hasOwnProperty.call(e||{},"light_entity"),o=Object.prototype.hasOwnProperty.call(e||{},"glow_color"),a=Object.prototype.hasOwnProperty.call(e||{},"value_badge"),n=Object.prototype.hasOwnProperty.call(e||{},"value_source"),r=Object.prototype.hasOwnProperty.call(e||{},"tap_action"),l=Object.prototype.hasOwnProperty.call(e||{},"toggle_entity"),h=si(e?.glow_color),c=this.host._devicePresentation(t,!0).valueBadge,d=y(this.host._planHass,t,this.host._devices),p=w(this.host._planHass,t,d),u=Pa(t,this.host._fullRegistryHass),_=this.host._spaceModelById(t.space)||this.host._spaceModel(),m=this.host._pos(t),g=_?Da(t,_,[m.x,m.y],this.host._fullRegistryHass):null;this.host._markerDialog={devId:t.id,name:t.name,binding:"virtual"===t.bindingKind?"virtual":t.bindingKind+":"+t.bindingRef,bindingMode:"virtual"===t.bindingKind?"virtual":"ha",bindingOpen:!1,showEntities:"entity"===t.bindingKind&&!!this.host._fullRegistryHass.entities[t.bindingRef||""]?.device_id,bindingFilter:"",icon:t.marker?.icon||"",autoIcon:t.icon||"",display:L(t.marker?.display),rippleColor:Bt(t.marker?.ripple_color,""),rippleSize:Number(t.marker?.ripple_size)>0?Number(t.marker.ripple_size):1.5,size:Number(t.marker?.size)>0?Number(t.marker.size):1,angle:Number(t.marker?.angle)||0,tapAction:ii(t.marker?.tap_action,t.primary?.split(".")[0]),tapActionTouched:!1,originalHasTapAction:r,originalTapAction:t.marker?.tap_action,tapHintAnnouncement:"",toggleEntity:e?.toggle_entity||"",toggleEntityTouched:!1,originalHasToggleEntity:l,originalToggleEntity:e?.toggle_entity,tapTarget:t.marker?.tap_target||"",tapConfirm:!0===t.marker?.tap_confirm,runFilter:"",controls:N(t.marker?.binding,t.marker?.controls,t.entities),controlsFilter:"",lightRole:!0===e?.is_light?"always":!1===e?.is_light?"never":"auto",lightRoleTouched:!1,originalHasIsLight:s,originalIsLight:e?.is_light,lightEntity:e?.light_entity||"",lightEntityTouched:!1,originalHasLightEntity:i,originalLightEntity:e?.light_entity,glowMode:null!=h?.bri?"fixed":h?"color":"auto",glowColor:h?.c||this.host._fillColors.glow_light.c,glowBrightness:Math.max(1,Math.round(100*(h?.bri??1))),glowColorDrafted:!!h,glowBrightnessDrafted:null!=h?.bri,glowTouched:!1,originalHasGlowColor:o&&(!!h||null===e?.glow_color),originalGlowColor:h||(null===e?.glow_color?null:void 0),valueBadgeEnabled:a?!0===e?.value_badge?.enabled:!!c,valueBadgeSource:e?.value_badge?.source||c?.source||p,valueBadgePosition:e?.value_badge?.position||c?.position||"right",valueBadgeTouched:!1,originalHasValueBadge:a,originalValueBadge:e?.value_badge,valueSource:e?.value_source||null,valueSourceTouched:!1,originalHasValueSource:n,originalValueSource:e?.value_source,useClimateTemp:!0===t.marker?.use_climate_temp,glowRadius:Number(t.marker?.glow_radius_cm)>0?String(this.host._imperial?Math.round(Number(t.marker.glow_radius_cm)/30.48*10)/10:Math.round(Number(t.marker.glow_radius_cm))/100):"",model:t.model||"",link:t.link||"",description:t.description||"",pdfs:[...t.pdfs||[]],room:t.marker?.room_id?t.space+"#@"+t.marker.room_id:t.space&&t.area?t.space+"#"+t.area:"",roomTouched:!1,radar:g,radarEligible:u.eligible,radarTouched:!1,radarRemove:!1,hideFromPlan:!0===t.marker?.hidden,busy:!1}}else this.host._markerDialog={name:"",binding:"virtual",bindingMode:"virtual",bindingOpen:!1,showEntities:!1,bindingFilter:"",icon:"",autoIcon:"",display:"badge",rippleColor:"",rippleSize:1.5,size:1,angle:0,tapAction:"info",tapActionTouched:!1,originalHasTapAction:!1,originalTapAction:void 0,tapHintAnnouncement:"",toggleEntity:"",toggleEntityTouched:!1,originalHasToggleEntity:!1,originalToggleEntity:void 0,tapTarget:"",tapConfirm:!1,runFilter:"",controls:[],controlsFilter:"",lightRole:"auto",lightRoleTouched:!1,originalHasIsLight:!1,originalIsLight:void 0,lightEntity:"",lightEntityTouched:!1,originalHasLightEntity:!1,originalLightEntity:void 0,glowMode:"auto",glowColor:this.host._fillColors.glow_light.c,glowBrightness:100,glowColorDrafted:!1,glowBrightnessDrafted:!1,glowTouched:!1,originalHasGlowColor:!1,originalGlowColor:void 0,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgePosition:"right",valueBadgeTouched:!1,originalHasValueBadge:!1,originalValueBadge:void 0,valueSource:null,valueSourceTouched:!1,originalHasValueSource:!1,originalValueSource:void 0,useClimateTemp:!1,glowRadius:"",model:"",link:"",description:"",pdfs:[],room:"",roomTouched:!1,radar:null,radarEligible:!1,radarTouched:!1,radarRemove:!1,hideFromPlan:!1,busy:!1,uploadId:"up_"+Date.now().toString(36)+Math.random().toString(36).slice(2,6)};this.host._markerDialog&&function(t,e){u(t,"marker",ya(e))}(this.host,this.host._markerDialog)}else this.host._showToast(this.host._t("toast.marker_needs_server"))}_runCandidates(){const t=[];for(const e of oi)for(const[s,i]of Object.entries(this.host.hass.states))s.startsWith(e+".")&&this.host._planEntityAvailable(s)&&t.push({value:s,label:i?.attributes?.friendly_name||s,sub:this.host._t("run."+e)});return t.sort((t,e)=>t.sub.localeCompare(e.sub)||t.label.localeCompare(e.label))}_bindingCandidates(){const t=ic({hass:this.host._planHass,devices:this.host._devices,markers:this.host._markers,showEntities:!!this.host._markerDialog?.showEntities,currentBinding:this.host._markerDialog?.binding,currentDeviceId:this.host._markerDialog?.devId,labels:{device:this.host._t("marker.sub_device"),z2mGroup:this.host._t("marker.sub_z2m_group"),group:this.host._t("marker.sub_group"),helper:this.host._t("marker.sub_helper"),entity:this.host._t("marker.sub_entity")}}),e=(this.host._markerDialog?.bindingFilter||"").toLowerCase().trim(),s=e?t.filter(t=>(t.label+" "+t.sub+" "+t.value).toLowerCase().includes(e)):t;return s.sort((t,e)=>t.label.localeCompare(e.label)),s.slice(0,200)}_backupErrorText(t){const e=t?.code??t?.error;if("string"==typeof e){const t=`backup.error.${e}`,s=this.host._t(t);if(s!==t)return s}return this.host._errText(t)}async _pickMarkerFiles(t){const e=t.target,s=e.files?[...e.files]:[];if(e.value="",!s.length||!this.host._markerDialog)return;const i=this.host._markerDialog.uploadId||this.host._markerDialog.devId||"new",o=[];for(const t of s)try{const e=new FormData;e.append("marker_id",i),e.append("file",t,t.name);const s=this.host.hass?.fetchWithAuth?await this.host.hass.fetchWithAuth("/api/houseplan/upload",{method:"POST",body:e}):await fetch("/api/houseplan/upload",{method:"POST",body:e,headers:this.host.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.host.hass.auth.data.access_token}`}:{}}),a=await s.json().catch(()=>({}));if(!s.ok||a.error){const t={too_large:this.host._t("err.too_large",{mb:a.max_mb||50}),bad_ext:this.host._t("err.bad_ext"),unauthorized:this.host._t("err.unauthorized")};throw new Error(t[a.error]||a.error||"HTTP "+s.status)}o.push({name:a.name||t.name,url:a.url})}catch(e){this.host._showToast(this.host._t("toast.file_failed",{name:t.name,err:this.host._errText(e)}))}o.length&&this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,pdfs:[...this.host._markerDialog.pdfs,...o]},this.host._showToast(this.host._t("toast.files_attached",{n:o.length})))}_removeMarkerPdf(t){this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,pdfs:this.host._markerDialog.pdfs.filter(e=>e.url!==t)})}_markerLightFields(t){const e={};if(t.lightRoleTouched?"always"===t.lightRole?e.is_light=!0:"never"===t.lightRole&&(e.is_light=!1):t.originalHasIsLight&&(e.is_light=t.originalIsLight??null),t.lightEntityTouched?t.lightEntity&&(e.light_entity=t.lightEntity):t.originalHasLightEntity&&(e.light_entity=t.originalLightEntity??null),t.glowTouched){if("auto"!==t.glowMode){const s={c:Bt(t.glowColor,this.host._fillColors.glow_light.c)};"fixed"===t.glowMode&&(s.bri=Math.max(.01,Math.min(1,Math.round(t.glowBrightness)/100))),e.glow_color=s}}else t.originalHasGlowColor&&(e.glow_color=t.originalGlowColor??null);return e}_markerTapActionFields(t){return t.tapActionTouched?{tap_action:t.tapAction||null}:t.originalHasTapAction?{tap_action:t.originalTapAction??null}:{}}_markerToggleEntityFields(t){return(e={touched:t.toggleEntityTouched,originalHas:t.originalHasToggleEntity,original:t.originalToggleEntity,value:t.toggleEntity}).touched?e.value?{toggle_entity:e.value}:{}:e.originalHas?{toggle_entity:e.original??null}:{};var e}async _saveMarker(){const t=this.host._markerDialog;if(!t||t.busy)return;const e=this._effectiveMarkerTapAction(t);if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return;if("virtual"===t.binding&&!t.name.trim())return;if("run"===e&&!t.tapTarget)return;if(t.valueBadgeTouched&&t.valueBadgeEnabled&&!t.valueBadgeSource)return;if("ha"===t.bindingMode){const e=this.host._bindingStatus(t.binding),s=t.devId?this.host._markers.find(e=>e.id===t.devId):null,i=!s||s.binding!==t.binding;if("active"!==e.kind&&i)return void this.host._showToast(this.host._t("ha_disabled"===e.kind?"toast.ha_disabled_add":"toast.ha_binding_unverified"));if("ha_disabled"===e.kind&&!0===s?.hidden&&!t.hideFromPlan)return this.host._markerDialog={...t,hideFromPlan:!0},void this.host._showToast(this.host._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device"))}const s=this.host._serverCfg;if(!s)return;const i=this.host._cfgRev,o=xt(s);let a=JSON.parse(JSON.stringify(s));const n=a.markers||[],r=ei(t.binding,t.devId,()=>"v_"+Date.now().toString(36)),l=t.devId,h=l?this.host._devices.find(t=>t.id===l):null,c=l?n.find(t=>t.id===l):null,d=!!c&&("string"==typeof c.area&&c.area.length>0||null===c.area&&!!c.space&&!!c.room_id),p="virtual"===t.binding||t.roomTouched||d,u="virtual"===t.binding||t.roomTouched?P(t.room):null;let _=d&&!t.roomTouched?c?.space||null:u?.space||null;const m=d&&!t.roomTouched?c?.area||null:u?.area||null,g=d&&!t.roomTouched?c?.room_id||null:u?.roomId||null,f=_||h?.space||null,b=f?this.host._spaceModelById(f):this.host._spaceModel();if(!b)return;const v=b.id;"virtual"!==t.binding||_||(_=v);let y={};if(t.radarTouched){if(t.radarRemove)y={radar:null};else if(t.radar){const e=Ra(t.radar,b.cellCm||5);if(!e)return void this.host._showToast(this.host._t("radar.invalid"));y={radar:e}}}else c&&Object.prototype.hasOwnProperty.call(c,"radar")&&(y={radar:c.radar});this.host._markerDialog={...t,busy:!0};let w=null,$=!1;try{const c="virtual"===t.binding?[]:n.filter(e=>e.removed&&e.binding===t.binding).map(t=>t.id),d=c.length>0,u=N(t.binding,t.controls,this.host._bindingEntities(t.binding)),f=n.find(t=>t.id===r||t.id===l)?.vacuum||null,k={id:r,vacuum:f,...y,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?t.angle:null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===e&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:u.length?u:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),...this._markerValueSourceFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Mt(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};p&&(k.space=_,k.area=m,k.room_id=g);const x=h?.marker?.room_id??null,M=t.roomTouched&&null!=h&&(h.space!==_||h.area!==m||x!==g);let C=!1;const S=t.uploadId||l;if(S&&S!==r&&k.pdfs?.length)try{const t=await this.host.hass.callWS({type:"houseplan/files/migrate",from_id:S,to_id:r}),e=t?.mapping||{};k.pdfs=ai(k.pdfs,S,r,e),C=Object.keys(e).length>0}catch(t){this.host._showToast(this.host._t("toast.files_migrate_failed",{err:this.host._errText(t)}))}a.markers=n,l&&l!==r&&(a.markers=ni(a.markers,l,r)),l&&l!==r&&"derived_marker_state"===k.value_badge?.source?.kind&&k.value_badge.source.ref===`marker:${l}`&&(k.value_badge.source={kind:"derived_marker_state",ref:`marker:${r}`}),l&&l!==r&&"derived_marker_state"===k.value_source?.kind&&k.value_source.ref===`marker:${l}`&&(k.value_source={kind:"derived_marker_state",ref:`marker:${r}`}),a.markers=a.markers.filter(t=>t.id!==r&&t.id!==l&&("virtual"===k.binding||t.binding!==k.binding)),a.markers.push(k);const P=new Set(c);l&&l!==r&&P.add(l),P.delete(r),P.size&&a.settings?.marker_area_snapshot&&(a.settings={...a.settings,marker_area_snapshot:ri(a.settings.marker_area_snapshot,P)});let I=null;const D=l?this.host._layout[l]:null,L=D?{s:D.s||h?.space||this.host._space,x:D.x,y:D.y}:l&&h&&this.host._defPos[l]?this.host._normPos(h.space,this.host._defPos[l].x,this.host._defPos[l].y):null;if(!d&&L&&L.s===v)r===l&&this.host._layout[r]&&!M||(I={s:L.s,x:L.x,y:L.y});else if(d||!this.host._layout[r]||M){let t=b.vb[0]+b.vb[2]/2,e=b.vb[1]+b.vb[3]/2;const s=g?b.rooms.find(t=>t.id===g):m?b.rooms.find(t=>t.area===m):void 0;s&&([t,e]=this.host._roomCenter(s)),I=this.host._normPos(v,t,e)}if(this.host._serverCfg!==s||this.host._cfgRev!==i||xt(s)!==o)return this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,busy:!1}),void this.host._showToast(this.host._t("toast.conflict"));if(a=this._prepareConfigCandidate(a),w=this.host._adoption.beginOptimistic(s,a),this.host._serverCfg=a,this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate(),this.host._saveConfigDebounced.pending()&&this.host._saveConfigDebounced.cancel(),await this._saveConfigNow(w),$=!0,I){const t=li(I);this.host._layout={...this.host._layout,[r]:t},this.host._noteLayoutRev(await this.host.hass.callWS({type:"houseplan/layout/update",device_id:r,pos:t}))}const T=new Set(c);l&&l!==r&&T.add(l),T.delete(r);for(const t of T)delete this.host._layout[t],await this.host.hass.callWS({type:"houseplan/layout/delete",device_id:t}).then(t=>this.host._noteLayoutRev(t)).catch(()=>{});C&&S&&await this.host.hass.callWS({type:"houseplan/files/cleanup",marker_id:S}).catch(()=>{}),wa(this.host),this._closeMarkerDialog(),this.host._cancelDeviceDrag(),this.host._devicePositionHistory.clear(),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("toast.marker_saved"))}catch(t){!$&&w&&(this.host._rollbackOptimistic(w),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate()),this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}async _deleteMarker(){const t=this.host._markerDialog;if(!t||t.busy||!t.devId)return;const e=t.devId?this.host._devices.find(e=>e.id===t.devId):null,s=this.host._markers.find(e=>e.id===t.devId);if(!e&&!s)return;const i=e?"virtual"===e.bindingKind?"virtual":e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:"":s.binding;if(!i)return;const o=t.name||this.host._t("device.fallback"),a=t.devId,n=await this.host._confirmDanger({key:"remove-marker",kind:"destructive",title:this.host._t("confirm.remove_marker_title"),message:this.host._t("confirm.remove_marker_body"),objectName:o,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),r=this.host._markerDialog;if(!n||!r||r.busy||r.devId!==a)return;const l=this.host._devices.find(t=>t.id===a),h=this.host._markers.find(t=>t.id===a);if(!l&&!h)return;const c=this.host._serverCfg;if(!c)return;c.markers=c.markers||[];const d=c.markers,p=l?"virtual"===l.bindingKind?"virtual":l.bindingKind&&l.bindingRef?`${l.bindingKind}:${l.bindingRef}`:"":h.binding;if(!p||p!==i)return;const u=hi(c.markers,a,p,"virtual"===p);c.markers=ci(u.markers,u.cleanupIds);const _=u.cleanupIds;_.size&&c.settings?.marker_area_snapshot&&(c.settings={...c.settings,marker_area_snapshot:ri(c.settings.marker_area_snapshot,_)}),this.host._markerDialog={...r,busy:!0};try{await this._saveConfigNow();for(const t of _){delete this.host._layout[t],delete this.host._defPos[t],this.host._dirtyPos.delete(t),this.host._sentPos.delete(t);const e=this.host._activityRt.get(t);e&&clearTimeout(e.timer),this.host._activityRt.delete(t),this.host._vacRt.delete(t),delete this.host._vacSrvTrails[t],await this.host.hass.callWS({type:"houseplan/layout/delete",device_id:t}).then(t=>this.host._noteLayoutRev(t)).catch(()=>{}),await this.host.hass.callWS({type:"houseplan/files/cleanup",marker_id:t}).catch(()=>{}),await this.host.hass.callWS({type:"houseplan/trail/delete",marker_id:t}).catch(()=>{})}this.host._deviceInboxReturn&&(this.host._deviceInboxReturn={...this.host._deviceInboxReturn,tab:"readd",anchor:p}),this._closeMarkerDialog(),this.host._cancelDeviceDrag(),this.host._devicePositionHistory.clear(),this.host._infoCard?.id===a&&this.host._closeInfoCard(),this.host._selId===a&&(this.host._selId=null),this.host._drag?.id===a&&(this.host._drag=null),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("toast.marker_removed"))}catch(t){this.host._serverCfg===c&&(c.markers=d),this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}_openSpaceDialog(t,e){if(this.host._serverStorage&&this.host._serverCfg){if("edit"===t){const s=this.host._serverCfg.spaces.find(t=>t.id===e);if(!s)return;const i=b(s),o=s.settings?.custom_fill&&"object"==typeof s.settings.custom_fill?di(s.settings.custom_fill):null,a="none"===i.fill?{...o||pi,a:0}:o;this.host._spaceDialog={mode:t,spaceId:e,title:s.title,planUrl:s.plan_url||null,planFile:null,source:s.plan_url?"file":"draw",showBorders:i.showBorders,showNames:i.showNames,zeroWallStyle:_i(s),displayTouched:!0,hideDecor:i.hideDecor,hideOpenings:i.hideOpenings,roomColor:i.color,roomOpacity:i.opacity,fillMode:"none"===i.fill?"custom":i.fill,customFill:a,glowEnabled:i.glow,bgColor:i.bgColor,bgMode:"static"===s.settings?.bg_mode||"daynight"===s.settings?.bg_mode?s.settings.bg_mode:null,northDeg:Ee({},s.settings),northDegInput:null===Ee({},s.settings)?"":String(Ee({},s.settings)),sunRays:"boolean"==typeof s.settings?.sun_rays?s.settings.sun_rays:null,tempMin:i.tempMin,tempMax:i.tempMax,tempMinInput:String(i.tempMin),tempMaxInput:String(i.tempMax),showLqi:i.showLqi??this.host._config?.show_signal??!0,cardFontScale:i.cardFontScale,labelTemp:i.labelTemp,labelHum:i.labelHum,labelLqi:i.labelLqi,labelLight:i.labelLight,cellCm:Number(s.cell_cm)>0?Number(s.cell_cm):5,cellCmInput:ui(Number(s.cell_cm)>0?Number(s.cell_cm):5,this.host._imperial),cellCmTouched:!1,busy:!1}}else this.host._spaceDialog={mode:t,title:"",planUrl:null,planFile:null,...yi(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:bi,roomOpacity:fi,fillMode:"custom",customFill:{...pi,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,northDegInput:"",sunRays:null,tempMin:gi,tempMax:mi,tempMinInput:String(gi),tempMaxInput:String(mi),showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:vi(this.host._imperial),cellCmInput:ui(vi(this.host._imperial),this.host._imperial),cellCmTouched:!1,busy:!1};this.host._spaceDialog&&qo(this.host,this.host._spaceDialog)}else this.host._showToast(this.host._t("toast.integration_missing"))}async _pickPlanFile(t){const e=t.target,s=e.files?.[0];if(!s||!this.host._spaceDialog)return;e.value="",this._decorAssetGuardReplace=null;const i=await Uo(this.host,s);i&&this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:i})}_renderBackdropGuard(){const t=this._decorAssetGuardReplace;return null!==t?Ko(this.host,()=>{},()=>{this.host._backdropGuard=null,this._decorAssetGuardReplace=null},this.host.hass,(e,s)=>this._uploadDecorImage(e,s,t),(this.host._backdropGuard?.file.size||0)<=2097152)??d:Vo(this.host,t=>{this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:t})},()=>{this.host._backdropGuard=null},this.host.hass)??d}_useServerPlan(t){const e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this.host._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let e=0;e<40;e++){const e=this.host._display(t);if(e){const s=await new Promise(t=>{const s=new Image;s.onload=()=>t(s.naturalWidth&&s.naturalHeight?s.naturalWidth/s.naturalHeight:0),s.onerror=()=>t(0),s.src=e}),i=this.host._spaceDialog;return i&&i.planUrl===t&&Number.isFinite(s)&&s>0?(this.host._spaceDialog={...i,savedAspect:s},s):0}if(await new Promise(t=>setTimeout(t,150)),this.host._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){const e=this.host._spaceDialog,s=e?.saved?.find(e=>e.name===t);if(!e||!s||s.used_by.length||s.url===e.planUrl)return;const i=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")}),o=this.host._spaceDialog,a=o?.saved?.find(e=>e.name===t);if(i&&o&&a&&a.url===s.url&&a.modified===s.modified&&!a.used_by.length&&a.url!==o.planUrl)try{await this.host.hass.callWS({type:"houseplan/plans/delete",name:t});const e=this.host._spaceDialog;e?.saved&&(this.host._spaceDialog={...e,saved:e.saved.filter(e=>e.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 p`<div class="savedplans muted">${this.host._t("space.loading")}</div>`;const e=t.saved||[];if(!e.length)return p`<div class="savedplans muted">${this.host._t("space.no_saved")}</div>`;return p`<div class="savedplans">
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
${e.map(e=>{return p`
|
||
<div class="savedplan ${e.url===t.planUrl?"cur":""}">
|
||
<img src=${this.host._display(e.url)} alt="" loading="lazy" decoding="async" />
|
||
<div class="savedmeta">
|
||
<b>${e.name}</b>
|
||
<span class="muted">${i=e.size,i>=1048576?(i/1048576).toFixed(1)+" MB":Math.round(i/1024)+" KB"}${e.used_by.length?" · "+this.host._t("space.used_by",{list:e.used_by.join(", ")}):""}</span>
|
||
</div>
|
||
<button class="btn ghost" @click=${()=>this._useServerPlan(e.url)}
|
||
?disabled=${e.url===t.planUrl}>${this.host._t("btn.use")}</button>
|
||
<button class="btn ghost danger"
|
||
title=${e.used_by.length||e.url===t.planUrl?this.host._t("space.in_use"):this.host._t("btn.delete")}
|
||
?disabled=${e.used_by.length>0||e.url===t.planUrl}
|
||
@click=${()=>this._deleteServerPlan(e.name)}>
|
||
<ha-icon icon="mdi:trash-can-outline"></ha-icon>
|
||
</button>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</div>`;var i})}
|
||
</div>`}async _saveSpaceDialog(){const t=this.host._spaceDialog;if(!t||t.busy||!t.title.trim())return;if(Zo(t,"space-dialog",this.host._imperial).length)return;if("file"===t.source&&!t.planFile&&!t.planUrl)return void this.host._showToast(this.host._t("toast.plan_required"));const e="create"===t.mode&&0===(this.host._serverCfg?.spaces.length||0);this.host._spaceDialog={...t,busy:!0};try{const i="create"===t.mode?"s"+Date.now().toString(36):t.spaceId;let s=null;if("file"===t.source&&t.planFile){s={url:(await this.host.hass.callWS({type:"houseplan/plan/set",space_id:i,ext:t.planFile.ext,data:t.planFile.b64})).url,aspect:t.planFile.aspect}}let o=t.savedAspect||null;!s&&"file"===t.source&&t.planUrl&&!o&&this.host._aspectJob&&(o=await this.host._aspectJob||null);const a=this.host._serverCfg;let n;if("create"===t.mode)n=ks(i,t.title.trim()),a.spaces.push(n);else{if(n=a.spaces.find(t=>t.id===i),!n)throw new Error("space "+i+" is gone from the config");n.title=t.title.trim()}s?(n.plan_url=s.url,n.plan_aspect=s.aspect):"file"===t.source&&t.planUrl&&t.planUrl!==n.plan_url&&(n.plan_url=t.planUrl,n.plan_aspect=o),"draw"===t.source&&(n.plan_url=null,n.plan_aspect=null,delete n.plan_x,delete n.plan_y,delete n.plan_scale,delete n.plan_scale_x,delete n.plan_scale_y,delete n.plan_angle),n.settings={...n.settings||{},show_borders:t.showBorders,show_names:t.showNames,hide_decor:t.hideDecor||void 0,hide_openings:t.hideOpenings||void 0,room_color:t.roomColor,room_opacity:t.roomOpacity,bg_color:t.bgColor||void 0,bg_mode:t.bgMode||void 0,north_deg:t.northDeg??void 0,sun_rays:t.sunRays??void 0,fill_mode:t.fillMode,custom_fill:t.customFill||void 0,glow_enabled:t.glowEnabled,temp_min:Number.isFinite(t.tempMin)?Math.min(t.tempMin,t.tempMax):bs,temp_max:Number.isFinite(t.tempMax)?Math.max(t.tempMin,t.tempMax):fs,show_lqi:t.showLqi,card_font_scale:1!==t.cardFontScale?t.cardFontScale:void 0,label_temp:t.labelTemp,label_hum:t.labelHum,label_lqi:t.labelLqi,label_light:t.labelLight},n.zero_wall_style=t.zeroWallStyle,n.cell_cm=Number.isFinite(t.cellCm)&&t.cellCm>0?Math.max(Xo,Math.min(Qo,t.cellCm)):5,await this._saveConfigNow(),this.host._spaceDialog=null,"create"===t.mode&&this.host._commitSpace(n.id),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._importQueue.length?this._openNextImport():e||this.host._importTotal>0?(this.host._importTotal=0,this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||this.host._space),this._setMode("plan"),this.host._tool="draw",this.host._path=[],this.host._cursorPt=null,this._primeDrawWallField(),this.host._showToast(this.host._t(e&&!this.host._importTotal?"toast.space_added_onboard":"import.done"))):(this.host._showToast("create"===t.mode?this.host._t("toast.space_added"):this.host._t("toast.space_saved")),"create"===t.mode&&("plan"!==this.host._mode?this._setMode("plan"):(this.host._tool="draw",this.host._path=[],this.host._cursorPt=null,this._primeDrawWallField(),this.host._saveNav())))}catch(t){"conflict"!==t?.code&&await this.host._reloadConfigOnly(!0),this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}async _deleteSpace(){const t=this.host._spaceDialog;if(!t||"edit"!==t.mode)return;const e=this.host._serverCfg;if(!e)return;const i=e.spaces.find(e=>e.id===t.spaceId),s=ta(e,this.host._layout||{},t.spaceId||""),o=1===e.spaces.length&&e.spaces[0]?.id===t.spaceId;if(s.count&&!o)return void(this.host._spaceDialog={...t,deleteBlockers:s.count});if(!i)return;const a=t.spaceId,n=await this.host._confirmDanger({key:"delete-space",kind:"destructive",title:this.host._t("confirm.delete_space_title"),message:ea(this.host._t("confirm.delete_space_body"),this.host._t("confirm.delete_space_vac_routes"),s.routeCount),objectName:i.title,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),r=this.host._spaceDialog,l=this.host._serverCfg;if(!n||!r||"edit"!==r.mode||r.busy||r.spaceId!==a||!l)return;if(!l.spaces.find(t=>t.id===a))return;const h=ta(l,this.host._layout||{},a),c=1===l.spaces.length&&l.spaces[0]?.id===a;if(!h.count||c){this.host._spaceDialog={...r,deleteBlockers:0,busy:!0};try{this.host._saveConfigDebounced.pending()&&this.host._saveConfigDebounced.flush(),this.host._persistLayout.pending()&&this.host._persistLayout.flush(),await this.host._writeChain,await this.host.hass.callWS({type:"houseplan/space/delete",space_id:a,expected_config_rev:this.host._cfgRev,expected_layout_rev:this.host._layoutRev});const[t,e]=await Promise.all([this.host._getAuthoritativeConfig(),this.host.hass.callWS({type:"houseplan/layout/get"})]);if("adopted"!==(await this.host._adoptAuthoritative({cfgResp:t,layResp:e,reason:"space-delete",profile:"post-write"})).status)return this.host._spaceDialog={...r,busy:!1},void this.host.requestUpdate();this.host._spaceDialog=null,this.host._space===a&&this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||""),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("toast.space_deleted"))}catch(t){"conflict"!==t?.code&&"space_in_use"!==t?.code||await Promise.all([this.host._reloadConfigOnly(!0),this.host._reloadLayoutOnly()]);const e=this.host._serverCfg;if(this.host._spaceDialog&&e){const t=ta(e,this.host._layout||{},a),i=1===e.spaces.length&&e.spaces[0]?.id===a;this.host._spaceDialog={...this.host._spaceDialog,busy:!1,deleteBlockers:i?0:t.count}}this.host._showToast(this.host._t("toast.delete_failed",{err:this.host._errText(t)}))}}else this.host._spaceDialog={...r,deleteBlockers:h.count}}async _saveConfigNow(t=null){this.host._cfgEpoch++;try{await this._writeConfig(t)}catch(t){throw t?.physicalGeometryRolledBack?await this._reloadRejectedPhysicalWrite():"conflict"===t?.code&&await this.host._reloadConfigOnly(),t}}_saveSpaceCopy(){return Cr(this.host,{clearGeometryGesture:()=>this._clearGeometryGesture(),optimizeReferenceContext:()=>this._optimizeReferenceContext(!1),reportPreflightFailure:(t,e)=>this.optimizePlans.reportPreflightFailure(t,e),saveConfigNow:t=>this._saveConfigNow(t),setMode:()=>this._setMode("plan"),showWallModelMigrationBlocked:t=>this._showWallModelMigrationBlocked(t)})}_startImport(){const t=this.host._importDialog;if(!t)return;const e=t.floors.filter(t=>t.checked).map(t=>t.name);this.host._importDialog=null,e.length?(this.host._importQueue=e,this.host._importTotal=e.length,this._openNextImport()):this._openSpaceDialog("create")}_openNextImport(){const t=this.host._importQueue.shift();void 0!==t&&(this.host._spaceDialog={mode:"create",title:t,planUrl:null,planFile:null,...$s(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:ys,roomOpacity:vs,fillMode:"custom",customFill:null,glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,northDegInput:"",sunRays:null,tempMin:bs,tempMax:fs,tempMinInput:String(bs),tempMaxInput:String(fs),showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:ws(this.host._imperial),cellCmInput:ms(ws(this.host._imperial),this.host._imperial),cellCmTouched:!1,busy:!1})}_skipImport(){this.host._spaceDialog=null,this.host._importQueue.length?this._openNextImport():this.host._importTotal>0&&this.host._model.length&&(this.host._importTotal=0,this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||this.host._space),this._setMode("plan"),this.host._showToast(this.host._t("import.done")))}_renderImportDialog(){const t=this.host._importDialog,e=t.floors.filter(t=>t.checked).length;return p`<hp-dialog .hass=${this.host.hass} data-kind="import" .title=${this.host._t("import.title")} icon="mdi:home-floor-1"
|
||
========
|
||
</div>`;var s})}
|
||
</div>`}async _saveSpaceDialog(){const t=this.host._spaceDialog;if(!t||t.busy||!t.title.trim())return;if(Jo(t,"space-dialog",this.host._imperial).length)return;if("file"===t.source&&!t.planFile&&!t.planUrl)return void this.host._showToast(this.host._t("toast.plan_required"));const e="create"===t.mode&&0===(this.host._serverCfg?.spaces.length||0);this.host._spaceDialog={...t,busy:!0};try{const s="create"===t.mode?"s"+Date.now().toString(36):t.spaceId;let i=null;if("file"===t.source&&t.planFile){const e=await Zo(this.host.hass,(t,e)=>this.host._t(t,e),s,t.planFile);i={url:e.url,aspect:t.planFile.aspect}}let o=t.savedAspect||null;!i&&"file"===t.source&&t.planUrl&&!o&&this.host._aspectJob&&(o=await this.host._aspectJob||null);const a=this.host._serverCfg;let n;if("create"===t.mode)n=wi(s,t.title.trim()),a.spaces.push(n);else{if(n=a.spaces.find(t=>t.id===s),!n)throw new Error("space "+s+" is gone from the config");n.title=t.title.trim()}i?(n.plan_url=i.url,n.plan_aspect=i.aspect):"file"===t.source&&t.planUrl&&t.planUrl!==n.plan_url&&(n.plan_url=t.planUrl,n.plan_aspect=o),"draw"===t.source&&(n.plan_url=null,n.plan_aspect=null,delete n.plan_x,delete n.plan_y,delete n.plan_scale,delete n.plan_scale_x,delete n.plan_scale_y,delete n.plan_angle),n.settings={...n.settings||{},show_borders:t.showBorders,show_names:t.showNames,hide_decor:t.hideDecor||void 0,hide_openings:t.hideOpenings||void 0,room_color:t.roomColor,room_opacity:t.roomOpacity,bg_color:t.bgColor||void 0,bg_mode:t.bgMode||void 0,north_deg:t.northDeg??void 0,sun_rays:t.sunRays??void 0,fill_mode:t.fillMode,custom_fill:t.customFill||void 0,glow_enabled:t.glowEnabled,temp_min:Number.isFinite(t.tempMin)?Math.min(t.tempMin,t.tempMax):gi,temp_max:Number.isFinite(t.tempMax)?Math.max(t.tempMin,t.tempMax):mi,show_lqi:t.showLqi,card_font_scale:1!==t.cardFontScale?t.cardFontScale:void 0,label_temp:t.labelTemp,label_hum:t.labelHum,label_lqi:t.labelLqi,label_light:t.labelLight},n.zero_wall_style=t.zeroWallStyle,n.cell_cm=Number.isFinite(t.cellCm)&&t.cellCm>0?Math.max(Yo,Math.min(Xo,t.cellCm)):5,await this._saveConfigNow(),this.host._spaceDialog=null,"create"===t.mode&&this.host._commitSpace(n.id),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._importQueue.length?this._openNextImport():e||this.host._importTotal>0?(this.host._importTotal=0,this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||this.host._space),this._setMode("plan"),this.host._tool="draw",this.host._path=[],this.host._cursorPt=null,this._primeDrawWallField(),this.host._showToast(this.host._t(e&&!this.host._importTotal?"toast.space_added_onboard":"import.done"))):(this.host._showToast("create"===t.mode?this.host._t("toast.space_added"):this.host._t("toast.space_saved")),"create"===t.mode&&("plan"!==this.host._mode?this._setMode("plan"):(this.host._tool="draw",this.host._path=[],this.host._cursorPt=null,this._primeDrawWallField(),this.host._saveNav())))}catch(t){"conflict"!==t?.code&&await this.host._reloadConfigOnly(!0),this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}async _deleteSpace(){const t=this.host._spaceDialog;if(!t||"edit"!==t.mode)return;const e=this.host._serverCfg;if(!e)return;const s=e.spaces.find(e=>e.id===t.spaceId),i=Qo(e,this.host._layout||{},t.spaceId||""),o=1===e.spaces.length&&e.spaces[0]?.id===t.spaceId;if(i.count&&!o)return void(this.host._spaceDialog={...t,deleteBlockers:i.count});if(!s)return;const a=t.spaceId,n=await this.host._confirmDanger({key:"delete-space",kind:"destructive",title:this.host._t("confirm.delete_space_title"),message:ta(this.host._t("confirm.delete_space_body"),this.host._t("confirm.delete_space_vac_routes"),i.routeCount),objectName:s.title,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),r=this.host._spaceDialog,l=this.host._serverCfg;if(!n||!r||"edit"!==r.mode||r.busy||r.spaceId!==a||!l)return;if(!l.spaces.find(t=>t.id===a))return;const h=Qo(l,this.host._layout||{},a),c=1===l.spaces.length&&l.spaces[0]?.id===a;if(!h.count||c){this.host._spaceDialog={...r,deleteBlockers:0,busy:!0};try{this.host._saveConfigDebounced.pending()&&this.host._saveConfigDebounced.flush(),this.host._persistLayout.pending()&&this.host._persistLayout.flush(),await this.host._writeChain,await this.host.hass.callWS({type:"houseplan/space/delete",space_id:a,expected_config_rev:this.host._cfgRev,expected_layout_rev:this.host._layoutRev});const[t,e]=await Promise.all([this.host._getAuthoritativeConfig(),this.host.hass.callWS({type:"houseplan/layout/get"})]);if("adopted"!==(await this.host._adoptAuthoritative({cfgResp:t,layResp:e,reason:"space-delete",profile:"post-write"})).status)return this.host._spaceDialog={...r,busy:!1},void this.host.requestUpdate();this.host._spaceDialog=null,this.host._space===a&&this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||""),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("toast.space_deleted"))}catch(t){"conflict"!==t?.code&&"space_in_use"!==t?.code||await Promise.all([this.host._reloadConfigOnly(!0),this.host._reloadLayoutOnly()]);const e=this.host._serverCfg;if(this.host._spaceDialog&&e){const t=Qo(e,this.host._layout||{},a),s=1===e.spaces.length&&e.spaces[0]?.id===a;this.host._spaceDialog={...this.host._spaceDialog,busy:!1,deleteBlockers:s?0:t.count}}this.host._showToast(this.host._t("toast.delete_failed",{err:this.host._errText(t)}))}}else this.host._spaceDialog={...r,deleteBlockers:h.count}}async _saveConfigNow(t=null){this.host._cfgEpoch++;try{await this._writeConfig(t)}catch(t){throw t?.physicalGeometryRolledBack?await this._reloadRejectedPhysicalWrite():"conflict"===t?.code&&await this.host._reloadConfigOnly(),t}}_saveSpaceCopy(){return kr(this.host,{clearGeometryGesture:()=>this._clearGeometryGesture(),optimizeReferenceContext:()=>this._optimizeReferenceContext(!1),reportPreflightFailure:(t,e)=>this._reportPreflightFailure(t,e),saveConfigNow:t=>this._saveConfigNow(t),setMode:()=>this._setMode("plan"),showWallModelMigrationBlocked:t=>this._showWallModelMigrationBlocked(t)})}_startImport(){const t=this.host._importDialog;if(!t)return;const e=t.floors.filter(t=>t.checked).map(t=>t.name);this.host._importDialog=null,e.length?(this.host._importQueue=e,this.host._importTotal=e.length,this._openNextImport()):this._openSpaceDialog("create")}_openNextImport(){const t=this.host._importQueue.shift();void 0!==t&&(this.host._spaceDialog={mode:"create",title:t,planUrl:null,planFile:null,...yi(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:bi,roomOpacity:fi,fillMode:"custom",customFill:null,glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,northDegInput:"",sunRays:null,tempMin:gi,tempMax:mi,tempMinInput:String(gi),tempMaxInput:String(mi),showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:vi(this.host._imperial),cellCmInput:ui(vi(this.host._imperial),this.host._imperial),cellCmTouched:!1,busy:!1})}_skipImport(){this.host._spaceDialog=null,this.host._importQueue.length?this._openNextImport():this.host._importTotal>0&&this.host._model.length&&(this.host._importTotal=0,this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||this.host._space),this._setMode("plan"),this.host._showToast(this.host._t("import.done")))}_renderImportDialog(){const t=this.host._importDialog,e=t.floors.filter(t=>t.checked).length;return p`<hp-dialog .hass=${this.host.hass} data-kind="import" .title=${this.host._t("import.title")} icon="mdi:home-floor-1"
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
@hp-close=${()=>this.host._importDialog=null}>
|
||
<div class="body">
|
||
<div class="rhint">${this.host._t("import.hint")}</div>
|
||
${t.floors.map((e,i)=>p`<label class="floorrow">
|
||
<input type="checkbox" .checked=${e.checked}
|
||
@change=${s=>{const o=[...t.floors];o[i]={...e,checked:s.target.checked},this.host._importDialog={floors:o}}} />
|
||
<span>${e.name}</span>
|
||
${null!=e.level?p`<span class="floorlvl">L${e.level}</span>`:d}
|
||
</label>`)}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<button class="btn ghost" @click=${()=>{this.host._importDialog=null,this._openSpaceDialog("create")}}>
|
||
${this.host._t("import.manual")}
|
||
</button>
|
||
<span class="spacer"></span>
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>this._startImport()} ?disabled=${!e}>
|
||
<ha-icon icon="mdi:import"></ha-icon>${this.host._t("import.start",{n:e})}
|
||
</button>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}_supportPatch(t,e){const i=this.host._supportDialog;if(!i||i.draftId!==t)return null;const s={...i,...e};return this.host._supportDialog=s,s}async _focusSupport(t){await this.host.updateComplete,this.host.renderRoot.querySelector(t)?.focus({preventScroll:!0})}_updateSupportDraft(t,e){const i=this.host._supportDialog;if(!i||"building"===i.status||"sending"===i.status||"success"===i.status)return;const s={...i,[t]:e},o=xd({...s,attach:!1,preview:null});"message_required"===o&&"validation.message_required"===i.errorCode||"message_too_long"===o||"contact_too_long"===o?this._supportPatch(i.draftId,{[t]:e,status:"error",errorCode:`validation.${o}`}):s.attach&&s.preview&&s.preview.expiresAt<=Date.now()?this._supportPatch(i.draftId,{[t]:e,status:"error",errorCode:"support_preview_expired"}):this._supportPatch(i.draftId,{[t]:e,status:s.attach&&s.preview?"ready":"idle",errorCode:""})}async _discardSupportPreview(t){if(t)try{await this.host.hass.callWS({type:"houseplan/support/preview/discard",token:t})}catch{}}async _closeSupportDialog(){const t=this.host._supportDialog;if(t){if("building"===t.status||"sending"===t.status){const t=l(this.host.hass,this.host._config?.language);if(!await this.host._confirmDanger({key:"close-support-busy",kind:"warning",title:_a(t,"support.close_busy_title"),message:_a(t,"support.close_busy_body"),confirmLabel:this.host._t("btn.close"),cancelLabel:this.host._t("btn.cancel")}))return await this.host.updateComplete,void this.host.renderRoot.querySelector("#support-dialog")?.rejectClose()}clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this.host._supportDialog=null,t.preview?.token&&"success"!==t.status&&this._discardSupportPreview(t.preview.token)}}_scheduleSupportExpiry(t,e){clearTimeout(this._supportExpiryTimer);const i=Math.max(0,e.expiresAt-Date.now());this._supportExpiryTimer=window.setTimeout(()=>{const i=this.host._supportDialog;i&&i.draftId===t&&i.preview?.token===e.token&&i.attach&&"success"!==i.status&&"sending"!==i.status&&this._supportPatch(t,{status:"error",errorCode:"support_preview_expired"})},Math.min(i+20,2147483647))}_supportFacts(){const t=this.host._haRegistry;return Cd({userAgent:globalThis.navigator?.userAgent||"",language:l(this.host.hass,this.host._config?.language),registryAccess:t.access,registryLastSuccess:t.lastSuccess})}_supportPreviewRequestIsCurrent(t,e){const i=this.host._supportDialog;return e===this._supportPreviewGeneration&&i?.draftId===t&&i.attach}async _buildSupportPreview(t){const e=this.host._supportDialog;if(!e||e.draftId!==t||!e.attach||!yd(this.host._haSupportApi))return;const i=++this._supportPreviewGeneration;this._supportPatch(t,{status:"building",errorCode:""});let s="";try{const e=await this.host.hass.callWS({type:"houseplan/support/preview",card_version:We(Yd),...this._supportFacts(),draft_id:t}),o=e&&"object"==typeof e?e:{},a=Date.now(),n="string"==typeof o.text?o.text:"",r=Number(o.size),l=Number(o.expires_in),h=Number(o.spaces),c=String(o.token||"");/^[0-9a-f]{48}$/.test(c)&&(s=c);const d=String(o.sha256||""),p=Number(o.version),u=String(o.format||""),_=(new TextEncoder).encode(n).byteLength;if(!/^[0-9a-f]{48}$/.test(c)||!/^[0-9a-f]{64}$/.test(d)||"houseplan-support-package"!==u||1!==p||!Number.isInteger(r)||r!==_||!Number.isInteger(h)||h<0||!Number.isFinite(l)||l<=0||l>600||!n.endsWith("\n"))throw{code:"support_rejected"};const m={token:c,expiresAt:a+1e3*l,size:r,sha256:d,spaces:h,format:u,version:p,text:n,preparedAt:a};if(!this._supportPreviewRequestIsCurrent(t,i))return s="",void this._discardSupportPreview(c);if(!this._supportPatch(t,{status:"ready",preview:m,errorCode:"",rawOpen:!1}))return s="",void this._discardSupportPreview(c);s="",this._scheduleSupportExpiry(t,m)}catch(e){if(s){const t=s;s="",this._discardSupportPreview(t)}if(!this._supportPreviewRequestIsCurrent(t,i))return;if(!this._supportPatch(t,{status:"error",errorCode:Sd(e)}))return;this._focusSupport("#support-error")}}async _setSupportAttachment(t){const e=this.host._supportDialog;if(!e||"sending"===e.status||"success"===e.status)return;const i=e.preview?.token||"";if(!t)return this._supportPreviewGeneration+=1,clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this._supportPatch(e.draftId,{attach:!1,status:"idle",preview:null,rawOpen:!1,errorCode:""}),void(i&&this._discardSupportPreview(i));this._supportPatch(e.draftId,{attach:!0,errorCode:""}),await this._buildSupportPreview(e.draftId)}async _refreshSupportPreview(){const t=this.host._supportDialog;t&&t.attach&&"building"!==t.status&&"sending"!==t.status&&await this._buildSupportPreview(t.draftId)}_downloadSupportPreview(){const t=this.host._supportDialog?.preview;if(!t)return;const e=new Blob([t.text],{type:"application/json;charset=utf-8"}),i=URL.createObjectURL(e),s=document.createElement("a");s.href=i,s.download=`houseplan-support-${t.sha256.slice(0,12)}.json`,s.style.display="none",document.body.append(s),s.click(),s.remove(),window.setTimeout(()=>URL.revokeObjectURL(i),0)}async _copySupportText(t,e){const i=l(this.host.hass,this.host._config?.language);try{await navigator.clipboard.writeText(t),this.host._showToast(_a(i,e))}catch{this.host._showToast(_a(i,"support.copy_failed"))}}async _submitSupport(){const t=this.host._supportDialog;if(!t||!yd(this.host._haSupportApi))return;const e=xd(t);if(e)return this._supportPatch(t.draftId,{status:"error",errorCode:`validation.${e}`}),void this._focusSupport("#support-message");if(!Md(t))return;const i=$d(t),s=this._supportPatch(t.draftId,{status:"sending",errorCode:"",idempotencyKey:i.idempotencyKey,submissionFingerprint:i.fingerprint});if(s)try{const e=await this.host.hass.callWS({type:"houseplan/support/submit",message:s.message.trim(),contact:s.contact.trim(),...s.attach&&s.preview?{preview_token:s.preview.token}:{},idempotency_key:s.idempotencyKey}),i=e&&"object"==typeof e&&"report_id"in e?String(e.report_id||""):"";if(!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(i))throw{code:"support_unavailable"};if(clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,!this._supportPatch(t.draftId,{status:"success",reportId:i,errorCode:""}))return;this._focusSupport("#support-receipt")}catch(e){if(!this._supportPatch(t.draftId,{status:"error",errorCode:Sd(e)}))return;this._focusSupport("#support-error")}}_supportErrorText(t){const e=l(this.host.hass,this.host._config?.language);if(t.errorCode.startsWith("validation.")){return _a(e,`support.validation.${t.errorCode.slice(11)}`)}return _a(e,`support.error.${t.errorCode||"support_unavailable"}`)}_supportMessageKeydown(t){"Enter"===t.key&&(t.ctrlKey||t.metaKey)&&(t.preventDefault(),this._submitSupport())}_renderSupportDialog(){const t=this.host._supportDialog,e=l(this.host.hass,this.host._config?.language),i="ru"===e?"https://github.com/Matysh/houseplan-card/blob/main/docs/USER-GUIDE.ru.md":"https://github.com/Matysh/houseplan-card/blob/main/docs/USER-GUIDE.md",s=yd(this.host._haSupportApi),o=(t,i)=>_a(e,t,i),a="building"===t.status||"sending"===t.status,n=xd(t),r=t.preview?Math.max(0,Math.floor((Date.now()-t.preview.preparedAt)/6e4)):0,h="error"===t.status&&!t.errorCode.startsWith("validation."),c="validation.contact_too_long"===t.errorCode,u="validation.message_required"===t.errorCode||"validation.message_too_long"===t.errorCode;return p`<hp-dialog id="support-dialog" .hass=${this.host.hass} data-kind="support"
|
||
========
|
||
</hp-dialog>`}_supportPatch(t,e){const s=this.host._supportDialog;if(!s||s.draftId!==t)return null;const i={...s,...e};return this.host._supportDialog=i,i}async _focusSupport(t){await this.host.updateComplete,this.host.renderRoot.querySelector(t)?.focus({preventScroll:!0})}_updateSupportDraft(t,e){const s=this.host._supportDialog;if(!s||"building"===s.status||"sending"===s.status||"success"===s.status)return;const i={...s,[t]:e},o=vd({...i,attach:!1,preview:null});"message_required"===o&&"validation.message_required"===s.errorCode||"message_too_long"===o||"contact_too_long"===o?this._supportPatch(s.draftId,{[t]:e,status:"error",errorCode:`validation.${o}`}):i.attach&&i.preview&&i.preview.expiresAt<=Date.now()?this._supportPatch(s.draftId,{[t]:e,status:"error",errorCode:"support_preview_expired"}):this._supportPatch(s.draftId,{[t]:e,status:i.attach&&i.preview?"ready":"idle",errorCode:""})}async _discardSupportPreview(t){if(t)try{await this.host.hass.callWS({type:"houseplan/support/preview/discard",token:t})}catch{}}async _closeSupportDialog(){const t=this.host._supportDialog;if(t){if("building"===t.status||"sending"===t.status){const t=l(this.host.hass,this.host._config?.language);if(!await this.host._confirmDanger({key:"close-support-busy",kind:"warning",title:da(t,"support.close_busy_title"),message:da(t,"support.close_busy_body"),confirmLabel:this.host._t("btn.close"),cancelLabel:this.host._t("btn.cancel")}))return await this.host.updateComplete,void this.host.renderRoot.querySelector("#support-dialog")?.rejectClose()}clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this.host._supportDialog=null,t.preview?.token&&"success"!==t.status&&this._discardSupportPreview(t.preview.token)}}_scheduleSupportExpiry(t,e){clearTimeout(this._supportExpiryTimer);const s=Math.max(0,e.expiresAt-Date.now());this._supportExpiryTimer=window.setTimeout(()=>{const s=this.host._supportDialog;s&&s.draftId===t&&s.preview?.token===e.token&&s.attach&&"success"!==s.status&&"sending"!==s.status&&this._supportPatch(t,{status:"error",errorCode:"support_preview_expired"})},Math.min(s+20,2147483647))}_supportFacts(){const t=this.host._haRegistry;return wd({userAgent:globalThis.navigator?.userAgent||"",language:l(this.host.hass,this.host._config?.language),registryAccess:t.access,registryLastSuccess:t.lastSuccess})}_supportPreviewRequestIsCurrent(t,e){const s=this.host._supportDialog;return e===this._supportPreviewGeneration&&s?.draftId===t&&s.attach}async _buildSupportPreview(t){const e=this.host._supportDialog;if(!e||e.draftId!==t||!e.attach||!md(this.host._haSupportApi))return;const s=++this._supportPreviewGeneration;this._supportPatch(t,{status:"building",errorCode:""});let i="";try{const e=await this.host.hass.callWS({type:"houseplan/support/preview",card_version:$i(qd),...this._supportFacts(),draft_id:t}),o=e&&"object"==typeof e?e:{},a=Date.now(),n="string"==typeof o.text?o.text:"",r=Number(o.size),l=Number(o.expires_in),h=Number(o.spaces),c=String(o.token||"");/^[0-9a-f]{48}$/.test(c)&&(i=c);const d=String(o.sha256||""),p=Number(o.version),u=String(o.format||""),_=(new TextEncoder).encode(n).byteLength;if(!/^[0-9a-f]{48}$/.test(c)||!/^[0-9a-f]{64}$/.test(d)||"houseplan-support-package"!==u||1!==p||!Number.isInteger(r)||r!==_||!Number.isInteger(h)||h<0||!Number.isFinite(l)||l<=0||l>600||!n.endsWith("\n"))throw{code:"support_rejected"};const m={token:c,expiresAt:a+1e3*l,size:r,sha256:d,spaces:h,format:u,version:p,text:n,preparedAt:a};if(!this._supportPreviewRequestIsCurrent(t,s))return i="",void this._discardSupportPreview(c);if(!this._supportPatch(t,{status:"ready",preview:m,errorCode:"",rawOpen:!1}))return i="",void this._discardSupportPreview(c);i="",this._scheduleSupportExpiry(t,m)}catch(e){if(i){const t=i;i="",this._discardSupportPreview(t)}if(!this._supportPreviewRequestIsCurrent(t,s))return;if(!this._supportPatch(t,{status:"error",errorCode:$d(e)}))return;this._focusSupport("#support-error")}}async _setSupportAttachment(t){const e=this.host._supportDialog;if(!e||"sending"===e.status||"success"===e.status)return;const s=e.preview?.token||"";if(!t)return this._supportPreviewGeneration+=1,clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this._supportPatch(e.draftId,{attach:!1,status:"idle",preview:null,rawOpen:!1,errorCode:""}),void(s&&this._discardSupportPreview(s));this._supportPatch(e.draftId,{attach:!0,errorCode:""}),await this._buildSupportPreview(e.draftId)}async _refreshSupportPreview(){const t=this.host._supportDialog;t&&t.attach&&"building"!==t.status&&"sending"!==t.status&&await this._buildSupportPreview(t.draftId)}_downloadSupportPreview(){const t=this.host._supportDialog?.preview;if(!t)return;const e=new Blob([t.text],{type:"application/json;charset=utf-8"}),s=URL.createObjectURL(e),i=document.createElement("a");i.href=s,i.download=`houseplan-support-${t.sha256.slice(0,12)}.json`,i.style.display="none",document.body.append(i),i.click(),i.remove(),window.setTimeout(()=>URL.revokeObjectURL(s),0)}async _copySupportText(t,e){const s=l(this.host.hass,this.host._config?.language);try{await navigator.clipboard.writeText(t),this.host._showToast(da(s,e))}catch{this.host._showToast(da(s,"support.copy_failed"))}}async _submitSupport(){const t=this.host._supportDialog;if(!t||!md(this.host._haSupportApi))return;const e=vd(t);if(e)return this._supportPatch(t.draftId,{status:"error",errorCode:`validation.${e}`}),void this._focusSupport("#support-message");if(!yd(t))return;const s=fd(t),i=this._supportPatch(t.draftId,{status:"sending",errorCode:"",idempotencyKey:s.idempotencyKey,submissionFingerprint:s.fingerprint});if(i)try{const e=await this.host.hass.callWS({type:"houseplan/support/submit",message:i.message.trim(),contact:i.contact.trim(),...i.attach&&i.preview?{preview_token:i.preview.token}:{},idempotency_key:i.idempotencyKey}),s=e&&"object"==typeof e&&"report_id"in e?String(e.report_id||""):"";if(!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(s))throw{code:"support_unavailable"};if(clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,!this._supportPatch(t.draftId,{status:"success",reportId:s,errorCode:""}))return;this._focusSupport("#support-receipt")}catch(e){if(!this._supportPatch(t.draftId,{status:"error",errorCode:$d(e)}))return;this._focusSupport("#support-error")}}_supportErrorText(t){const e=l(this.host.hass,this.host._config?.language);if(t.errorCode.startsWith("validation.")){return da(e,`support.validation.${t.errorCode.slice(11)}`)}return da(e,`support.error.${t.errorCode||"support_unavailable"}`)}_supportMessageKeydown(t){"Enter"===t.key&&(t.ctrlKey||t.metaKey)&&(t.preventDefault(),this._submitSupport())}_renderSupportDialog(){const t=this.host._supportDialog,e=l(this.host.hass,this.host._config?.language),s="ru"===e?"https://github.com/Matysh/houseplan-card/blob/main/docs/USER-GUIDE.ru.md":"https://github.com/Matysh/houseplan-card/blob/main/docs/USER-GUIDE.md",i=md(this.host._haSupportApi),o=(t,s)=>da(e,t,s),a="building"===t.status||"sending"===t.status,n=vd(t),r=t.preview?Math.max(0,Math.floor((Date.now()-t.preview.preparedAt)/6e4)):0,h="error"===t.status&&!t.errorCode.startsWith("validation."),c="validation.contact_too_long"===t.errorCode,u="validation.message_required"===t.errorCode||"validation.message_too_long"===t.errorCode;return p`<hp-dialog id="support-dialog" .hass=${this.host.hass} data-kind="support"
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
.title=${this.host._t("support.title")} icon="mdi:help-circle-outline" wide dismiss-on-scrim
|
||
@hp-close=${()=>{this._closeSupportDialog()}}>
|
||
<div class="body supportbody">
|
||
<section class="supportsection" aria-labelledby="support-about-heading">
|
||
<h3 id="support-about-heading">${o("support.about_group")}</h3>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
<div class="aboutver">${this.host._t("gs.about_version",{v:We(Yd)})}</div>
|
||
========
|
||
<div class="aboutver">${this.host._t("gs.about_version",{v:$i(qd)})}</div>
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<div class="supportlinks">
|
||
<a class="aboutlink" href="https://github.com/Matysh/houseplan-card" target="_blank" rel="noopener noreferrer">
|
||
<ha-icon icon="mdi:github"></ha-icon>${this.host._t("gs.about_github")}</a>
|
||
<a class="aboutlink" href="https://t.me/ha_houseplan" target="_blank" rel="noopener noreferrer">
|
||
<ha-icon icon="mdi:send"></ha-icon>${this.host._t("gs.about_telegram")}</a>
|
||
</div>
|
||
</section>
|
||
<section class="supportsection" aria-labelledby="support-docs-heading">
|
||
<h3 id="support-docs-heading">${o("support.guide_group")}</h3>
|
||
<a class="aboutlink" href=${i} target="_blank" rel="noopener noreferrer">
|
||
<ha-icon icon="mdi:book-open-page-variant-outline"></ha-icon>${o("support.guide")}</a>
|
||
</section>
|
||
${s?p`
|
||
<section class="supportsection supportform" aria-labelledby="support-form-heading">
|
||
<h3 id="support-form-heading">${o("support.form_group")}</h3>
|
||
<label for="support-contact">${o("support.contact")}</label>
|
||
<input id="support-contact" class="namein" type="text" autocomplete="off"
|
||
aria-invalid=${c?"true":"false"}
|
||
aria-describedby=${c?"support-error":d}
|
||
.value=${t.contact} ?disabled=${a||"success"===t.status}
|
||
@input=${t=>this._updateSupportDraft("contact",t.target.value)} />
|
||
<label for="support-message">${o("support.message")}</label>
|
||
<textarea id="support-message" class="supportmessage" required
|
||
aria-invalid=${u?"true":"false"}
|
||
aria-describedby=${u?"support-error":d}
|
||
.value=${t.message} ?disabled=${a||"success"===t.status}
|
||
@keydown=${t=>this._supportMessageKeydown(t)}
|
||
@input=${t=>this._updateSupportDraft("message",t.target.value)}></textarea>
|
||
<label class="srcrow supportattach">
|
||
<input type="checkbox" .checked=${t.attach} aria-describedby="support-attach-hint"
|
||
?disabled=${a||"success"===t.status}
|
||
@change=${t=>{this._setSupportAttachment(t.target.checked)}} />
|
||
<span>${o("support.attach")}</span>
|
||
</label>
|
||
<p id="support-attach-hint" class="rhint">${o("support.attach_hint")}</p>
|
||
${t.attach?p`<p class="supportwarning" role="note">
|
||
<ha-icon icon="mdi:shield-alert-outline"></ha-icon>
|
||
<span>${o("support.geometry_warning")}</span>
|
||
</p>`:d}
|
||
${"building"===t.status?p`<div class="supportstatus" role="status" aria-live="polite">
|
||
<ha-icon icon="mdi:progress-clock"></ha-icon>${o("support.building")}
|
||
</div>`:d}
|
||
${t.attach&&t.preview?p`
|
||
<div class="supportpreview">
|
||
<div class="supportsummary">${o("support.preview_summary",{version:t.preview.version,spaces:t.preview.spaces,size:(_=t.preview.size,(Math.max(0,_)/1024).toFixed(_<10240?1:0))})}</div>
|
||
<div class="supporthash"><span>SHA-256</span><code>${t.preview.sha256}</code></div>
|
||
<div class="rhint">${o("support.prepared",{n:r})}</div>
|
||
<details ?open=${t.rawOpen}
|
||
@toggle=${e=>this._supportPatch(t.draftId,{rawOpen:e.currentTarget.open})}>
|
||
<summary>${o("support.show_data")}</summary>
|
||
${t.rawOpen?p`<textarea class="supportraw" readonly
|
||
.value=${t.preview.text}></textarea>`:d}
|
||
</details>
|
||
<div class="supportactions">
|
||
<button type="button" class="btn ghost" @click=${()=>this._downloadSupportPreview()}>
|
||
<ha-icon icon="mdi:download"></ha-icon>${o("support.download")}
|
||
</button>
|
||
<button type="button" class="btn ghost" @click=${()=>{this._refreshSupportPreview()}}
|
||
?disabled=${a||"success"===t.status}>
|
||
<ha-icon icon="mdi:refresh"></ha-icon>${o("support.refresh")}
|
||
</button>
|
||
</div>
|
||
</div>`:d}
|
||
<p class="rhint supportprivacy">${o("support.privacy")}</p>
|
||
${"error"===t.status?p`
|
||
<div id="support-error" class="supporterror" role="alert" tabindex="-1">
|
||
<strong>${o("support.error_title")}</strong>
|
||
<span>${this._supportErrorText(t)}</span>
|
||
</div>`:d}
|
||
${"error"===t.status&&t.attach&&!t.preview?p`
|
||
<div class="supportactions">
|
||
<button type="button" class="btn ghost"
|
||
@click=${()=>{this._refreshSupportPreview()}}>
|
||
<ha-icon icon="mdi:refresh"></ha-icon>${o("support.refresh")}
|
||
</button>
|
||
</div>`:d}
|
||
${h?p`
|
||
<div class="supportmanual">
|
||
<strong>${o("support.manual_recovery")}</strong>
|
||
<div class="supportactions">
|
||
<button type="button" class="btn ghost" @click=${()=>{this._copySupportText(t.message,"support.message_copied")}}>${o("support.copy_message")}</button>
|
||
${t.preview?p`<button type="button" class="btn ghost"
|
||
@click=${()=>this._downloadSupportPreview()}>${o("support.download")}</button>`:d}
|
||
<a class="aboutlink" href="https://t.me/ha_houseplan" target="_blank" rel="noopener noreferrer">Telegram</a>
|
||
<a class="aboutlink" href="https://github.com/Matysh/houseplan-card/issues" target="_blank" rel="noopener noreferrer">GitHub</a>
|
||
</div>
|
||
</div>`:d}
|
||
${"success"===t.status?p`
|
||
<div id="support-receipt" class="supportsuccess" role="status" aria-live="polite" tabindex="-1">
|
||
<strong>${o("support.success",{id:t.reportId})}</strong>
|
||
<button type="button" class="btn ghost" @click=${()=>{this._copySupportText(t.reportId,"support.id_copied")}}>${o("support.copy_id")}</button>
|
||
</div>`:d}
|
||
</section>`:p`
|
||
<div class="supportupdate" role="status">
|
||
<ha-icon icon="mdi:update"></ha-icon>
|
||
<span>${o("support.update_required")}</span>
|
||
</div>`}
|
||
</div>
|
||
<div class="row supportfooter" slot="footer">
|
||
<button type="button" class="btn ghost" data-hp="dialog-cancel" @click=${()=>{this._closeSupportDialog()}}>
|
||
${this.host._t("btn.close")}
|
||
</button>
|
||
<span class="spacer"></span>
|
||
${s&&"success"!==t.status?p`
|
||
<button type="button" class="btn on" data-hp="dialog-confirm" @click=${()=>{this._submitSupport()}}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
?disabled=${!Md(t)}>
|
||
<ha-icon icon="mdi:send"></ha-icon>${"sending"===t.status?o("support.sending"):"error"!==t.status||n?o("support.send"):o("support.retry")}
|
||
</button>`:d}
|
||
</div>
|
||
</hp-dialog>`;var _}_checkOptimizeGeometryImpl(t){return xs(t,{fallbackSpaceName:t=>this.host._t("gs.align_preflight_space",{n:String(t)})})}_checkSpacePhysicalGeometryImpl(t,e,i){return Ms(t,e,{fallbackSpaceName:t=>this.host._t("gs.align_preflight_space",{n:String(t)}),captureWallGeometry:i?(t,e)=>i(e):void 0})}_optimizeReferenceContext(t){const e=this.host._haRegistry,i=this.host._fullRegistryHass,s={},o=(...t)=>{for(const e of t){const t=String(e||"").trim();if(t)return t}return""};for(const[t,i]of Object.entries(e.devices||{}))s[t]=o(i?.name_by_user,i?.name,i?.model);for(const[t,i]of Object.entries(e.entities||{}))s[`lg_${t}`]=o(this.host.hass?.states?.[t]?.attributes?.friendly_name,i?.name,i?.original_name);for(const t of this.host._devices)s[t.id]=o(t.name,s[t.id]);for(const t of this.host._serverCfg?.markers||[]){const e=String(t.binding||"").indexOf(":"),a=e>0?t.binding.slice(0,e):"",n=e>0?t.binding.slice(e+1):"",r="device"===a?i?.devices?.[n]:"entity"===a?i?.entities?.[n]:null;s[t.id]=o(t.name,"device"===a?r?.name_by_user:null,r?.name,"entity"===a?this.host.hass?.states?.[n]?.attributes?.friendly_name:null,s[t.id])}return{effectiveAreaByMarker:Object.fromEntries(this.host._devices.filter(t=>!t.virtual&&!!t.area).map(t=>[t.id,t.area])),ownerRoster:{authoritative:e.authoritative,deviceIds:Object.keys(e.devices||{}),entityIds:[...new Set([...Object.keys(e.entities||{}),...Object.keys(this.host.hass?.states||{})])],names:s},removeLiveMissingPositions:t}}async _undoPlanOptimization(){if(!this.host._canOptimizeUndo||this.host._optimizeUndoBusy)return;const t=this.host._undoKind;this._clearGeometryGesture(),this.host._optimizeUndoBusy=!0,this.host.requestUpdate();try{await this.host.hass.callWS({type:"houseplan/plan/optimize_undo",expected_config_rev:this.host._cfgRev,expected_layout_rev:this.host._layoutRev});const[e,i]=await Promise.all([this.host._getAuthoritativeConfig(),this.host.hass.callWS({type:"houseplan/layout/get"})]);if("adopted"!==(await this.host._adoptAuthoritative({cfgResp:e,layResp:i,reason:"optimize-undo",profile:"post-write"})).status)return;this.host._geometryHistory.clear(),this.host._cancelDeviceDrag(),this.host._devicePositionHistory.clear(),this.host._canOptimizeUndo=!1,this.host._undoKind=null,this.host._cfgEpoch++,this.host._modelCache=null,this.host._frame=null,this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._cacheSnapshot(),this.host.requestUpdate(),this.host._showToast(this.host._t("import"===t?"backup.import_undone":"gs.optimize_undone"))}catch(t){this.host._canOptimizeUndo=!1,this.host._undoKind=null,this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}finally{this.host._optimizeUndoBusy=!1,this.host.requestUpdate()}}async _runBackupExport(){const t=this.host._backupExportDialog;if(t&&!t.busy){this.host._backupExportDialog={...t,busy:!0,error:""};try{const e=await this.host.hass.callWS({type:"houseplan/export/create",kind:t.kind,space_id:"space"===t.kind?this.host._space:void 0,..."space"===t.kind&&t.planOnly?{plan_only:!0}:{},card_version:We(Yd)}),i=new Blob([JSON.stringify(e.document,null,2)+"\n"],{type:"application/json;charset=utf-8"}),s=URL.createObjectURL(i),o=document.createElement("a");o.href=s,o.download=e.filename||`houseplan-${t.kind}.json`,o.style.display="none",document.body.append(o),o.click(),o.remove(),window.setTimeout(()=>URL.revokeObjectURL(s),0),this.host._backupExportDialog=null,this.host._showToast(this.host._t("backup.export_done"))}catch(t){this.host._backupExportDialog&&(this.host._backupExportDialog={...this.host._backupExportDialog,busy:!1,error:this._backupErrorText(t)})}}}async _pickBackupImport(t){const e=t.target,i=e.files?.[0];if(e.value="",i){this.host._settingsDialog=null,this.host._backupImportDialog={filename:i.name,size:i.size,token:"",preview:null,expectedConfigRev:this.host._cfgRev,expectedLayoutRev:this.host._layoutRev,duplicatePolicy:"skip",confirmMissing:!1,busy:!0,error:""};try{this.host._saveConfigDebounced.pending()&&this.host._saveConfigDebounced.flush(),await this.host._writeChain,this.host._persistLayout.pending()&&this.host._persistLayout.flush();const t="/api/houseplan/import/preview?duplicate_policy=skip",e={method:"POST",body:i,headers:{"content-type":"application/json"}},s=this.host.hass?.fetchWithAuth?await this.host.hass.fetchWithAuth(t,e):await fetch(t,{...e,headers:{...e.headers,...this.host.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.host.hass.auth.data.access_token}`}:{}}}),o=await s.json().catch(()=>({}));if(!s.ok||o.error)throw Object.assign(new Error(o.message||o.error||`HTTP ${s.status}`),{code:o.error});this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,token:o.token,preview:o.preview,expectedConfigRev:o.expected_config_rev,expectedLayoutRev:o.expected_layout_rev,busy:!1})}catch(t){this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,busy:!1,error:this._backupErrorText(t)})}}}async _setBackupDuplicatePolicy(t){const e=this.host._backupImportDialog;if(e&&!e.busy&&e.token&&t!==e.duplicatePolicy){this.host._backupImportDialog={...e,duplicatePolicy:t,busy:!0,error:""};try{const i=await this.host.hass.callWS({type:"houseplan/import/revalidate",token:e.token,duplicate_policy:t});this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,preview:{...e.preview,...i.preview},expectedConfigRev:i.expected_config_rev,expectedLayoutRev:i.expected_layout_rev,confirmMissing:!1,busy:!1})}catch(t){this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,duplicatePolicy:e.duplicatePolicy,preview:e.preview,confirmMissing:e.confirmMissing,busy:!1,error:this._backupErrorText(t)})}}}async _applyBackupImport(){const t=this.host._backupImportDialog;if(!t||t.busy||!t.token||!t.preview)return;if(t.preview.confirmation_required&&!t.confirmMissing)return;this.host._backupImportDialog={...t,busy:!0,error:""};const e=this.host._space;try{const i=await this.host.hass.callWS({type:"houseplan/import/apply",token:t.token,expected_config_rev:t.expectedConfigRev,expected_layout_rev:t.expectedLayoutRev,duplicate_policy:t.duplicatePolicy,confirm_missing_content:t.confirmMissing}),[s,o]=await Promise.all([this.host._getAuthoritativeConfig(),this.host.hass.callWS({type:"houseplan/layout/get"})]);if("adopted"!==(await this.host._adoptAuthoritative({cfgResp:s,layResp:o,reason:"import-apply",profile:"post-write"})).status)return this.host._backupImportDialog={...t,busy:!1,error:""},void this.host.requestUpdate();this.host._geometryHistory.clear(),this.host._dirtyPos.clear(),this.host._sentPos.clear(),this.host._defPos={},this.host._cfgEpoch++,this.host._modelCache=null,this.host._frame=null,this.host._visibleDeviceSnapshot=null,this.host._candidateDeviceSnapshot=null,this.host._stagedDeviceSnapshotToken=-1,this.host._capturedSnapshotConfigEpoch=-1,this.host._regSignature="",this.host._signer.invalidate(this.host.hass),this.host._resign(),this.host._maybeRebuildDevices();const a=this.host._serverCfg?.spaces||[],n="space"===i.kind&&i.space_id?i.space_id:a.some(t=>t.id===e)?e:a[0]?.id||this.host._space;this.host._hasFixedFloor?this.host._adoptInitialSpace(this.host._model,!0):this.host._commitSpace(n),this.host._backupImportDialog=null,this.host._cacheSnapshot(),this.host.requestUpdate();const r="space"===i.kind?t.preview.counts:i.counts;this.host._showToast(this.host._t("space"===i.kind?"backup.space_done":"backup.full_done",{spaces:String(r?.spaces||0),rooms:String(r?.rooms||0),markers:String(r?.markers||0),refs:String(i.repaired_target_refs||0)}))}catch(t){if("conflict"===t?.code&&this.host._backupImportDialog?.token)try{const t=this.host._backupImportDialog,e=await this.host.hass.callWS({type:"houseplan/import/revalidate",token:t.token,duplicate_policy:t.duplicatePolicy});return void(this.host._backupImportDialog={...t,preview:{...t.preview,...e.preview},expectedConfigRev:e.expected_config_rev,expectedLayoutRev:e.expected_layout_rev,confirmMissing:!1,busy:!1,error:this.host._t("backup.revalidated")})}catch(e){t=e}this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,busy:!1,error:this._backupErrorText(t)})}}_renderBackupExportDialog(){const t=this.host._backupExportDialog,e=(this.host._serverCfg?.spaces||[]).find(t=>t.id===this.host._space);return p`<hp-dialog .hass=${this.host.hass} data-kind="backup" .title=${this.host._t("backup.export_title")}
|
||
========
|
||
?disabled=${!yd(t)}>
|
||
<ha-icon icon="mdi:send"></ha-icon>${"sending"===t.status?o("support.sending"):"error"!==t.status||n?o("support.send"):o("support.retry")}
|
||
</button>`:d}
|
||
</div>
|
||
</hp-dialog>`;var _}_preflightDiagnostics(t,e){const s=new Map((e?.spaces||[]).map(t=>[String(t?.id||""),t]));return{kind:"houseplan-optimize-preflight",origin:"runtime",cardVersion:$i(qd),checkedAt:(new Date).toISOString(),preflightFingerprint:t.fingerprint,failures:t.failures.map(t=>({spaceId:t.spaceId,displayName:t.displayName,reason:t.reason,detail:t.detail??null,spaceGeometryFingerprint:s.has(t.spaceId)?ee(s.get(t.spaceId)):null}))}}_reportPreflightFailure(t,e){t.ok||t.fingerprint===this.host._reportedPreflightFingerprint||(this.host._reportedPreflightFingerprint=t.fingerprint,console.warn("[houseplan] optimize preflight failed",this._preflightDiagnostics(t,e)))}_preflightVersionsDiffer(){const t=this.host._haIntegrationVersion;return"string"==typeof t&&t.length>0&&t!==$i(qd)}async _copyPreflightDiagnostics(){const t=this.host._alignDialog?.preflight;if(!t||t.ok)return;const e=JSON.stringify(this._preflightDiagnostics(t,this.host._alignDialog?.config??null),null,2);try{await navigator.clipboard.writeText(e),this.host._preflightClipboardFallback=null,this.host._showToast(this.host._t("gs.preflight_copied"))}catch{this.host._preflightClipboardFallback=e}}_checkOptimizeGeometryImpl(t){return ki(t,{fallbackSpaceName:t=>this.host._t("gs.align_preflight_space",{n:String(t)})})}_checkSpacePhysicalGeometryImpl(t,e,s){return xi(t,e,{fallbackSpaceName:t=>this.host._t("gs.align_preflight_space",{n:String(t)}),captureWallGeometry:s?(t,e)=>s(e):void 0})}_optimizeReferenceContext(t){const e=this.host._haRegistry,s=this.host._fullRegistryHass,i={},o=(...t)=>{for(const e of t){const t=String(e||"").trim();if(t)return t}return""};for(const[t,s]of Object.entries(e.devices||{}))i[t]=o(s?.name_by_user,s?.name,s?.model);for(const[t,s]of Object.entries(e.entities||{}))i[`lg_${t}`]=o(this.host.hass?.states?.[t]?.attributes?.friendly_name,s?.name,s?.original_name);for(const t of this.host._devices)i[t.id]=o(t.name,i[t.id]);for(const t of this.host._serverCfg?.markers||[]){const e=String(t.binding||"").indexOf(":"),a=e>0?t.binding.slice(0,e):"",n=e>0?t.binding.slice(e+1):"",r="device"===a?s?.devices?.[n]:"entity"===a?s?.entities?.[n]:null;i[t.id]=o(t.name,"device"===a?r?.name_by_user:null,r?.name,"entity"===a?this.host.hass?.states?.[n]?.attributes?.friendly_name:null,i[t.id])}return{effectiveAreaByMarker:Object.fromEntries(this.host._devices.filter(t=>!t.virtual&&!!t.area).map(t=>[t.id,t.area])),ownerRoster:{authoritative:e.authoritative,deviceIds:Object.keys(e.devices||{}),entityIds:[...new Set([...Object.keys(e.entities||{}),...Object.keys(this.host.hass?.states||{})])],names:i},removeLiveMissingPositions:t}}_previewAlignDialog(t){if(!this.host._norm||!this.host._serverCfg)return;const e=this.host._serverCfg.spaces||[];let s;try{s=lr(this.host._serverCfg,this.host._layout||{},this._optimizeReferenceContext(t))}catch(t){return void this._showWallModelMigrationBlocked(t)}const i=s.changed?this.host._checkOptimizeGeometry(s.config):null;i&&this._reportPreflightFailure(i,s.config);const o=Math.ceil(10*s.report.maxShiftCm)/10,a=e.find(t=>null!=t?.id&&String(t.id)===s.report.maxSpace),n=e.length>1&&a?String(a.title||a.id):"";this.host._preflightClipboardFallback=null,this.host._alignDialog={report:s.report,config:s.config,layout:s.layout,cm:o,where:n,preflight:i,changed:s.changed,busy:!1,removeLiveMissingPositions:t}}async _runAlignToGrid(){let t=this.host._alignDialog;if(!t||t.busy||!this.host._serverCfg||!t.changed||!t.preflight?.ok)return;const e=xt(t.config);if(t.preflight.fingerprint!==e){const e=this.host._checkOptimizeGeometry(t.config);if(this._reportPreflightFailure(e,t.config),t={...t,preflight:e},this.host._alignDialog=t,!e.ok)return}this._clearGeometryGesture(),this.host._alignDialog={...t,busy:!0};try{await hr(this.host,t.config,t.layout),this.host._alignDialog=null,this.host._preflightClipboardFallback=null,this.host._showToast(this.host._t("gs.align_done",{n:String(t.report.moved),m:String(t.report.migrated+t.report.canonicalized+t.report.coordsCanonicalized+t.report.latticeCoordinatesCanonicalized+t.report.wallsMerged+t.report.spansMerged+t.report.partitionsMerged+t.report.partitionsReconciled+t.report.openingsRehosted+t.report.wallsStraightened),r:String(t.report.spaceRefsRemapped+t.report.roomRefsRemapped+t.report.positionsRemapped+t.report.markersDetached+t.report.orphanRoomLabelsRemoved+t.report.orphanDevicePositionsRemoved+t.report.orphanGroupPositionsRemoved)}))}catch(t){if(this.host._alignDialog&&(this.host._alignDialog={...this.host._alignDialog,busy:!1}),"wall_model_client_outdated"===t?.code)return void this.host._showToast(this.host._t("toast.wall_model_client_outdated"));"conflict"===t?.code&&await Promise.all([this.host._reloadConfigOnly(!0),this.host._reloadLayoutOnly()]),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}async _undoPlanOptimization(){if(!this.host._canOptimizeUndo||this.host._optimizeUndoBusy)return;const t=this.host._undoKind;this._clearGeometryGesture(),this.host._optimizeUndoBusy=!0,this.host.requestUpdate();try{await this.host.hass.callWS({type:"houseplan/plan/optimize_undo",expected_config_rev:this.host._cfgRev,expected_layout_rev:this.host._layoutRev});const[e,s]=await Promise.all([this.host._getAuthoritativeConfig(),this.host.hass.callWS({type:"houseplan/layout/get"})]);if("adopted"!==(await this.host._adoptAuthoritative({cfgResp:e,layResp:s,reason:"optimize-undo",profile:"post-write"})).status)return;this.host._geometryHistory.clear(),this.host._cancelDeviceDrag(),this.host._devicePositionHistory.clear(),this.host._canOptimizeUndo=!1,this.host._undoKind=null,this.host._cfgEpoch++,this.host._modelCache=null,this.host._frame=null,this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._cacheSnapshot(),this.host.requestUpdate(),this.host._showToast(this.host._t("import"===t?"backup.import_undone":"gs.optimize_undone"))}catch(t){this.host._canOptimizeUndo=!1,this.host._undoKind=null,this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}finally{this.host._optimizeUndoBusy=!1,this.host.requestUpdate()}}async _runBackupExport(){const t=this.host._backupExportDialog;if(t&&!t.busy){this.host._backupExportDialog={...t,busy:!0,error:""};try{const e=await this.host.hass.callWS({type:"houseplan/export/create",kind:t.kind,space_id:"space"===t.kind?this.host._space:void 0,..."space"===t.kind&&t.planOnly?{plan_only:!0}:{},card_version:$i(qd)}),s=new Blob([JSON.stringify(e.document,null,2)+"\n"],{type:"application/json;charset=utf-8"}),i=URL.createObjectURL(s),o=document.createElement("a");o.href=i,o.download=e.filename||`houseplan-${t.kind}.json`,o.style.display="none",document.body.append(o),o.click(),o.remove(),window.setTimeout(()=>URL.revokeObjectURL(i),0),this.host._backupExportDialog=null,this.host._showToast(this.host._t("backup.export_done"))}catch(t){this.host._backupExportDialog&&(this.host._backupExportDialog={...this.host._backupExportDialog,busy:!1,error:this._backupErrorText(t)})}}}async _pickBackupImport(t){const e=t.target,s=e.files?.[0];if(e.value="",s){this.host._settingsDialog=null,this.host._backupImportDialog={filename:s.name,size:s.size,token:"",preview:null,expectedConfigRev:this.host._cfgRev,expectedLayoutRev:this.host._layoutRev,duplicatePolicy:"skip",confirmMissing:!1,busy:!0,error:""};try{this.host._saveConfigDebounced.pending()&&this.host._saveConfigDebounced.flush(),await this.host._writeChain,this.host._persistLayout.pending()&&this.host._persistLayout.flush();const t="/api/houseplan/import/preview?duplicate_policy=skip",e={method:"POST",body:s,headers:{"content-type":"application/json"}},i=this.host.hass?.fetchWithAuth?await this.host.hass.fetchWithAuth(t,e):await fetch(t,{...e,headers:{...e.headers,...this.host.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.host.hass.auth.data.access_token}`}:{}}}),o=await i.json().catch(()=>({}));if(!i.ok||o.error)throw Object.assign(new Error(o.message||o.error||`HTTP ${i.status}`),{code:o.error});this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,token:o.token,preview:o.preview,expectedConfigRev:o.expected_config_rev,expectedLayoutRev:o.expected_layout_rev,busy:!1})}catch(t){this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,busy:!1,error:this._backupErrorText(t)})}}}async _setBackupDuplicatePolicy(t){const e=this.host._backupImportDialog;if(e&&!e.busy&&e.token&&t!==e.duplicatePolicy){this.host._backupImportDialog={...e,duplicatePolicy:t,busy:!0,error:""};try{const s=await this.host.hass.callWS({type:"houseplan/import/revalidate",token:e.token,duplicate_policy:t});this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,preview:{...e.preview,...s.preview},expectedConfigRev:s.expected_config_rev,expectedLayoutRev:s.expected_layout_rev,confirmMissing:!1,busy:!1})}catch(t){this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,duplicatePolicy:e.duplicatePolicy,preview:e.preview,confirmMissing:e.confirmMissing,busy:!1,error:this._backupErrorText(t)})}}}async _applyBackupImport(){const t=this.host._backupImportDialog;if(!t||t.busy||!t.token||!t.preview)return;if(t.preview.confirmation_required&&!t.confirmMissing)return;this.host._backupImportDialog={...t,busy:!0,error:""};const e=this.host._space;try{const s=await this.host.hass.callWS({type:"houseplan/import/apply",token:t.token,expected_config_rev:t.expectedConfigRev,expected_layout_rev:t.expectedLayoutRev,duplicate_policy:t.duplicatePolicy,confirm_missing_content:t.confirmMissing}),[i,o]=await Promise.all([this.host._getAuthoritativeConfig(),this.host.hass.callWS({type:"houseplan/layout/get"})]);if("adopted"!==(await this.host._adoptAuthoritative({cfgResp:i,layResp:o,reason:"import-apply",profile:"post-write"})).status)return this.host._backupImportDialog={...t,busy:!1,error:""},void this.host.requestUpdate();this.host._geometryHistory.clear(),this.host._dirtyPos.clear(),this.host._sentPos.clear(),this.host._defPos={},this.host._cfgEpoch++,this.host._modelCache=null,this.host._frame=null,this.host._visibleDeviceSnapshot=null,this.host._candidateDeviceSnapshot=null,this.host._stagedDeviceSnapshotToken=-1,this.host._capturedSnapshotConfigEpoch=-1,this.host._regSignature="",this.host._signer.invalidate(this.host.hass),this.host._resign(),this.host._maybeRebuildDevices();const a=this.host._serverCfg?.spaces||[],n="space"===s.kind&&s.space_id?s.space_id:a.some(t=>t.id===e)?e:a[0]?.id||this.host._space;this.host._hasFixedFloor?this.host._adoptInitialSpace(this.host._model,!0):this.host._commitSpace(n),this.host._backupImportDialog=null,this.host._cacheSnapshot(),this.host.requestUpdate();const r="space"===s.kind?t.preview.counts:s.counts;this.host._showToast(this.host._t("space"===s.kind?"backup.space_done":"backup.full_done",{spaces:String(r?.spaces||0),rooms:String(r?.rooms||0),markers:String(r?.markers||0),refs:String(s.repaired_target_refs||0)}))}catch(t){if("conflict"===t?.code&&this.host._backupImportDialog?.token)try{const t=this.host._backupImportDialog,e=await this.host.hass.callWS({type:"houseplan/import/revalidate",token:t.token,duplicate_policy:t.duplicatePolicy});return void(this.host._backupImportDialog={...t,preview:{...t.preview,...e.preview},expectedConfigRev:e.expected_config_rev,expectedLayoutRev:e.expected_layout_rev,confirmMissing:!1,busy:!1,error:this.host._t("backup.revalidated")})}catch(e){t=e}this.host._backupImportDialog&&(this.host._backupImportDialog={...this.host._backupImportDialog,busy:!1,error:this._backupErrorText(t)})}}_renderBackupExportDialog(){const t=this.host._backupExportDialog,e=(this.host._serverCfg?.spaces||[]).find(t=>t.id===this.host._space);return p`<hp-dialog .hass=${this.host.hass} data-kind="backup" .title=${this.host._t("backup.export_title")}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
icon="mdi:download" dismiss-on-scrim @hp-close=${()=>this.host._backupExportDialog=null}>
|
||
<div class="body backupbody">
|
||
<div class="rhint">${this.host._t("backup.export_hint")}</div>
|
||
<label class="srcrow"><input type="radio" name="backup-kind" value="full"
|
||
.checked=${"full"===t.kind}
|
||
@change=${()=>this.host._backupExportDialog={...t,kind:"full",planOnly:!1}} />
|
||
<span>${this.host._t("backup.full")}</span></label>
|
||
<label class="srcrow"><input type="radio" name="backup-kind" value="space"
|
||
.checked=${"space"===t.kind} ?disabled=${!e}
|
||
@change=${()=>this.host._backupExportDialog={...t,kind:"space"}} />
|
||
<span>${e?this.host._t("backup.current_space_title",{title:e.title||e.id}):this.host._t("backup.no_current_space")}</span></label>
|
||
${"space"===t.kind&&e?p`<label class="srcrow backupplanonly">
|
||
<input type="checkbox" .checked=${t.planOnly}
|
||
@change=${e=>this.host._backupExportDialog={...t,planOnly:e.target.checked}} />
|
||
<span><b>${this.host._t("backup.plan_only")}</b><small>${this.host._t("backup.plan_only_hint")}</small></span>
|
||
</label>`:d}
|
||
<div class="backupwarn">${this.host._t("backup.privacy_warning")}</div>
|
||
${t.error?p`<div class="backuperror" role="alert">${t.error}</div>`:d}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<button class="btn ghost" autofocus data-hp="dialog-cancel" @click=${()=>this.host._backupExportDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<span class="spacer"></span>
|
||
<button class="btn on" data-hp="dialog-confirm" ?disabled=${t.busy||"space"===t.kind&&!e}
|
||
@click=${()=>this._runBackupExport()}>
|
||
<ha-icon icon="mdi:download"></ha-icon>${t.busy?"…":this.host._t("backup.download")}
|
||
</button>
|
||
</div>
|
||
</hp-dialog>`}_renderBackupImportDialog(){const t=this.host._backupImportDialog,e=t.preview,i=(e?.content||[]).filter(t=>"decor_asset"===t.kind),s=new Set(i.map(t=>t.url)).size,o=i.filter(t=>"missing_preserved"===t.state),a=new Set(o.map(t=>t.url)).size,n=e?.counts||{},r=e?.migration||{},l=e?.reference_report||{},h=t=>Object.values(t||{}).reduce((t,e)=>t+(Number(e)||0),0),c=[["incoming_remapped",h(l.remapped?.incoming)],["target_repaired",h(l.remapped?.target)],["preserved_unresolved",h(l.preservedUnresolved)],["collisions",h(l.collisions)],["dropped_links",h(l.droppedIncomingLinks)],["bounded_lineages",Number(l.boundedLineages)||0]].filter(([,t])=>t>0);return p`<hp-dialog .hass=${this.host.hass} data-kind="backup" .title=${this.host._t("backup.import_title")}
|
||
icon="mdi:upload" wide dismiss-on-scrim @hp-close=${()=>this.host._backupImportDialog=null}>
|
||
<div class="body backupbody" aria-busy=${t.busy?"true":"false"}>
|
||
<div class="backupfile"><b>${t.filename}</b><span>${(t.size/1024).toFixed(1)} KB</span></div>
|
||
${t.busy&&!e?p`<div class="rhint" role="status" aria-live="polite">${this.host._t("backup.reading")}</div>`:d}
|
||
${t.error?p`<div class="backuperror" role="alert">${t.error}</div>`:d}
|
||
${e?p`
|
||
<div class="backupsummary">
|
||
<b>${this.host._t("full"===e.kind?"backup.full":"backup.current_space")}</b>
|
||
${e.plan_only?p`<span class="backupplanonlystatus">${this.host._t("backup.plan_only_preview")}</span>`:d}
|
||
<span>${this.host._t("same"===e.source?"backup.same_source":"backup.foreign_source")}</span>
|
||
<span>${this.host._t("backup.created",{value:e.created_at||"—"})}</span>
|
||
<span>${this.host._t("backup.versions",{card:e.card_version||"—",integration:e.integration_version||"—",model:String(e.model_version??"—")})}</span>
|
||
</div>
|
||
<div class="backupcounts">
|
||
<span>${this.host._t("backup.count_spaces",{n:"full"===e.kind?`${e.current_counts?.spaces||0} → ${n.spaces||0}`:String(n.spaces||0)})}</span>
|
||
<span>${this.host._t("backup.count_rooms",{n:"full"===e.kind?`${e.current_counts?.rooms||0} → ${n.rooms||0}`:String(n.rooms||0)})}</span>
|
||
<span>${this.host._t("backup.count_walls",{n:"full"===e.kind?`${e.current_counts?.walls||0} → ${n.walls||0}`:String(n.walls||0)})}</span>
|
||
<span>${this.host._t("backup.count_openings",{n:"full"===e.kind?`${e.current_counts?.openings||0} → ${n.openings||0}`:String(n.openings||0)})}</span>
|
||
<span>${this.host._t("backup.count_decor",{n:"full"===e.kind?`${e.current_counts?.decor||0} → ${n.decor||0}`:String(n.decor||0)})}</span>
|
||
<span>${this.host._t("backup.count_markers",{n:"full"===e.kind?`${e.current_counts?.markers||0} → ${n.markers||0}`:String(n.markers||0)})}</span>
|
||
<span>${this.host._t("backup.count_layout",{n:"full"===e.kind?`${e.current_counts?.layout||0} → ${n.layout||0}`:String(n.layout||0)})}</span>
|
||
</div>
|
||
${e.bindings?p`<div class="rhint">${this.host._t("backup.bindings",{device:String(e.bindings.device||0),entity:String(e.bindings.entity||0),virtual:String(e.bindings.virtual||0),legacy:String(e.legacy_positions||0)})}</div><div class="rhint">${this.host._t("backup.binding_status",{active:String(e.bindings.active||0),disabled:String(e.bindings.disabled||0),missing:String(e.bindings.missing||0)})}</div>`:d}
|
||
${e.missing_areas?.length?p`<div class="backupwarn">${this.host._t("backup.missing_areas",{areas:e.missing_areas.join(", ")})}</div>`:d}
|
||
${e.dropped_marker_links?p`<div class="backupwarn">${this.host._t("backup.dropped_marker_links",{n:String(e.dropped_marker_links)})}</div>`:d}
|
||
${r.room_drafts||r.room_draft_segments?p`
|
||
<div class="rhint">${this.host._t("backup.room_drafts_migrated",{drafts:String(r.room_drafts||0),segments:String(r.room_draft_segments||0)})}</div>`:d}
|
||
${e.repaired_target_refs?p`<div class="rhint">${this.host._t("backup.repaired_target_refs",{n:String(e.repaired_target_refs)})}</div>`:d}
|
||
${e.preserved_unresolved_refs?p`
|
||
<div class="backupwarn">${this.host._t("backup.preserved_unresolved_refs",{n:String(e.preserved_unresolved_refs)})}<br />${this.host._t("backup.preserved_unresolved_hint")}</div>
|
||
`:d}
|
||
${c.length?p`<details class="backupdetails">
|
||
<summary>${this.host._t("backup.import_details")}</summary>
|
||
<div>
|
||
${c.map(([t,e])=>p`<span>${this.host._t(`backup.import_detail.${t}`,{n:String(e)})}</span>`)}
|
||
${(l.examples||[]).slice(0,8).map(t=>p`
|
||
<code>${t.owner} → ${t.reference}</code>
|
||
`)}
|
||
</div>
|
||
</details>`:d}
|
||
${"full"===e.kind?p`
|
||
<div class="backupwarn">${this.host._t("backup.replace_warning")}</div>
|
||
${"foreign"===e.source?p`<div class="rhint">${this.host._t("backup.foreign_bookkeeping")}</div>`:d}`:p`
|
||
<div class="backupsummary"><b>${this.host._t("backup.final_name")}</b><span>${e.space_title}</span></div>
|
||
<div class="rhint">${this.host._t("backup.target_settings")}</div>
|
||
${e.duplicates?p`<fieldset class="backupchoices"><legend>${this.host._t("backup.duplicates",{n:String(e.duplicates)})}</legend>
|
||
<label><input type="radio" name="duplicate-policy" .checked=${"skip"===t.duplicatePolicy}
|
||
@change=${()=>this._setBackupDuplicatePolicy("skip")} />${this.host._t("backup.skip")}</label>
|
||
<label><input type="radio" name="duplicate-policy" .checked=${"virtual"===t.duplicatePolicy}
|
||
@change=${()=>this._setBackupDuplicatePolicy("virtual")} />${this.host._t("backup.virtual_copy")}</label>
|
||
</fieldset>`:d}`}
|
||
${e.content?.length?p`<div class="backupcontent">
|
||
<b>${this.host._t("backup.content")}</b>
|
||
${i.length?p`<span>${this.host._t("backup.decor_images_summary",{assets:s,objects:i.length,missing:a})}</span>`:d}
|
||
${e.content.filter(t=>"decor_asset"!==t.kind).map(t=>p`<span>${t.url} · ${this.host._t("available"===t.state?"backup.content_available":"external"===t.state?"backup.content_external":"backup.content_detach_required")}</span>`)}
|
||
</div>`:d}
|
||
${e.confirmation_required?p`<label class="srcrow backupconfirm">
|
||
<input type="checkbox" .checked=${t.confirmMissing}
|
||
@change=${e=>this.host._backupImportDialog={...t,confirmMissing:e.target.checked}} />
|
||
<span>${this.host._t(o.length?"backup.confirm_missing_images":"backup.confirm_detach")}</span>
|
||
</label>`:d}
|
||
`:d}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<button class="btn ghost" autofocus data-hp="dialog-cancel" @click=${()=>this.host._backupImportDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<span class="spacer"></span>
|
||
${e?p`<button class="btn ${"full"===e.kind?"danger":"on"}" data-hp="dialog-confirm"
|
||
?disabled=${t.busy||e.confirmation_required&&!t.confirmMissing} @click=${()=>this._applyBackupImport()}>
|
||
<ha-icon icon=${"full"===e.kind?"mdi:database-import":"mdi:plus"}></ha-icon>
|
||
${t.busy?"…":this.host._t("full"===e.kind?"backup.replace":"backup.add")}
|
||
</button>`:d}
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}_setFillColor(t,e){const i=this.host._settingsDialog;this.host._settingsDialog={...i,colors:{...i.colors,[t]:{...i.colors[t],...e}}}}_updateDecorStyle(t){this.host._decorStyle=t,null!==this._decorStylePersistTimer&&window.clearTimeout(this._decorStylePersistTimer),this._decorStylePersistTimer=window.setTimeout(()=>{this._decorStylePersistTimer=null,this._persistDecorStyle()},1e3)}_persistDecorStyle(){const t=this.host._serverCfg;if(!t)return;const e=Cs(this.host._decorStyle),i={...t.settings},s=JSON.stringify(i.decor_default_style??null);e?i.decor_default_style=e:delete i.decor_default_style,JSON.stringify(i.decor_default_style??null)!==s&&(this.host._serverCfg={...t,settings:i},this._saveConfig())}async _saveSettingsDialog(){const t=this.host._settingsDialog;if(!t||t.busy)return;if(Dr(t).length)return;this.host._settingsDialog={...t,busy:!0};let e=null;try{const i=this.host._serverCfg,s=JSON.stringify(t.colors)===JSON.stringify(Pt);let o={...i.settings};s?delete o.fill_colors:o.fill_colors=t.colors;const a=this.host._imperial?30.48*t.glowRadius:100*t.glowRadius;Number.isFinite(a)&&a>0&&300!==Math.round(a)?o.glow_radius_cm=Math.round(a):delete o.glow_radius_cm,t.bgColor?o.bg_color=t.bgColor:delete o.bg_color,null!==t.northDeg&&Number.isInteger(t.northDeg)&&t.northDeg>=0&&t.northDeg<=359?o.north_deg=t.northDeg:delete o.north_deg,o.bg_mode=t.bgMode,t.sunRays?o.sun_rays=!0:delete o.sun_rays,o.sun_ray_origin=t.sunRayOrigin,t.showRoomTooltip?delete o.show_room_tooltip:o.show_room_tooltip=!1;const n=o.radar;n&&null!=n.version&&1!==n.version||(o.radar={...n||{},version:1},t.radarShowLive?delete o.radar.show_live:o.radar.show_live=!1),o=Ss(o,t.zigbeeTopology),delete o.weather_entity;const r={...i,settings:o};e=this.host._adoption.beginOptimistic(i,r),this.host._serverCfg=r,await this._saveConfigNow(e),!t.showRoomTooltip&&this.host._tip?.room&&(this.host._tip=null),this.host._settingsDialog=null,this.host.requestUpdate(),this.host._showToast(this.host._t("gs.saved"))}catch(t){e&&this.host._rollbackOptimistic(e),this.host._settingsDialog&&(this.host._settingsDialog={...this.host._settingsDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}_boolInput(t,e,i=!1){const s=t=>e(!!t.target.checked);return customElements.get("ha-switch")?p`<ha-switch .checked=${t} .disabled=${i} @change=${s}></ha-switch>`:p`<input type="checkbox" .checked=${t} ?disabled=${i} @change=${s} />`}_rangeInput(t,e,i,s,o,a=!1,n){const r=t=>{const e=Number(t.target.value);Number.isFinite(e)&&o(e)};return customElements.get("ha-slider")?p`<ha-slider .min=${t} .max=${e} .step=${i} .value=${s}
|
||
.disabled=${a} aria-label=${n||d} @input=${r} @change=${r}></ha-slider>`:p`<input type="range" min=${t} max=${e} step=${i} .value=${String(s)}
|
||
?disabled=${a} aria-label=${n||d} @input=${r} />`}_renderSettingsDialog(){return Lr.call(this)}_rulesSet(t){this.host._rulesDialog={...this.host._rulesDialog,rules:t}}async _saveRules(){const t=this.host._rulesDialog;if(!t||t.busy)return;const e=t.rules.filter(t=>t.pattern.trim()&&t.icon.trim());this.host._rulesDialog={...t,busy:!0};try{const t=this.host._serverCfg,i=JSON.stringify(e)===JSON.stringify(He),s={...t.settings};i?delete s.icon_rules:s.icon_rules=e,this.host._serverCfg={...t,settings:s},await this._saveConfigNow(),this.host._rulesDialog=null,this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("rules.saved"))}catch(t){this.host._rulesDialog&&(this.host._rulesDialog={...this.host._rulesDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}_renderRulesDialog(){const t=this.host._rulesDialog,e=Ps(t.rules),i=t.test.trim()?Is(t.test,"",e):null,s=(e,i)=>{const s=[...t.rules],o=e+i;o<0||o>=s.length||([s[e],s[o]]=[s[o],s[e]],this._rulesSet(s))};return p`<hp-dialog .hass=${this.host.hass} data-kind="rules" .title=${this.host._t("rules.title")}
|
||
========
|
||
</hp-dialog>`}_setFillColor(t,e){const s=this.host._settingsDialog;this.host._settingsDialog={...s,colors:{...s.colors,[t]:{...s.colors[t],...e}}}}_updateDecorStyle(t){this.host._decorStyle=t,null!==this._decorStylePersistTimer&&window.clearTimeout(this._decorStylePersistTimer),this._decorStylePersistTimer=window.setTimeout(()=>{this._decorStylePersistTimer=null,this._persistDecorStyle()},1e3)}_persistDecorStyle(){const t=this.host._serverCfg;if(!t)return;const e=Mi(this.host._decorStyle),s={...t.settings},i=JSON.stringify(s.decor_default_style??null);e?s.decor_default_style=e:delete s.decor_default_style,JSON.stringify(s.decor_default_style??null)!==i&&(this.host._serverCfg={...t,settings:s},this._saveConfig())}async _saveSettingsDialog(){const t=this.host._settingsDialog;if(!t||t.busy)return;if(Sr(t).length)return;this.host._settingsDialog={...t,busy:!0};let e=null;try{const s=this.host._serverCfg,i=JSON.stringify(t.colors)===JSON.stringify(Pt);let o={...s.settings};i?delete o.fill_colors:o.fill_colors=t.colors;const a=this.host._imperial?30.48*t.glowRadius:100*t.glowRadius;Number.isFinite(a)&&a>0&&300!==Math.round(a)?o.glow_radius_cm=Math.round(a):delete o.glow_radius_cm,t.bgColor?o.bg_color=t.bgColor:delete o.bg_color,null!==t.northDeg&&Number.isInteger(t.northDeg)&&t.northDeg>=0&&t.northDeg<=359?o.north_deg=t.northDeg:delete o.north_deg,o.bg_mode=t.bgMode,t.sunRays?o.sun_rays=!0:delete o.sun_rays,o.sun_ray_origin=t.sunRayOrigin,t.showRoomTooltip?delete o.show_room_tooltip:o.show_room_tooltip=!1;const n=o.radar;n&&null!=n.version&&1!==n.version||(o.radar={...n||{},version:1},t.radarShowLive?delete o.radar.show_live:o.radar.show_live=!1),o=Ci(o,t.zigbeeTopology),delete o.weather_entity;const r={...s,settings:o};e=this.host._adoption.beginOptimistic(s,r),this.host._serverCfg=r,await this._saveConfigNow(e),!t.showRoomTooltip&&this.host._tip?.room&&(this.host._tip=null),this.host._settingsDialog=null,this.host.requestUpdate(),this.host._showToast(this.host._t("gs.saved"))}catch(t){e&&this.host._rollbackOptimistic(e),this.host._settingsDialog&&(this.host._settingsDialog={...this.host._settingsDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}_boolInput(t,e,s=!1){const i=t=>e(!!t.target.checked);return customElements.get("ha-switch")?p`<ha-switch .checked=${t} .disabled=${s} @change=${i}></ha-switch>`:p`<input type="checkbox" .checked=${t} ?disabled=${s} @change=${i} />`}_rangeInput(t,e,s,i,o,a=!1,n){const r=t=>{const e=Number(t.target.value);Number.isFinite(e)&&o(e)};return customElements.get("ha-slider")?p`<ha-slider .min=${t} .max=${e} .step=${s} .value=${i}
|
||
.disabled=${a} aria-label=${n||d} @input=${r} @change=${r}></ha-slider>`:p`<input type="range" min=${t} max=${e} step=${s} .value=${String(i)}
|
||
?disabled=${a} aria-label=${n||d} @input=${r} />`}_renderAlignDialog(){const t=this.host._alignDialog,e=t.report,s=t.changed&&!t.preflight?.ok,i=t.preflight?.failures||[],o=i.slice(0,3).map(t=>t.displayName),a=o.length?o.join(", "):this.host._t("gs.align_preflight_space",{n:"1"}),n=Math.max(0,i.length-o.length),r=n?this.host._t("gs.align_preflight_more",{n:String(n)}):"",l=e.spaceRefsRemapped+e.roomRefsRemapped+e.positionsRemapped+e.markersDetached,h=e.migrated+e.canonicalized+e.coordsCanonicalized+e.wallSegmentsMigrated+e.roomDraftsMigrated+e.roomDraftSegmentsMigrated+e.wallsMerged+e.spansMerged+e.partitionsMerged+e.partitionsReconciled+e.openingsRehosted,c=e.moved+e.rotated+e.coordsCanonicalized+e.wallsStraightened,u=Math.ceil(10*e.maxStraightenShiftCm)/10,_=(this.host._serverCfg?.spaces||[]).find(t=>String(t?.id||"")===e.maxStraightenSpace),m=(this.host._serverCfg?.spaces||[]).length>1&&_?String(_.title||_.id):"",g=e.orphanRoomLabelsRemoved+e.orphanDevicePositionsRemoved+e.orphanGroupPositionsRemoved,f=e.liveMissingPositions.map(t=>t.name).filter(Boolean),b=f.slice(0,3).join(", "),v=Math.max(0,f.length-3),y=b?this.host._t("gs.optimize_live_names",{names:b,more:v?this.host._t("gs.optimize_reference_more",{n:String(v)}):""}):"",w=e.unverifiedPositions.some(t=>"registry_unavailable"===t.reason),$=t=>e.removedPositions.some(e=>e.id===t.id)?this.host._t("gs.optimize_detail_removed"):e.liveMissingPositions.some(e=>e.id===t.id)?this.host._t("gs.optimize_detail_live"):this.host._t("gs.optimize_detail_unverified"),k=t=>this.host._t("room_label"===t?"gs.optimize_detail_room_label":"group"===t?"gs.optimize_detail_group":"device"===t?"gs.optimize_detail_device":"gs.optimize_detail_unknown"),x=[...e.removedPositions,...e.liveMissingPositions.filter(t=>!e.removedPositions.some(e=>e.id===t.id)),...e.unverifiedPositions],M=x.slice(0,10),C=Math.max(0,x.length-M.length);return p`<hp-dialog .hass=${this.host.hass} data-kind="settings" .title=${this.host._t("gs.align_title")} icon="mdi:broom"
|
||
dismiss-on-scrim @hp-close=${()=>{this.host._alignDialog=null,this.host._preflightClipboardFallback=null}}>
|
||
<div class="body">
|
||
${s?p`
|
||
<p class="alignmsg">${this.host._t("gs.align_preflight_failed",{spaces:a,more:r})}</p>
|
||
${i.slice(0,10).map(t=>p`<p class="alignmsg">
|
||
${t.displayName}: ${this.host._t(`gs.preflight_reason_${t.reason}`)}
|
||
</p>`)}
|
||
${i.length>10?p`<p class="alignmsg">
|
||
${this.host._t("gs.align_preflight_more",{n:String(i.length-10)})}
|
||
</p>`:d}
|
||
<div class="rhint">${this.host._t("gs.align_preflight_hint")}</div>
|
||
${this._preflightVersionsDiffer()?p`
|
||
<div class="rhint">${this.host._t("gs.preflight_update_hint")}</div>`:d}
|
||
<div class="row">
|
||
<button class="btn ghost" @click=${()=>this._copyPreflightDiagnostics()}>
|
||
<ha-icon icon="mdi:content-copy"></ha-icon>
|
||
${this.host._t("gs.preflight_copy")}
|
||
</button>
|
||
</div>
|
||
${this.host._preflightClipboardFallback?p`<details open>
|
||
<summary>${this.host._t("gs.preflight_copy")}</summary>
|
||
<pre style="user-select:text;white-space:pre-wrap">${this.host._preflightClipboardFallback}</pre>
|
||
</details>`:d}`:t.changed?p`
|
||
${e.moved?p`<p class="alignmsg">${this.host._t("gs.align_count",{n:String(e.moved),total:String(e.total),cm:String(t.cm)})}</p>`:d}
|
||
${e.latticeCoordinatesCanonicalized?p`
|
||
<p class="alignmsg">${this.host._t("gs.optimize_lattice_summary",{n:String(e.latticeCoordinatesCanonicalized),cm:Si(e.latticeMaxShiftCm)})}</p>
|
||
${e.latticeSpaces.map(t=>p`<p class="alignmsg">${this.host._t("gs.optimize_lattice_space",{space:t.space,n:String(t.canonicalized),far:String(t.far)})}</p>`)}
|
||
`:d}
|
||
${t.where?p`<p class="alignmsg">${this.host._t("gs.align_where",{s:t.where})}</p>`:d}
|
||
${e.rotated?p`<p class="alignmsg">${this.host._t("gs.align_turned",{n:String(e.rotated)})}</p>`:d}
|
||
${e.wallSegmentsMigrated?p`<p class="alignmsg">${this.host._t("gs.wall_segments_migrated",{n:String(e.wallSegmentsMigrated)})}</p>`:d}
|
||
${e.roomDraftsMigrated||e.roomDraftSegmentsMigrated?p`
|
||
<p class="alignmsg">${this.host._t("gs.room_drafts_migrated",{drafts:String(e.roomDraftsMigrated),segments:String(e.roomDraftSegmentsMigrated)})}</p>`:d}
|
||
${e.legacyZeroWallsMigrated?p`<p class="alignmsg">${this.host._t("gs.zero_walls_migrated",{n:String(e.legacyZeroWallsMigrated)})}</p>`:d}
|
||
${h?p`<p class="alignmsg">${this.host._t("gs.optimize_changes",{m:String(e.migrated),c:String(e.canonicalized),p:String(e.coordsCanonicalized),w:String(e.wallsMerged),s:String(e.spansMerged),i:String(e.partitionsMerged)})}</p>`:d}
|
||
${e.partitionsReconciled?p`<p class="alignmsg">${this.host._t("gs.optimize_coincident_partitions",{n:String(e.partitionsReconciled)})}</p>`:d}
|
||
${e.openingsRehosted?p`<p class="alignmsg">${this.host._t("gs.optimize_openings_rehosted",{n:String(e.openingsRehosted)})}</p>`:d}
|
||
${e.wallsStraightened?p`<p class="alignmsg">${this.host._t("gs.optimize_walls_straightened",{n:String(e.wallsStraightened),cm:String(u)})}</p>`:d}
|
||
${m?p`<p class="alignmsg">${this.host._t("gs.optimize_walls_straightened_where",{s:m})}</p>`:d}
|
||
${e.glowSpacesMigrated||e.glowRoomsMigrated?p`<p class="alignmsg">${this.host._t("gs.optimize_glow_migration",{spaces:String(e.glowSpacesMigrated),rooms:String(e.glowRoomsMigrated)})}</p>`:d}
|
||
${c?p`<div class="rhint">${this.host._t("gs.align_warn")}</div>`:d}`:p`<p class="alignmsg">${this.host._t(e.liveMissingPositions.length||e.unverifiedPositions.length||e.nestedRefsUnresolved?"gs.optimize_no_automatic_changes":"gs.align_none")}</p>`}
|
||
${!s&&e.wallsStraightenSkipped?p`<p class="rhint">${this.host._t("gs.optimize_walls_straighten_skipped",{n:String(e.wallsStraightenSkipped)})}</p>`:d}
|
||
${l?p`<p class="alignmsg">${this.host._t("gs.optimize_references",{spaces:String(e.spaceRefsRemapped),rooms:String(e.roomRefsRemapped),positions:String(e.positionsRemapped),detached:String(e.markersDetached)})}</p>`:d}
|
||
${g?p`<p class="alignmsg">${this.host._t("gs.optimize_orphans_removed",{total:String(g),rooms:String(e.orphanRoomLabelsRemoved),devices:String(e.orphanDevicePositionsRemoved),groups:String(e.orphanGroupPositionsRemoved)})}</p>`:d}
|
||
${e.liveMissingPositions.length?p`<div class="optimize-live">
|
||
<p class="alignmsg">${this.host._t(t.removeLiveMissingPositions?"gs.optimize_live_positions_remove":"gs.optimize_live_positions",{n:String(e.liveMissingPositions.length),names:y})}</p>
|
||
<button class="btn ghost optimize-cleanup" type="button"
|
||
aria-pressed=${t.removeLiveMissingPositions?"true":"false"}
|
||
@click=${()=>this._toggleOptimizeLivePositions()} ?disabled=${t.busy}>
|
||
<ha-icon icon=${t.removeLiveMissingPositions?"mdi:undo":"mdi:map-marker-remove-outline"}></ha-icon>
|
||
${this.host._t(t.removeLiveMissingPositions?"gs.optimize_live_keep":"gs.optimize_live_remove")}
|
||
</button>
|
||
${t.removeLiveMissingPositions?p`<div class="rhint optimize-selected" role="status">
|
||
${this.host._t("gs.optimize_live_selected")}
|
||
</div>`:d}
|
||
</div>`:d}
|
||
${e.unverifiedPositions.length?p`<div class="rhint" role="alert">
|
||
${this.host._t("gs.optimize_unverified",{n:String(e.unverifiedPositions.length)})}
|
||
${w?` ${this.host._t("gs.optimize_registry_limited")}`:""}
|
||
</div>`:d}
|
||
${e.nestedRefsUnresolved?p`<div class="rhint" role="alert">${this.host._t("gs.optimize_vacuum_warning",{n:String(e.nestedRefsUnresolved)})}</div>`:d}
|
||
${x.length?p`<details class="optimize-details">
|
||
<summary>${this.host._t("gs.optimize_details")}</summary>
|
||
<ul>
|
||
${M.map(t=>p`<li>${this.host._t("gs.optimize_detail_item",{status:$(t),kind:k(t.kind),id:t.id,space:t.spaceId})}</li>`)}
|
||
</ul>
|
||
${C?p`<div class="rhint">${this.host._t("gs.optimize_details_more",{n:String(C)})}</div>`:d}
|
||
</details>`:d}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>{this.host._alignDialog=null,this.host._preflightClipboardFallback=null}}>${this.host._t("btn.cancel")}</button>
|
||
${t.changed&&t.preflight?.ok?p`
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>this._runAlignToGrid()} ?disabled=${t.busy}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${t.busy?"…":this.host._t("gs.align_run")}
|
||
</button>`:d}
|
||
</div>
|
||
</hp-dialog>`}_renderSettingsDialog(){return Pr.call(this)}_rulesSet(t){this.host._rulesDialog={...this.host._rulesDialog,rules:t}}async _saveRules(){const t=this.host._rulesDialog;if(!t||t.busy)return;const e=t.rules.filter(t=>t.pattern.trim()&&t.icon.trim());this.host._rulesDialog={...t,busy:!0};try{const t=this.host._serverCfg,s=JSON.stringify(e)===JSON.stringify(Be),i={...t.settings};s?delete i.icon_rules:i.icon_rules=e,this.host._serverCfg={...t,settings:i},await this._saveConfigNow(),this.host._rulesDialog=null,this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("rules.saved"))}catch(t){this.host._rulesDialog&&(this.host._rulesDialog={...this.host._rulesDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}_renderRulesDialog(){const t=this.host._rulesDialog,e=Pi(t.rules),s=t.test.trim()?Ii(t.test,"",e):null,i=(e,s)=>{const i=[...t.rules],o=e+s;o<0||o>=i.length||([i[e],i[o]]=[i[o],i[e]],this._rulesSet(i))};return p`<hp-dialog .hass=${this.host.hass} data-kind="rules" .title=${this.host._t("rules.title")}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
icon="mdi:shape-plus-outline" wide @hp-close=${()=>this.host._rulesDialog=null}>
|
||
<div class="body">
|
||
<div class="rhint">${this.host._t("rules.hint")}</div>
|
||
<div class="rtest">
|
||
<input class="namein" type="text" placeholder=${this.host._t("rules.test_ph")}
|
||
.value=${t.test}
|
||
@input=${e=>this.host._rulesDialog={...t,test:e.target.value}} />
|
||
${i?p`<ha-icon icon=${i}></ha-icon><span class="rtesticon">${i}</span>`:d}
|
||
</div>
|
||
${t.rules.map((e,i)=>{const o=""!==e.pattern.trim()&&!Ds(e.pattern);return p`<div class="rrow">
|
||
<input class="namein rpat ${o?"bad":""}" type="text"
|
||
placeholder=${this.host._t("rules.pattern_ph")}
|
||
title=${o?this.host._t("rules.invalid"):""}
|
||
.value=${e.pattern}
|
||
@input=${s=>{const o=[...t.rules];o[i]={...e,pattern:s.target.value},this._rulesSet(o)}} />
|
||
<input class="namein ricon" type="text" placeholder=${this.host._t("rules.icon_ph")}
|
||
.value=${e.icon}
|
||
@input=${s=>{const o=[...t.rules];o[i]={...e,icon:s.target.value},this._rulesSet(o)}} />
|
||
<ha-icon class="rprev" icon=${e.icon||"mdi:chip"}></ha-icon>
|
||
<ha-icon class="ract" icon="mdi:arrow-up" title=${this.host._t("btn.up")}
|
||
@click=${()=>s(i,-1)}></ha-icon>
|
||
<ha-icon class="ract" icon="mdi:arrow-down" title=${this.host._t("btn.down")}
|
||
@click=${()=>s(i,1)}></ha-icon>
|
||
<ha-icon class="ract del" icon="mdi:close" title=${this.host._t("btn.delete")}
|
||
@click=${()=>this._rulesSet(t.rules.filter((t,e)=>e!==i))}></ha-icon>
|
||
</div>`})}
|
||
<button class="btn ghost" @click=${()=>this._rulesSet([...t.rules,{pattern:"",icon:""}])}>
|
||
<ha-icon icon="mdi:plus"></ha-icon>${this.host._t("rules.add")}
|
||
</button>
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<button class="btn ghost" @click=${()=>this._rulesSet(He.map(t=>({...t})))}>
|
||
${this.host._t("rules.reset")}
|
||
</button>
|
||
<span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._rulesDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>this._saveRules()} ?disabled=${t.busy}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${t.busy?"…":this.host._t("btn.save")}
|
||
</button>
|
||
</div>
|
||
</hp-dialog>`}_saveKioskScale(t){this.host._kioskScale={...this.host._kioskScale,...t};try{localStorage.setItem("houseplan_card_kiosk_v1",JSON.stringify(this.host._kioskScale))}catch{}this.host.requestUpdate()}_renderKioskDialog(){const t=this.host._kioskScale,e=(e,i)=>p`<label>${i}</label>
|
||
<div class="colorrow">
|
||
${this._rangeInput(50,300,5,Math.round(100*t[e]),t=>this._saveKioskScale({[e]:t/100}))}
|
||
<span class="opv">${Math.round(100*t[e])}%</span>
|
||
</div>`;return p`<hp-dialog .hass=${this.host.hass} data-kind="kiosk" .title=${this.host._t("kiosk.title")} icon="mdi:tablet"
|
||
dismiss-on-scrim @hp-close=${()=>this.host._kioskDialog=!1}>
|
||
<div class="body">
|
||
<div class="rhint">${this.host._t("kiosk.hint")}</div>
|
||
${e("icon",this.host._t("kiosk.icon_scale"))}
|
||
${e("font",this.host._t("kiosk.font_scale"))}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<button class="btn ghost" @click=${()=>this._saveKioskScale({icon:1,font:1})}>${this.host._t("gs.reset")}</button>
|
||
<span class="spacer"></span>
|
||
<button class="btn on" data-hp="dialog-cancel" @click=${()=>this.host._kioskDialog=!1}>${this.host._t("btn.close")}</button>
|
||
</div>
|
||
</hp-dialog>`}_renderVacSection(t){const e=this.host._devices.find(e=>e.id===t.devId);if(!e||!this.host._isVacDev(e))return d;const i=e.marker?.vacuum||{},o=this.host._vacAllCamerasFor===e.id,a=this.host._vacSourceResolution(e,o),n=a.entityId,r=a.candidates.find(t=>t.entityId===n)||null,l=n?Ls(this.host.hass?.states[n]?.attributes):null,h=!1!==i.live&&("ok"===a.status||"unsupported"===a.status),c=this._vacPlanRoomAnchors(e.space),u=l?Ts(l.rooms,c.map(t=>t.name)):0,_=!!(h&&l&&u>=3),m=t=>{const i=this.host._vacEnsureMarker(e);i&&(i.vacuum={...i.vacuum||{},...t},this.host._regSignature="",this.host._maybeRebuildDevices(),this._saveConfig(),this.host.requestUpdate())},g=new Set(e.entities||[]),f=a.candidates.filter(t=>g.has(t.entityId)||t.entityId===i.source),b=o?a.candidates.filter(t=>t.entityId.startsWith("camera.")&&!f.some(e=>e.entityId===t.entityId)):[],v=t=>[t.hasPosition?this.host._t("vac.cap_position"):"",t.hasRooms?this.host._t("vac.cap_rooms_short"):"",t.hasPath?this.host._t("vac.cap_path"):"",t.hasMapId?this.host._t("vac.cap_map"):""].filter(Boolean).join(" · ")||this.host._t("vac.cap_none"),y=t=>p`
|
||
<button type="button" class="vacsource ${t.entityId===n?"on":""}"
|
||
@click=${()=>m({source:t.entityId})}>
|
||
<span><b>${t.name}</b><small>${t.entityId}</small></span>
|
||
<span class="vacsource-meta">${t.platform||this.host._t("vac.platform_unknown")} · ${v(t)}</span>
|
||
</button>`,w=a.candidates.some(t=>g.has(t.entityId)&&"known_xcme_incomplete"===t.category)||!!a.pinned&&!!n?.startsWith("camera.")&&!r?.hasPosition;return p`
|
||
<label>${this.host._t("vac.section")}</label>
|
||
<div class="bindbox vacbox">
|
||
<div class="vacdiag" role="status">
|
||
<div><span>${this.host._t("vac.diag_source")}</span><b>${n||this.host._t("vac.source_none")}</b></div>
|
||
${r?.platform?p`<div><span>${this.host._t("vac.diag_platform")}</span><b>${r.platform}</b></div>`:d}
|
||
<div><span>${this.host._t("vac.diag_status")}</span><b>${this.host._t(`vac.source_status_${a.status}`)}</b></div>
|
||
<div><span>${this.host._t("vac.diag_position")}</span><b>${l?.pos?this.host._t("common.yes"):this.host._t("common.no")}</b></div>
|
||
<div><span>${this.host._t("vac.diag_rooms")}</span><b>${s(this.host._t("vac.diag_rooms_value"),{total:String(l?.rooms.length||0),matched:String(u),readiness:this.host._t(u>=3?"vac.autocal_ready":"vac.autocal_not_ready")})}</b></div>
|
||
<div><span>${this.host._t("vac.diag_path")}</span><b>${l?.path.length?this.host._t("common.yes"):this.host._t("common.no")}</b></div>
|
||
<div><span>${this.host._t("vac.diag_map")}</span><b>${l?.mapId??"default"}</b></div>
|
||
</div>
|
||
${"missing"===a.status||"disabled"===a.status||"unverified"===a.status?p`<div class="warn vacsource-warning">
|
||
<span>${this.host._t(`vac.source_banner_${a.status}`)}</span>
|
||
<button type="button" class="btn ghostbtn" @click=${()=>{const t=[...this.host.renderRoot.querySelectorAll("details.vacpicker")].find(t=>t.dataset.devId===e.id);t&&(t.open=!0,t.querySelector("summary")?.focus())}}>${this.host._t("vac.choose_source")}</button>
|
||
</div>`:d}
|
||
${w?p`<div class="warn vacxcme">
|
||
<b>${this.host._t("vac.xcme_hint")}</b>
|
||
<pre>attributes:
|
||
- vacuum_position
|
||
- rooms
|
||
- path
|
||
- map_name</pre>
|
||
</div>`:d}
|
||
<details class="vacpicker" data-dev-id=${e.id}>
|
||
<summary class="btn ghostbtn">${this.host._t("vac.choose_source")}</summary>
|
||
<div class="vacsource-list">
|
||
<button type="button" class="vacsource ${a.pinned?"":"on"}"
|
||
@click=${()=>m({source:null})}>
|
||
<span><b>${this.host._t("vac.source_auto")}</b><small>${this.host._t("vac.source_auto_hint")}</small></span>
|
||
</button>
|
||
${f.map(y)}
|
||
<details ?open=${o}
|
||
@toggle=${t=>{t.currentTarget.open?this.host._vacOpenAllCameras(e):(this.host._vacAllCamerasFor=null,this.host._vacAllCameraCache=null)}}>
|
||
<summary>${this.host._t("vac.all_cameras")}</summary>
|
||
<div class="rhint">${this.host._t("vac.all_cameras_warn")}</div>
|
||
${o?b.length?b.map(y):p`<div class="rhint">${this.host._t("vac.all_cameras_empty")}</div>`:d}
|
||
</details>
|
||
</div>
|
||
</details>
|
||
<div class="vacbtns">
|
||
${_?p`<button class="btn" ?disabled=${this.host._markerDialog?.busy} @click=${()=>this._vacAutoCalibrate(e)}>${this.host._t("vac.autocal")}</button>`:d}
|
||
${h?p`<button class="btn ghostbtn" ?disabled=${this.host._markerDialog?.busy} @click=${()=>this._vacStartFit(e)}>${this.host._t("vac.fit")}</button>`:d}
|
||
<a class="btn ghostbtn" href="https://github.com/Matysh/houseplan-card/blob/main/docs/VACUUM.md"
|
||
target="_blank" rel="noopener">${this.host._t("vac.documentation")}</a>
|
||
</div>
|
||
${l?p`
|
||
<label class="srcrow">
|
||
${this._boolInput(!1!==i.live,t=>m({live:!!t&&null}))}
|
||
<span>${this.host._t("vac.live")}</span>
|
||
</label>
|
||
<label>${this.host._t("vac.trail")}</label>
|
||
<select class="areasel"
|
||
@change=${t=>m({trail_mode:t.target.value,trail:null})}>
|
||
${["never","cleaning","always"].map(t=>p`
|
||
<option value=${t} ?selected=${Rs(i)===t}>${this.host._t("vac.trail_"+t)}</option>`)}
|
||
</select>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${wa(this,e,a)}
|
||
`:d}
|
||
</div>`}_vacMapId(t,e,i=this.host._planHass){return this.host._vacMapId(t,e,i)}_vacSaveMatrix(t,e,i,s,o=""){return bd(this,t,e,i,s,o)}_vacPlanRoomAnchors(t){return(this.host._spaceModelById(t)?.rooms||[]).map(t=>({room:t,poly:B(t)})).filter(({room:t,poly:e})=>t.name&&e).map(({room:t,poly:e})=>{const i=Fs(e);return i?{name:String(t.name),cx:i[0],cy:i[1]}:null}).filter(Boolean)}async _vacAutoCalibrate(t){if(this.host._markerDialog?.busy)return;const e=this.host._vacSource(t),i=e?Ls(this.host.hass?.states[e]?.attributes):null;if(!e||!i||i.rooms.length<3)return void this.host._showToast(this.host._t("vac.autocal_no_rooms"));const s=this._vacMapId(t,i),a=function(t,e,i,s,a){const n=o(t,e,i,s).find(t=>t.source===s&&t.map_id===a);return{space:n?.space||i,routeId:n?.id||""}}(t.id,t.marker?.vacuum??null,t.space,e,s),n=zs(i.rooms,this._vacPlanRoomAnchors(a.space));if(!n)return void this.host._showToast(this.host._t("vac.autocal_no_match"));const r=this.host._serverCfg?.spaces?.find(t=>t.id===a.space),l=Number(r?.cell_cm),h=Number.isFinite(l)&&l>0?l:5,c=Ns(n.residual,this.host._gridPitch,h);c>Es?this.host._vacCalConfirm={markerId:t.id,source:e,mapId:s,routeId:a.routeId,space:a.space,matrix:n.matrix,rooms:n.matched.length,error:pe(c,"mi"===this.host.hass?.config?.unit_system?.length)}:await async function(t,e){if(gd.has(t))return;gd.add(t);const i=t.host,s=i._markerDialog,o=s?{...s,busy:!0}:null;o&&(i._markerDialog=o,i.requestUpdate());try{await bd(t,e.markerId,e.source,e.mapId,e.matrix,e.routeId)&&i._showToast(i._t("vac.autocal_done",{rooms:String(e.rooms)}))}finally{gd.delete(t),o&&i._markerDialog===o&&(i._markerDialog={...o,busy:!1},i.requestUpdate())}}(this,{markerId:t.id,source:e,mapId:s,routeId:a.routeId,space:a.space,matrix:n.matrix,rooms:n.matched.length})}_vacApplyCalibrationProposal(t){return async function(t,e){const i=t.host,s=i._vacCalConfirm;if(!s||s.busy)return;if(e){const t=i._devices.find(t=>t.id===s.markerId),e=n(s.matrix);if(!t||!e)return;const o=s.space||t.space;if(o!==i._space&&!i._commitSpace(o))return;return i._vacCalConfirm=null,i._markerDialog=null,void(i._vacFit={markerId:s.markerId,source:s.source,routeId:s.routeId,mapId:s.mapId,p:e,drag:null})}const o={...s,busy:!0};i._vacCalConfirm=o,i.requestUpdate();const a=await bd(t,s.markerId,s.source,s.mapId,s.matrix,s.routeId);i._vacCalConfirm===o&&(i._vacCalConfirm=a?null:{...s,busy:!1},i.requestUpdate()),a&&i._showToast(i._t("vac.autocal_done",{rooms:String(s.rooms)}))}(this,t)}_vacStartFit(t,e=""){if(this.host._markerDialog?.busy)return;const i=this.host._vacSource(t),s=i?Ls(this.host.hass?.states[i]?.attributes):null;if(!i||!s)return void this.host._showToast(this.host._t("vac.cal_need_pos"));const l=this._vacMapId(t,s),h=function(t,e,i){const s=o(t,e,i.dockSpace,i.source),l=s.find(t=>t.id===i.routeId)||s.find(t=>t.source===i.source&&t.map_id===i.mapId)||null,h=l?.space||i.dockSpace,c=i.viewBoxOf(h);if(!c)return null;const d=a(l?l.calibration:e?.calibration?.[i.mapId]),p=d&&n(d)||r(i.rooms,c);return{space:h,routeId:l?.id||"",params:p}}(t.id,t.marker?.vacuum??null,{routeId:e,source:i,mapId:l,dockSpace:t.space,rooms:s.rooms,viewBoxOf:t=>this.host._spaceModelById(t)?.vb??null});h&&(this.host._markerDialog=null,(h.space===this.host._space||this.host._commitSpace(h.space))&&(this.host._vacFit={markerId:t.id,source:i,mapId:l,routeId:h.routeId,p:h.params,drag:null}))}_vacFitSave(){return async function(t,e){const i=t.host,s=i._vacFit;if(!s||s.busy)return;const o={...s,busy:!0,drag:null};i._vacFit=o,i.requestUpdate();const a=await bd(t,s.markerId,s.source,s.mapId,e(s.p),s.routeId);i._vacFit===o&&(i._vacFit=a?null:{...s,busy:!1,drag:null},i.requestUpdate()),a&&i._showToast(i._t("vac.cal_done"))}(this,Os)}_vacFitTurn(t){const e=this.host._vacFit;if(!e||e.busy)return;const i=Ls(this.host.hass?.states[e.source]?.attributes),s=this._vacGhostCentre(i?.rooms||[]),o={...e.p,...t};this.host._vacFit={...e,p:As(o,e.p,s[0],s[1])}}_vacGhostCentre(t){const e=[],i=[];for(const s of t)e.push(s.x0??s.cx,s.x1??s.cx),i.push(s.y0??s.cy,s.y1??s.cy);return e.length?[(Math.min(...e)+Math.max(...e))/2,(Math.min(...i)+Math.max(...i))/2]:[0,0]}_vacDelta(t,e,i){const s=this.host._stageEl,o=s?.clientWidth||1,a=s?.clientHeight||1;return[e/o*t.w,i/a*t.h]}_vacFitPointer(t,e){const i=this.host._vacFit;if(!i)return;if(t.stopPropagation(),i.busy)return;if("pointerdown"===t.type){const e=t.target,s=e.getAttribute?.("data-corner");try{t.currentTarget.setPointerCapture?.(t.pointerId)}catch{}return void(this.host._vacFit={...i,drag:s?{kind:"scale",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:Number(s.split(",")[0]),fy:Number(s.split(",")[1])}:{kind:"move",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:0,fy:0}})}const s=i.drag;if(s){if("pointermove"===t.type){const[o,a]=this._vacDelta(e,t.clientX-s.sx,t.clientY-s.sy);if("move"===s.kind)this.host._vacFit={...i,p:{...s.p0,ox:s.p0.ox+o,oy:s.p0.oy+a}};else{const t=Ls(this.host.hass?.states[i.source]?.attributes),e=this._vacGhostCentre(t?.rooms||[]),n=Os(s.p0),[r,l]=Bs(n,e[0],e[1]),[h,c]=Bs(n,s.fx,s.fy),d=Math.hypot(r-h,l-c)||1,[p,u]=[2*r-h,2*l-c],_=Math.hypot(p+2*o-h,u+2*a-c)/2,m=Math.max(.05,_/d),g={...s.p0,s:s.p0.s*m};this.host._vacFit={...i,p:As(g,s.p0,s.fx,s.fy)}}return}"pointerup"!==t.type&&"pointercancel"!==t.type||(this.host._vacFit={...i,drag:null})}}_renderVacFit(t){const e=this.host._vacFit;if(!e)return d;const i=Ls(this.host._renderPlanHass?.states?.[e.source]?.attributes);if(!i)return d;const s=Os(e.p),o=[],a=[],n=[];for(const t of i.rooms){if(null==t.x0)continue;const e=[[t.x0,t.y0],[t.x1,t.y0],[t.x1,t.y1],[t.x0,t.y1]].map(([t,e])=>Bs(s,t,e));e.forEach(([t,e])=>{a.push(t),n.push(e)});const[i,r]=Bs(s,t.cx,t.cy);o.push(Tt`<polygon points="${e.map(t=>t[0].toFixed(1)+","+t[1].toFixed(1)).join(" ")}"></polygon>
|
||
<text x="${i.toFixed(1)}" y="${r.toFixed(1)}">${t.name}</text>`)}let r=d;if(i.pos){const[e,o]=Bs(s,i.pos.x,i.pos.y);r=Tt`<circle class="vacfitdot" cx="${e.toFixed(1)}" cy="${o.toFixed(1)}" r="${(.012*t.w).toFixed(1)}"></circle>`}const l=[];if(a.length){const e=(()=>{const t=s[0]*s[4]-s[1]*s[3];return(e,i)=>[(s[4]*(e-s[2])-s[1]*(i-s[5]))/t,(-s[3]*(e-s[2])+s[0]*(i-s[5]))/t]})(),i=Math.min(...a),o=Math.max(...a),r=Math.min(...n),h=Math.max(...n),c=.022*t.w,d=c/4;for(const[t,s,a,n]of[[i,r,o,h],[o,r,i,h],[o,h,i,r],[i,h,o,r]]){const i=e(a,n);l.push(Tt`<circle class="vacfithandle" data-corner="${i[0]+","+i[1]}"
|
||
cx="${t.toFixed(1)}" cy="${s.toFixed(1)}" r="${c.toFixed(1)}"></circle>
|
||
<circle class="vacfitknob" cx="${t.toFixed(1)}" cy="${s.toFixed(1)}" r="${d.toFixed(2)}"></circle>`)}}return p`<svg class="vacfit" viewBox="${t.x} ${t.y} ${t.w} ${t.h}"
|
||
========
|
||
${ba(this,e,a)}
|
||
`:d}
|
||
</div>`}_vacMapId(t,e,s=this.host._planHass){return this.host._vacMapId(t,e,s)}_vacSaveMatrix(t,e,s,i,o=""){return _d(this,t,e,s,i,o)}_vacPlanRoomAnchors(t){return(this.host._spaceModelById(t)?.rooms||[]).map(t=>({room:t,poly:B(t)})).filter(({room:t,poly:e})=>t.name&&e).map(({room:t,poly:e})=>{const s=zi(e);return s?{name:String(t.name),cx:s[0],cy:s[1]}:null}).filter(Boolean)}async _vacAutoCalibrate(t){if(this.host._markerDialog?.busy)return;const e=this.host._vacSource(t),s=e?Li(this.host.hass?.states[e]?.attributes):null;if(!e||!s||s.rooms.length<3)return void this.host._showToast(this.host._t("vac.autocal_no_rooms"));const i=this._vacMapId(t,s),a=function(t,e,s,i,a){const n=o(t,e,s,i).find(t=>t.source===i&&t.map_id===a);return{space:n?.space||s,routeId:n?.id||""}}(t.id,t.marker?.vacuum??null,t.space,e,i),n=Fi(s.rooms,this._vacPlanRoomAnchors(a.space));if(!n)return void this.host._showToast(this.host._t("vac.autocal_no_match"));const r=this.host._serverCfg?.spaces?.find(t=>t.id===a.space),l=Number(r?.cell_cm),h=Number.isFinite(l)&&l>0?l:5,c=Ni(n.residual,this.host._gridPitch,h);c>Ai?this.host._vacCalConfirm={markerId:t.id,source:e,mapId:i,routeId:a.routeId,space:a.space,matrix:n.matrix,rooms:n.matched.length,error:pe(c,"mi"===this.host.hass?.config?.unit_system?.length)}:await async function(t,e){if(pd.has(t))return;pd.add(t);const s=t.host,i=s._markerDialog,o=i?{...i,busy:!0}:null;o&&(s._markerDialog=o,s.requestUpdate());try{await _d(t,e.markerId,e.source,e.mapId,e.matrix,e.routeId)&&s._showToast(s._t("vac.autocal_done",{rooms:String(e.rooms)}))}finally{pd.delete(t),o&&s._markerDialog===o&&(s._markerDialog={...o,busy:!1},s.requestUpdate())}}(this,{markerId:t.id,source:e,mapId:i,routeId:a.routeId,space:a.space,matrix:n.matrix,rooms:n.matched.length})}_vacApplyCalibrationProposal(t){return async function(t,e){const s=t.host,i=s._vacCalConfirm;if(!i||i.busy)return;if(e){const t=s._devices.find(t=>t.id===i.markerId),e=n(i.matrix);if(!t||!e)return;const o=i.space||t.space;if(o!==s._space&&!s._commitSpace(o))return;return s._vacCalConfirm=null,s._markerDialog=null,void(s._vacFit={markerId:i.markerId,source:i.source,routeId:i.routeId,mapId:i.mapId,p:e,drag:null})}const o={...i,busy:!0};s._vacCalConfirm=o,s.requestUpdate();const a=await _d(t,i.markerId,i.source,i.mapId,i.matrix,i.routeId);s._vacCalConfirm===o&&(s._vacCalConfirm=a?null:{...i,busy:!1},s.requestUpdate()),a&&s._showToast(s._t("vac.autocal_done",{rooms:String(i.rooms)}))}(this,t)}_vacStartFit(t,e=""){if(this.host._markerDialog?.busy)return;const s=this.host._vacSource(t),i=s?Li(this.host.hass?.states[s]?.attributes):null;if(!s||!i)return void this.host._showToast(this.host._t("vac.cal_need_pos"));const l=this._vacMapId(t,i),h=function(t,e,s){const i=o(t,e,s.dockSpace,s.source),l=i.find(t=>t.id===s.routeId)||i.find(t=>t.source===s.source&&t.map_id===s.mapId)||null,h=l?.space||s.dockSpace,c=s.viewBoxOf(h);if(!c)return null;const d=a(l?l.calibration:e?.calibration?.[s.mapId]),p=d&&n(d)||r(s.rooms,c);return{space:h,routeId:l?.id||"",params:p}}(t.id,t.marker?.vacuum??null,{routeId:e,source:s,mapId:l,dockSpace:t.space,rooms:i.rooms,viewBoxOf:t=>this.host._spaceModelById(t)?.vb??null});h&&(this.host._markerDialog=null,(h.space===this.host._space||this.host._commitSpace(h.space))&&(this.host._vacFit={markerId:t.id,source:s,mapId:l,routeId:h.routeId,p:h.params,drag:null}))}_vacFitSave(){return async function(t,e){const s=t.host,i=s._vacFit;if(!i||i.busy)return;const o={...i,busy:!0,drag:null};s._vacFit=o,s.requestUpdate();const a=await _d(t,i.markerId,i.source,i.mapId,e(i.p),i.routeId);s._vacFit===o&&(s._vacFit=a?null:{...i,busy:!1,drag:null},s.requestUpdate()),a&&s._showToast(s._t("vac.cal_done"))}(this,Oi)}_vacFitTurn(t){const e=this.host._vacFit;if(!e||e.busy)return;const s=Li(this.host.hass?.states[e.source]?.attributes),i=this._vacGhostCentre(s?.rooms||[]),o={...e.p,...t};this.host._vacFit={...e,p:Ei(o,e.p,i[0],i[1])}}_vacGhostCentre(t){const e=[],s=[];for(const i of t)e.push(i.x0??i.cx,i.x1??i.cx),s.push(i.y0??i.cy,i.y1??i.cy);return e.length?[(Math.min(...e)+Math.max(...e))/2,(Math.min(...s)+Math.max(...s))/2]:[0,0]}_vacDelta(t,e,s){const i=this.host._stageEl,o=i?.clientWidth||1,a=i?.clientHeight||1;return[e/o*t.w,s/a*t.h]}_vacFitPointer(t,e){const s=this.host._vacFit;if(!s)return;if(t.stopPropagation(),s.busy)return;if("pointerdown"===t.type){const e=t.target,i=e.getAttribute?.("data-corner");try{t.currentTarget.setPointerCapture?.(t.pointerId)}catch{}return void(this.host._vacFit={...s,drag:i?{kind:"scale",sx:t.clientX,sy:t.clientY,p0:{...s.p},fx:Number(i.split(",")[0]),fy:Number(i.split(",")[1])}:{kind:"move",sx:t.clientX,sy:t.clientY,p0:{...s.p},fx:0,fy:0}})}const i=s.drag;if(i){if("pointermove"===t.type){const[o,a]=this._vacDelta(e,t.clientX-i.sx,t.clientY-i.sy);if("move"===i.kind)this.host._vacFit={...s,p:{...i.p0,ox:i.p0.ox+o,oy:i.p0.oy+a}};else{const t=Li(this.host.hass?.states[s.source]?.attributes),e=this._vacGhostCentre(t?.rooms||[]),n=Oi(i.p0),[r,l]=Bi(n,e[0],e[1]),[h,c]=Bi(n,i.fx,i.fy),d=Math.hypot(r-h,l-c)||1,[p,u]=[2*r-h,2*l-c],_=Math.hypot(p+2*o-h,u+2*a-c)/2,m=Math.max(.05,_/d),g={...i.p0,s:i.p0.s*m};this.host._vacFit={...s,p:Ei(g,i.p0,i.fx,i.fy)}}return}"pointerup"!==t.type&&"pointercancel"!==t.type||(this.host._vacFit={...s,drag:null})}}_renderVacFit(t){const e=this.host._vacFit;if(!e)return d;const s=Li(this.host._renderPlanHass?.states?.[e.source]?.attributes);if(!s)return d;const i=Oi(e.p),o=[],a=[],n=[];for(const t of s.rooms){if(null==t.x0)continue;const e=[[t.x0,t.y0],[t.x1,t.y0],[t.x1,t.y1],[t.x0,t.y1]].map(([t,e])=>Bi(i,t,e));e.forEach(([t,e])=>{a.push(t),n.push(e)});const[s,r]=Bi(i,t.cx,t.cy);o.push(Tt`<polygon points="${e.map(t=>t[0].toFixed(1)+","+t[1].toFixed(1)).join(" ")}"></polygon>
|
||
<text x="${s.toFixed(1)}" y="${r.toFixed(1)}">${t.name}</text>`)}let r=d;if(s.pos){const[e,o]=Bi(i,s.pos.x,s.pos.y);r=Tt`<circle class="vacfitdot" cx="${e.toFixed(1)}" cy="${o.toFixed(1)}" r="${(.012*t.w).toFixed(1)}"></circle>`}const l=[];if(a.length){const e=(()=>{const t=i[0]*i[4]-i[1]*i[3];return(e,s)=>[(i[4]*(e-i[2])-i[1]*(s-i[5]))/t,(-i[3]*(e-i[2])+i[0]*(s-i[5]))/t]})(),s=Math.min(...a),o=Math.max(...a),r=Math.min(...n),h=Math.max(...n),c=.022*t.w,d=c/4;for(const[t,i,a,n]of[[s,r,o,h],[o,r,s,h],[o,h,s,r],[s,h,o,r]]){const s=e(a,n);l.push(Tt`<circle class="vacfithandle" data-corner="${s[0]+","+s[1]}"
|
||
cx="${t.toFixed(1)}" cy="${i.toFixed(1)}" r="${c.toFixed(1)}"></circle>
|
||
<circle class="vacfitknob" cx="${t.toFixed(1)}" cy="${i.toFixed(1)}" r="${d.toFixed(2)}"></circle>`)}}return p`<svg class="vacfit" viewBox="${t.x} ${t.y} ${t.w} ${t.h}"
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
preserveAspectRatio="none"
|
||
@pointerdown=${e=>this._vacFitPointer(e,t)}
|
||
@pointermove=${e=>this._vacFitPointer(e,t)}
|
||
@pointerup=${e=>this._vacFitPointer(e,t)}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
@pointercancel=${e=>this._vacFitPointer(e,t)}>${o}${r}${l}</svg>`}_resetRoomDialogFields(){this.host._roomEditId=null,this.host._roomFill="",this.host._roomCustomFill=null,this.host._roomTempMin="",this.host._roomTempMax="",this.host._roomTempSrc="",this.host._roomHumSrc="",this.host._roomSrcOpen=null,this.host._roomSrcFilter="",this.host._roomNameScale=1,this.host._roomLabelScale=1}_openRoomEdit(t){if(!t.id)return;this.host._roomEditId=t.id,this.host._nameSel=t.name||"",this.host._areaSel=t.area||"",this.host._roomFill="glow"===t.settings?.fill_mode?"":t.settings?.fill_mode||"";const e="custom"===this.host._roomFill?t.settings?.custom_fill:null;var i;this.host._roomCustomFill=e&&"object"==typeof e?us(e,b(this.host._curSpaceCfg).customFill):null,[this.host._roomTempMin,this.host._roomTempMax]=Hs(t.settings),this.host._roomTempSrc=t.settings?.temp_source||"",this.host._roomHumSrc=t.settings?.hum_source||"",this.host._roomNameScale=Ws(t.settings?.name_scale),this.host._roomLabelScale=Ws(t.settings?.label_scale),this.host._roomSrcOpen=null,this.host._roomSrcFilter="",this.host._roomDialog=!0,i=this.host,u(i,"room",Tr(i))}_roomSettingsFromDialog(){const t={};return this.host._roomFill&&(t.fill_mode=this.host._roomFill),"custom"===this.host._roomFill&&this.host._roomCustomFill&&(t.custom_fill=this.host._roomCustomFill),this.host._roomTempSrc&&(t.temp_source=this.host._roomTempSrc),this.host._roomHumSrc&&(t.hum_source=this.host._roomHumSrc),Gs(t,this.host._roomTempMin,this.host._roomTempMax),1!==this.host._roomNameScale&&(t.name_scale=this.host._roomNameScale),1!==this.host._roomLabelScale&&(t.label_scale=this.host._roomLabelScale),Object.keys(t).length?t:null}_saveRoomEdit(){const t=this.host._curSpaceCfg,e=t?.rooms.find(t=>t.id===this.host._roomEditId);if(!e)return this.host._roomDialog=!1,void(this.host._roomEditId=null);e.name=this.host._nameSel.trim()||e.name,e.area=this.host._areaSel||null;const i=e.settings||{},s={...i};Gs(s,this.host._roomTempMin,this.host._roomTempMax)&&(this.host._roomFill?s.fill_mode=this.host._roomFill:delete s.fill_mode,"custom"===this.host._roomFill&&this.host._roomCustomFill?s.custom_fill=this.host._roomCustomFill:delete s.custom_fill,"glow"===i.fill_mode&&"boolean"!=typeof i.glow&&(s.glow=!0),this.host._roomTempSrc?s.temp_source=this.host._roomTempSrc:delete s.temp_source,this.host._roomHumSrc?s.hum_source=this.host._roomHumSrc:delete s.hum_source,1!==this.host._roomNameScale?s.name_scale=this.host._roomNameScale:delete s.name_scale,1!==this.host._roomLabelScale?s.label_scale=this.host._roomLabelScale:delete s.label_scale,Object.keys(s).length?e.settings=s:delete e.settings,this._saveConfig(),this.host._roomDialog=!1,this.host._roomEditId=null,this.host._nameSel="",this.host._areaSel="",this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate(),this.host._showToast(this.host._t("toast.room_updated")))}_roomSrcCandidates(){const t=this.host._planHass,e=ce(this.host._markers),i=this.host._roomSrcFilter.trim().toLowerCase(),s=[];for(const o of Object.values(t.devices)){if("service"===o.entry_type)continue;if(e.devices.has(o.id))continue;const t=(o.name_by_user||o.name||o.id).trim();i&&!t.toLowerCase().includes(i)||s.push({value:"device:"+o.id,label:t,sub:o.model||this.host._t("marker.sub_device")})}for(const[o,a]of Object.entries(t.entities)){if(!o.startsWith("sensor.")||a.hidden)continue;if(de(t,o,e))continue;const n=a.name||t.states[o]?.attributes?.friendly_name||o;i&&!(n+" "+o).toLowerCase().includes(i)||s.push({value:"entity:"+o,label:n,sub:o})}return s.sort((t,e)=>t.label.localeCompare(e.label)),s.slice(0,200)}_roomSrcLabel(t){const e=t.indexOf(":"),i=t.slice(0,e),s=t.slice(e+1);return"device"===i?this.host._fullRegistryHass.devices[s]?.name_by_user||this.host._fullRegistryHass.devices[s]?.name||s:this.host._fullRegistryHass.entities[s]?.name||this.host.hass.states[s]?.attributes?.friendly_name||s}_labelPos(t,e){const i=this.host._layout["rl_"+(t.id||"")];if(i&&i.s===e)return{x:i.x*Qd,y:i.y*Qd};const s=this._snap(this.host._roomCenter(t));return{x:s[0],y:s[1]}}_labelDown(t,e,i){if("plan"!==this.host._mode)return;t.preventDefault(),t.stopPropagation();const s=this._labelPos(e,i);this.host._drag={id:"rl_"+(e.id||""),sx:t.clientX,sy:t.clientY,ox:s.x,oy:s.y,moved:!1},ep(t),this.host._tip=null}_labelMove(t,e,i){const s="rl_"+(e.id||"");if(!this.host._drag||this.host._drag.id!==s)return;const o=this.host._stageEl;if(!o)return;const a=this.host._spaceModelById(i);if(!a)return;const n=a.vb,r=o.getBoundingClientRect(),l=this.host._viewOr(n),h=(t.clientX-this.host._drag.sx)/r.width*l.w,c=(t.clientY-this.host._drag.sy)/r.height*l.h;Math.abs(t.clientX-this.host._drag.sx)+Math.abs(t.clientY-this.host._drag.sy)>3&&(this.host._drag.moved=!0);const d=qe(this.host._drag.ox+h),p=qe(this.host._drag.oy+c);this.host._savePos({id:s,space:i},d,p)}_labelUp(t){const e="rl_"+(t.id||"");if(!this.host._drag||this.host._drag.id!==e)return;const i=this.host._drag.moved;this.host._drag=i?this.host._drag:null,i&&window.setTimeout(()=>this.host._drag=null,0)}_labelScale(t){const e=this.host._layout["rl_"+(t.id||"")]?.k;return"number"==typeof e&&Number.isFinite(e)?Math.min(3,Math.max(.5,e)):1}_rlResizeDown(t,e,i){if("plan"!==this.host._mode)return;t.preventDefault(),t.stopPropagation();const s=t.target.closest(".roomlabel");if(!s)return;const o=s.getBoundingClientRect(),a=o.left+o.width/2,n=o.top+o.height/2,r=Math.max(8,Math.hypot(t.clientX-a,t.clientY-n));this.host._rlResize={id:"rl_"+(e.id||""),space:i,k0:this._labelScale(e),cx:a,cy:n,d0:r},ep(t)}_rlResizeMove(t){const e=this.host._rlResize;if(!e)return;t.stopPropagation();const i=Math.max(8,Math.hypot(t.clientX-e.cx,t.clientY-e.cy)),s=Math.min(3,Math.max(.5,e.k0*(i/e.d0))),o=this.host._layout[e.id];if(o)this.host._layout={...this.host._layout,[e.id]:{...o,k:s}};else{const t=e.id.slice(3),i=this.host._spaceModelById(e.space);if(!i)return;const o=i.rooms.find(e=>e.id===t);if(!o)return;const a=this._labelPos(o,e.space);this.host._layout={...this.host._layout,[e.id]:{s:e.space,x:a.x/Qd,y:a.y/Qd,k:s}}}this.host._dirtyPos.add(e.id)}_rlResizeUp(){this.host._rlResize&&(this.host._rlResize=null,this.host._persistLayout())}_renderRoomGear(t,e,i){if(!t.id)return d;let s=null;if(t.poly?(s=this.host._gearPtCache.get(t.poly)||null,s||(s=gi(t.poly),this.host._gearPtCache.set(t.poly,s))):null!=t.x&&null!=t.y&&(s=[t.x+(t.w||0)/2,t.y+(t.h||0)/2]),!s)return d;const o=(s[0]-i.x)/i.w*100,a=(s[1]-i.y)/i.h*100;return p`<button class="rlgearbtn" data-hp="room-settings" data-room=${t.id}
|
||
========
|
||
@pointercancel=${e=>this._vacFitPointer(e,t)}>${o}${r}${l}</svg>`}_resetRoomDialogFields(){this.host._roomEditId=null,this.host._roomFill="",this.host._roomCustomFill=null,this.host._roomTempMin="",this.host._roomTempMax="",this.host._roomTempSrc="",this.host._roomHumSrc="",this.host._roomSrcOpen=null,this.host._roomSrcFilter="",this.host._roomNameScale=1,this.host._roomLabelScale=1}_openRoomEdit(t){if(!t.id)return;this.host._roomEditId=t.id,this.host._nameSel=t.name||"",this.host._areaSel=t.area||"",this.host._roomFill="glow"===t.settings?.fill_mode?"":t.settings?.fill_mode||"";const e="custom"===this.host._roomFill?t.settings?.custom_fill:null;var s;this.host._roomCustomFill=e&&"object"==typeof e?di(e,b(this.host._curSpaceCfg).customFill):null,[this.host._roomTempMin,this.host._roomTempMax]=Hi(t.settings),this.host._roomTempSrc=t.settings?.temp_source||"",this.host._roomHumSrc=t.settings?.hum_source||"",this.host._roomNameScale=Wi(t.settings?.name_scale),this.host._roomLabelScale=Wi(t.settings?.label_scale),this.host._roomSrcOpen=null,this.host._roomSrcFilter="",this.host._roomDialog=!0,s=this.host,u(s,"room",Ir(s))}_roomSettingsFromDialog(){const t={};return this.host._roomFill&&(t.fill_mode=this.host._roomFill),"custom"===this.host._roomFill&&this.host._roomCustomFill&&(t.custom_fill=this.host._roomCustomFill),this.host._roomTempSrc&&(t.temp_source=this.host._roomTempSrc),this.host._roomHumSrc&&(t.hum_source=this.host._roomHumSrc),ji(t,this.host._roomTempMin,this.host._roomTempMax),1!==this.host._roomNameScale&&(t.name_scale=this.host._roomNameScale),1!==this.host._roomLabelScale&&(t.label_scale=this.host._roomLabelScale),Object.keys(t).length?t:null}_saveRoomEdit(){const t=this.host._curSpaceCfg,e=t?.rooms.find(t=>t.id===this.host._roomEditId);if(!e)return this.host._roomDialog=!1,void(this.host._roomEditId=null);e.name=this.host._nameSel.trim()||e.name,e.area=this.host._areaSel||null;const s=e.settings||{},i={...s};ji(i,this.host._roomTempMin,this.host._roomTempMax)&&(this.host._roomFill?i.fill_mode=this.host._roomFill:delete i.fill_mode,"custom"===this.host._roomFill&&this.host._roomCustomFill?i.custom_fill=this.host._roomCustomFill:delete i.custom_fill,"glow"===s.fill_mode&&"boolean"!=typeof s.glow&&(i.glow=!0),this.host._roomTempSrc?i.temp_source=this.host._roomTempSrc:delete i.temp_source,this.host._roomHumSrc?i.hum_source=this.host._roomHumSrc:delete i.hum_source,1!==this.host._roomNameScale?i.name_scale=this.host._roomNameScale:delete i.name_scale,1!==this.host._roomLabelScale?i.label_scale=this.host._roomLabelScale:delete i.label_scale,Object.keys(i).length?e.settings=i:delete e.settings,this._saveConfig(),this.host._roomDialog=!1,this.host._roomEditId=null,this.host._nameSel="",this.host._areaSel="",this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate(),this.host._showToast(this.host._t("toast.room_updated")))}_roomSrcCandidates(){const t=this.host._planHass,e=ce(this.host._markers),s=this.host._roomSrcFilter.trim().toLowerCase(),i=[];for(const o of Object.values(t.devices)){if("service"===o.entry_type)continue;if(e.devices.has(o.id))continue;const t=(o.name_by_user||o.name||o.id).trim();s&&!t.toLowerCase().includes(s)||i.push({value:"device:"+o.id,label:t,sub:o.model||this.host._t("marker.sub_device")})}for(const[o,a]of Object.entries(t.entities)){if(!o.startsWith("sensor.")||a.hidden)continue;if(de(t,o,e))continue;const n=a.name||t.states[o]?.attributes?.friendly_name||o;s&&!(n+" "+o).toLowerCase().includes(s)||i.push({value:"entity:"+o,label:n,sub:o})}return i.sort((t,e)=>t.label.localeCompare(e.label)),i.slice(0,200)}_roomSrcLabel(t){const e=t.indexOf(":"),s=t.slice(0,e),i=t.slice(e+1);return"device"===s?this.host._fullRegistryHass.devices[i]?.name_by_user||this.host._fullRegistryHass.devices[i]?.name||i:this.host._fullRegistryHass.entities[i]?.name||this.host.hass.states[i]?.attributes?.friendly_name||i}_labelPos(t,e){const s=this.host._layout["rl_"+(t.id||"")];if(s&&s.s===e)return{x:s.x*Vd,y:s.y*Vd};const i=this._snap(this.host._roomCenter(t));return{x:i[0],y:i[1]}}_labelDown(t,e,s){if("plan"!==this.host._mode)return;t.preventDefault(),t.stopPropagation();const i=this._labelPos(e,s);this.host._drag={id:"rl_"+(e.id||""),sx:t.clientX,sy:t.clientY,ox:i.x,oy:i.y,moved:!1},Zd(t),this.host._tip=null}_labelMove(t,e,s){const i="rl_"+(e.id||"");if(!this.host._drag||this.host._drag.id!==i)return;const o=this.host._stageEl;if(!o)return;const a=this.host._spaceModelById(s);if(!a)return;const n=a.vb,r=o.getBoundingClientRect(),l=this.host._viewOr(n),h=(t.clientX-this.host._drag.sx)/r.width*l.w,c=(t.clientY-this.host._drag.sy)/r.height*l.h;Math.abs(t.clientX-this.host._drag.sx)+Math.abs(t.clientY-this.host._drag.sy)>3&&(this.host._drag.moved=!0);const d=Ge(this.host._drag.ox+h),p=Ge(this.host._drag.oy+c);this.host._savePos({id:i,space:s},d,p)}_labelUp(t){const e="rl_"+(t.id||"");if(!this.host._drag||this.host._drag.id!==e)return;const s=this.host._drag.moved;this.host._drag=s?this.host._drag:null,s&&window.setTimeout(()=>this.host._drag=null,0)}_labelScale(t){const e=this.host._layout["rl_"+(t.id||"")]?.k;return"number"==typeof e&&Number.isFinite(e)?Math.min(3,Math.max(.5,e)):1}_rlResizeDown(t,e,s){if("plan"!==this.host._mode)return;t.preventDefault(),t.stopPropagation();const i=t.target.closest(".roomlabel");if(!i)return;const o=i.getBoundingClientRect(),a=o.left+o.width/2,n=o.top+o.height/2,r=Math.max(8,Math.hypot(t.clientX-a,t.clientY-n));this.host._rlResize={id:"rl_"+(e.id||""),space:s,k0:this._labelScale(e),cx:a,cy:n,d0:r},Zd(t)}_rlResizeMove(t){const e=this.host._rlResize;if(!e)return;t.stopPropagation();const s=Math.max(8,Math.hypot(t.clientX-e.cx,t.clientY-e.cy)),i=Math.min(3,Math.max(.5,e.k0*(s/e.d0))),o=this.host._layout[e.id];if(o)this.host._layout={...this.host._layout,[e.id]:{...o,k:i}};else{const t=e.id.slice(3),s=this.host._spaceModelById(e.space);if(!s)return;const o=s.rooms.find(e=>e.id===t);if(!o)return;const a=this._labelPos(o,e.space);this.host._layout={...this.host._layout,[e.id]:{s:e.space,x:a.x/Vd,y:a.y/Vd,k:i}}}this.host._dirtyPos.add(e.id)}_rlResizeUp(){this.host._rlResize&&(this.host._rlResize=null,this.host._persistLayout())}_renderRoomGear(t,e,s){if(!t.id)return d;let i=null;if(t.poly?(i=this.host._gearPtCache.get(t.poly)||null,i||(i=_s(t.poly),this.host._gearPtCache.set(t.poly,i))):null!=t.x&&null!=t.y&&(i=[t.x+(t.w||0)/2,t.y+(t.h||0)/2]),!i)return d;const o=(i[0]-s.x)/s.w*100,a=(i[1]-s.y)/s.h*100;return p`<button class="rlgearbtn" data-hp="room-settings" data-room=${t.id}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
style="left:${o}%;top:${a}%"
|
||
title=${this.host._t("room.settings_title")}
|
||
@pointerdown=${t=>t.stopPropagation()}
|
||
@click=${e=>{e.stopPropagation(),this._openRoomEdit(t)}}>
|
||
<ha-icon icon="mdi:cog-outline"></ha-icon>
|
||
<span class="rlgeartext">${this.host._t("room.settings_short")}</span>
|
||
</button>`}_alignCandidates(){const t=[],e=this.host._spaceModel();if(this.host._markup){if(!e)return t;if(this.host._drag?.id.startsWith("rl_")){const i=this.host._drag.id.slice(3);for(const s of e.rooms){if(!s.name||s.id===i)continue;const e=this._labelPos(s,this.host._space);t.push([e.x,e.y])}return t}for(const i of e.rooms){const e=B(i);if(e)for(const i of e)t.push(i)}if("draw"===this.host._tool)for(const e of this.host._path)t.push(e);if("split"===this.host._tool&&this.host._splitSel?.pts)for(const e of this.host._splitSel.pts)t.push(e);return t}if("devices"===this.host._mode){const e=this.host._deviceDrag?.id??this.host._drag?.id;for(const i of this.host._devices){if(i.space!==this.host._space||i.id===e||"ha_disabled"===i.bindingStatus?.kind)continue;const s=this.host._pos(i);t.push([s.x,s.y])}return t}if("decor"===this.host._mode){const e=this.host._decorMove?.id;return t.push(...this._decorSnapGeometry(e).points),this.host._decorDraft&&t.push(this.host._decorDraft.a),t}return t}_renderAlignGuides(){const t=this.host._alignPoint;if(!t)return Tt``;const e=this.host._drag?.id.startsWith("rl_")?.5*this.host._gridPitch:.05*this.host._gridPitch,i=js(t,this._alignCandidates(),e);if(!i.length)return Tt``;const s=this.host._gridPitch,o=1.5*s;return Tt`<g class="alignguides">
|
||
${i.map(e=>{const[i,a,n,r]="x"===e.axis?[e.at,e.from[1],e.at,t[1]+Math.sign(t[1]-e.from[1])*o]:[e.from[0],e.at,t[0]+Math.sign(t[0]-e.from[0])*o,e.at];return Tt`<line class="alignline" x1="${i}" y1="${a}" x2="${n}" y2="${r}"></line>
|
||
<circle class="aligndot" cx="${e.from[0]}" cy="${e.from[1]}"
|
||
r="${Et(.18*s,this.host._cellCm)}"></circle>`})}
|
||
</g>`}_renderOpeningCenterTick(t){const e=(t.angle+90)*Math.PI/180,i=Et(15,this.host._cellCm);return Tt`<line class="alignline opcentertick"
|
||
x1="${t.x-Math.cos(e)*i}" y1="${t.y-Math.sin(e)*i}"
|
||
x2="${t.x+Math.cos(e)*i}" y2="${t.y+Math.sin(e)*i}"></line>`}_renderOpeningDimensionGuides(t){const e=t.labels.flatMap(t=>t.dimension?[t.dimension]:[]);if(!e.length)return Tt``;const i=this._cssPxToRender(4);return Tt`<g class="opening-dimensions" aria-hidden="true" pointer-events="none">
|
||
${e.map(t=>{const e=-t.axis[1],s=t.axis[0],o=(t,o)=>Tt`<line
|
||
class="opening-dimension-tick" data-end=${o}
|
||
x1=${t[0]-e*i} y1=${t[1]-s*i}
|
||
x2=${t[0]+e*i} y2=${t[1]+s*i}></line>`;return Tt`<g class="opening-dimension" data-source=${t.source}
|
||
data-room=${t.roomId||d}>
|
||
<line class="opening-dimension-line"
|
||
x1=${t.from[0]} y1=${t.from[1]}
|
||
x2=${t.to[0]} y2=${t.to[1]}></line>
|
||
${o(t.from,"from")}${o(t.to,"to")}
|
||
</g>`})}
|
||
</g>`}_renderOpeningPlacementPreview(){const t=this.host._openingPreview;if(!t)return Tt``;const e={type:t.type,length:t.renderedLength,angle:t.angle,amount:Us(t.type,null),flipH:t.flipH,flipV:t.flipV,base:"var(--hp-open)",tone:"var(--hp-open)",cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,face:t.face},i="passage"===t.type?qs(t,Et(this.host._gridPitch,this.host._cellCm)):null;return Tt`<g class="opening-preview" data-kind=${t.type}
|
||
aria-hidden="true" pointer-events="none"
|
||
transform="translate(${t.x} ${t.y}) rotate(${t.angle})">
|
||
${i?Tt`
|
||
<rect class="passage-preview-cut" pointer-events="none"
|
||
x=${i.rect.x} y=${i.rect.y}
|
||
width=${i.rect.width} height=${i.rect.height}></rect>
|
||
${i.boundaries.map(t=>Tt`
|
||
<line class="passage-preview-boundary" pointer-events="none"
|
||
x1=${t.x1} y1=${t.y1}
|
||
x2=${t.x2} y2=${t.y2}></line>`)}
|
||
`:Ks(e)}
|
||
</g>
|
||
<circle class="opening-preview-dot opghost-dot" aria-hidden="true" pointer-events="none"
|
||
cx=${t.x} cy=${t.y}
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
r=${Et(.18*this.host._gridPitch,this.host._cellCm)}></circle>`}_renderOpeningDialog(){const t=this.host._openingDialog,e=this.host._spaceModel()?.partitions||[],i=t.id?this.host._curSpaceCfg?.openings?.find(e=>e.id===t.id):null,s={id:t.id||"preview",type:t.type,x:t.x/Qd,y:t.y/this.host._spaceH,angle:t.angle,length:i&&!t.lengthTouched?i.length:this.host._cmToUnits(Math.max(20,t.lengthCm))/Qd,...t.host?{host:t.host}:{}},o=Yi(i,s),a=t.host?o?J(s,e,Qd,this.host._cellCm,this.host._gridPitch):H(s,e,Qd,this.host._cellCm,this.host._gridPitch):null,n="does-not-fit-jamb"===a?.reason,r=t.host?e.find(e=>e.id===t.host.id):null,l=r?pe(r.cm/2,this.host._imperial):"",h=!!t.host&&!a?.resolved&&!n,c="gate"===t.type?"mdi:gate":"window"===t.type?"mdi:window-closed-variant":"passage"===t.type?"mdi:arch":"mdi:door",u=(e,i)=>{const s="contact"===e?t.contact:t.lock,o="contact"===e?!!t.contactOpen:!!t.lockOpen,a="contact"===e?t.contactFilter||"":t.lockFilter||"",n=i.find(t=>t.value===s),r=n?.label||this.host.hass.states[s]?.attributes?.friendly_name||this.host._fullRegistryHass.entities[s]?.name||s,l=_o(i,a);return p`
|
||
========
|
||
r=${At(.18*this.host._gridPitch,this.host._cellCm)}></circle>`}_renderOpeningDialog(){const t=this.host._openingDialog,e=this.host._spaceModel()?.partitions||[],s=t.id?this.host._curSpaceCfg?.openings?.find(e=>e.id===t.id):null,i={id:t.id||"preview",type:t.type,x:t.x/Vd,y:t.y/this.host._spaceH,angle:t.angle,length:s&&!t.lengthTouched?s.length:this.host._cmToUnits(Math.max(20,t.lengthCm))/Vd,...t.host?{host:t.host}:{}},o=Vs(s,i),a=t.host?o?J(i,e,Vd,this.host._cellCm,this.host._gridPitch):H(i,e,Vd,this.host._cellCm,this.host._gridPitch):null,n="does-not-fit-jamb"===a?.reason,r=t.host?e.find(e=>e.id===t.host.id):null,l=r?pe(r.cm/2,this.host._imperial):"",h=!!t.host&&!a?.resolved&&!n,c="gate"===t.type?"mdi:gate":"window"===t.type?"mdi:window-closed-variant":"passage"===t.type?"mdi:arch":"mdi:door",u=(e,s)=>{const i="contact"===e?t.contact:t.lock,o="contact"===e?!!t.contactOpen:!!t.lockOpen,a="contact"===e?t.contactFilter||"":t.lockFilter||"",n=s.find(t=>t.value===i),r=n?.label||this.host.hass.states[i]?.attributes?.friendly_name||this.host._fullRegistryHass.entities[i]?.name||i,l=_o(s,a);return p`
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<button type="button" class="dropbtn opening-entity-drop ${o?"open":""}"
|
||
data-opening-picker=${e} aria-expanded=${o?"true":"false"}
|
||
@click=${()=>this._toggleOpeningEntityPicker(e)}>
|
||
${s?p`<b>${r}</b><span class="ref">${s}</span>`:p`<span class="muted">${this.host._t("opening.none")}</span>`}
|
||
<ha-icon icon=${o?"mdi:chevron-up":"mdi:chevron-down"}></ha-icon>
|
||
</button>
|
||
${o?p`<div class="droppanel opening-entity-panel" data-opening-panel=${e}>
|
||
<input class="namein opening-entity-search" type="text"
|
||
placeholder=${this.host._t("opening.search_ph")} .value=${a}
|
||
@input=${t=>this._filterOpeningEntities(e,t.target.value)} />
|
||
<div class="candlist">
|
||
<button type="button" class="cand opening-entity-candidate ${s?"":"sel"}"
|
||
data-opening-entity="" @click=${()=>this._selectOpeningEntity(e,"")}>
|
||
<span class="cl">${this.host._t("opening.none")}</span>
|
||
</button>
|
||
${l.map(t=>p`
|
||
<button type="button"
|
||
class="cand opening-entity-candidate ${t.value===s?"sel":""}"
|
||
data-opening-entity=${t.value}
|
||
@click=${()=>this._selectOpeningEntity(e,t.value)}>
|
||
<span class="cl">${t.label}</span>
|
||
<span class="cs">${t.value}</span>
|
||
</button>`)}
|
||
${l.length?d:p`<div class="cand muted opening-entity-empty">${this.host._t("marker.nothing_found")}</div>`}
|
||
</div>
|
||
</div>`:d}`};return p`<hp-dialog .hass=${this.host.hass} data-kind="opening" wide
|
||
.title=${t.id?this.host._t("opening.edit"):this.host._t("opening.new")} icon=${c}
|
||
@hp-close=${()=>this.host._openingDialog=null}>
|
||
<div class="body">
|
||
${t.host?p`<label>${this.host._t("opening.host_partition")}</label>
|
||
<div class=${h||n?"habindingbanner":"rhint"}
|
||
role=${h||n?"status":d}>
|
||
${h||n?p`<ha-icon icon="mdi:alert-outline"></ha-icon>`:d}
|
||
<span>${h?this.host._t("opening.partition_orphan"):n?this.host._t("opening.partition_jamb_margin",{distance:l}):this.host._t("opening.host_partition")}</span>
|
||
</div>`:d}
|
||
<label>${this.host._t("opening.type_label")}</label>
|
||
<label class="srcrow"><input type="radio" name="optype" .checked=${"window"===t.type}
|
||
@change=${()=>this.host._openingDialog={...t,type:"window",lengthCm:t.id?t.lengthCm:Vs("window"),contactOpen:!1,lockOpen:!1}} />
|
||
<span>${this.host._t("opening.window")}</span></label>
|
||
<label class="srcrow"><input type="radio" name="optype" .checked=${"door"===t.type}
|
||
@change=${()=>this.host._openingDialog={...t,type:"door",lengthCm:t.id?t.lengthCm:Vs("door"),contactOpen:!1,lockOpen:!1}} />
|
||
<span>${this.host._t("opening.door")}</span></label>
|
||
<label class="srcrow"><input type="radio" name="optype" .checked=${"passage"===t.type}
|
||
@change=${()=>this.host._openingDialog={...t,type:"passage",lengthCm:t.id?t.lengthCm:Vs("passage"),contactOpen:!1,lockOpen:!1}} />
|
||
<span>${this.host._t("opening.passage")}</span></label>
|
||
<label class="srcrow"><input type="radio" name="optype" .checked=${"gate"===t.type}
|
||
@change=${()=>this.host._openingDialog={...t,type:"gate",lengthCm:t.id?t.lengthCm:Vs("gate"),flipH:!1,contactOpen:!1,lockOpen:!1}} />
|
||
<span>${this.host._t("opening.gate")}</span></label>
|
||
|
||
<label>${this.host._t("opening.length_label")}</label>
|
||
<input class="namein tempin" type="number" min="20" max="600" step="5" .value=${String(t.lengthCm)}
|
||
@input=${e=>{const i=Mt(e.target.value);null!=i&&(this.host._openingDialog={...t,lengthCm:i,lengthTouched:!0})}} />
|
||
|
||
${"passage"===t.type&&(t.contact||t.lock)?p`<div class="habindingbanner" role="status" aria-live="polite">
|
||
<ha-icon icon="mdi:alert-outline"></ha-icon>
|
||
<span>${this.host._t("opening.passage_binding_warning")}</span>
|
||
</div>`:d}
|
||
|
||
${"passage"!==t.type?p`<label>${this.host._t("opening.contact_label")}</label>
|
||
${u("contact",this._contactCandidates())}
|
||
${t.contact?p`<label class="srcrow">${this._boolInput(t.invert,e=>this.host._openingDialog={...t,invert:e})}
|
||
<span>${this.host._t("opening.invert")}</span></label>`:d}`:d}
|
||
|
||
${"door"===t.type||"gate"===t.type?p`<label>${this.host._t("opening.lock_label")}</label>
|
||
${u("lock",this._lockCandidates())}`:d}
|
||
|
||
${"gate"!==t.type&&"passage"!==t.type?p`<label class="srcrow">${this._boolInput(t.flipH,e=>this.host._openingDialog={...t,flipH:e})}
|
||
<span>${this.host._t("opening.flip_h")}</span></label>`:d}
|
||
${"passage"!==t.type?p`<label class="srcrow">${this._boolInput(t.flipV,e=>this.host._openingDialog={...t,flipV:e})}
|
||
<span>${this.host._t("opening.flip_v")}</span></label>`:d}
|
||
</div>
|
||
<div class="row dialog-action-footer" slot="footer">
|
||
${t.id?p`<div class="dialog-action-group dialog-action-danger">
|
||
<button class="btn danger" @click=${()=>this._deleteOpening()}>
|
||
<ha-icon icon="mdi:delete-outline"></ha-icon>${this.host._t("btn.delete")}
|
||
</button>
|
||
</div>`:d}
|
||
${h?p`<button class="btn ghost" @click=${()=>this._rebindPartitionOpening()}>
|
||
${this.host._t("opening.rebind_partition")}
|
||
</button>`:d}
|
||
<div class="dialog-action-group dialog-action-commit">
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._openingDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>this._saveOpening()}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${this.host._t("btn.save")}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</hp-dialog>`}_gridLevels(){const t=this.host._stageEl,e=this.host._viewOr(this.host._baseVb()),i=t&&t.clientWidth&&e.w?t.clientWidth/e.w:1;return Js(this.host._gridPitch,i)}_renderMarkupDefs(t){const e=this._gridLevels();if(!e)return Tt`<defs></defs>`;const i=this.host._gridPitch*e.fine,s=this.host._gridPitch*e.coarse,o=this.host._gridPitch*e.fine*.14;return Tt`<defs>
|
||
<pattern id="hp-grid" x="0" y="0" width="${i}" height="${i}" patternUnits="userSpaceOnUse">
|
||
<circle cx="0" cy="0" r="${o}" class="griddot"></circle>
|
||
<circle cx="${i}" cy="0" r="${o}" class="griddot"></circle>
|
||
<circle cx="0" cy="${i}" r="${o}" class="griddot"></circle>
|
||
<circle cx="${i}" cy="${i}" r="${o}" class="griddot"></circle>
|
||
</pattern>
|
||
<pattern id="hp-grid-major" x="0" y="0" width="${s}" height="${s}" patternUnits="userSpaceOnUse">
|
||
<rect width="${s}" height="${s}" fill="url(#hp-grid)"></rect>
|
||
<circle cx="0" cy="0" r="${2.1*o}" class="griddot major"></circle>
|
||
<circle cx="${s}" cy="0" r="${2.1*o}" class="griddot major"></circle>
|
||
<circle cx="0" cy="${s}" r="${2.1*o}" class="griddot major"></circle>
|
||
<circle cx="${s}" cy="${s}" r="${2.1*o}" class="griddot major"></circle>
|
||
</pattern>
|
||
</defs>`}_renderPhysicalEditorLayer(){const t=this.host._spaceModel();if(!t)return Tt``;const e=this.host._gridPitch,i=this.host._viewOr(this.host._baseVb()),s=this.host._stageEl,o=s?.clientWidth?i.w/s.clientWidth:e/8,a=Math.max(.22*e,8*o),n=Math.max(a,12*o),r=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`,l=(t,e)=>this.host._physicalSel?.kind===t&&this.host._physicalSel.id===e||"column"===t&&this.host._duplicateColumnId===e,h=(t.partitions||[]).map(t=>{const e=ri(t.a,t.b,t.cm,this.host._cellCm,this.host._gridPitch);return e?Tt`<path class="physical-hit ${l("partition",t.id)?"selected":""}"
|
||
data-hp="partition" data-kind="partition" data-id=${t.id} d=${r(e)}
|
||
stroke-width=${24} vector-effect="non-scaling-stroke"
|
||
@pointerdown=${e=>this._physicalDown(e,"partition",t.id)}
|
||
@pointermove=${t=>this._physicalMove(t)}
|
||
@pointerup=${t=>this._physicalUp(t)}></path>`:Tt`<line class="physical-hit ${l("partition",t.id)?"selected":""}"
|
||
data-hp="partition" data-kind="partition" data-id=${t.id}
|
||
x1=${t.a[0]} y1=${t.a[1]} x2=${t.b[0]} y2=${t.b[1]}
|
||
stroke-width=${24} vector-effect="non-scaling-stroke"
|
||
@pointerdown=${e=>this._physicalDown(e,"partition",t.id)}
|
||
@pointermove=${t=>this._physicalMove(t)}
|
||
@pointerup=${t=>this._physicalUp(t)}></line>`}),c=(t.wall_columns||[]).map(t=>{const e=this.host._physicalRotate?.id===t.id?{...t,angle:this.host._physicalRotate.angle}:t,i=ni(e,this.host._cellCm,this.host._gridPitch);return Tt`<path class="physical-hit ${l("column",t.id)?"selected":""}"
|
||
data-hp="wall-column" data-kind=${t.shape} data-id=${t.id} d=${r(i)}
|
||
stroke-width=${24} vector-effect="non-scaling-stroke"
|
||
@pointerdown=${e=>this._physicalDown(e,"column",t.id)}
|
||
@pointermove=${t=>this._physicalMove(t)}
|
||
@pointerup=${t=>this._physicalUp(t)}></path>`}),p=this.host._physicalDrag,u=(()=>{if(!p?.moved)return d;if("partition"===p.kind&&0===Number(p.base.cm)){const t=p.base;return Tt`<line class="physical-drag zero"
|
||
x1=${t.a[0]} y1=${t.a[1]}
|
||
x2=${t.b[0]} y2=${t.b[1]}
|
||
transform="translate(${p.delta[0]} ${p.delta[1]})"></line>`}const t="partition"===p.kind?ri(p.base.a,p.base.b,p.base.cm,this.host._cellCm,this.host._gridPitch):ni(p.base,this.host._cellCm,this.host._gridPitch);return t?Tt`<path class="physical-drag" d=${r(t)}
|
||
transform="translate(${p.delta[0]} ${p.delta[1]})"></path>`:d})(),_=(()=>{const i=this.host._physicalSel;if(!i)return d;if("partition"===i.kind){const e=t.partitions.find(t=>t.id===i.id);if(!e)return d;const s=ri(e.a,e.b,e.cm,this.host._cellCm,this.host._gridPitch),o=(e.a[0]+e.b[0])/2,n=(e.a[1]+e.b[1])/2;return Tt`<g class="physical-chrome" data-kind="partition-selection">
|
||
${s?Tt`<path class="frame" d=${r(s)}></path>`:Tt`<line class="frame" x1=${e.a[0]} y1=${e.a[1]}
|
||
x2=${e.b[0]} y2=${e.b[1]}></line>`}
|
||
<circle class="move-dot" cx=${e.a[0]} cy=${e.a[1]} r=${.55*a}></circle>
|
||
<circle class="move-dot" cx=${e.b[0]} cy=${e.b[1]} r=${.55*a}></circle>
|
||
<circle class="move-dot" cx=${o} cy=${n} r=${a}></circle>
|
||
</g>`}const s=t.wall_columns.find(t=>t.id===i.id);if(!s)return d;const l=this.host._physicalRotate?.id===s.id?{...s,angle:this.host._physicalRotate.angle}:s,h=ni(l,this.host._cellCm,this.host._gridPitch);if("square"!==l.shape)return Tt`<g class="physical-chrome" data-kind="circle-selection">
|
||
<path class="frame" d=${r(h)}></path>
|
||
<circle class="move-dot" cx=${l.center[0]} cy=${l.center[1]} r=${a}></circle>
|
||
</g>`;const c=X(l.cm,this.host._cellCm,this.host._gridPitch),p=Ye(l.angle)*Math.PI/180,u=Math.sin(p),_=-Math.cos(p),m=[l.center[0]+u*c/2,l.center[1]+_*c/2],g=[m[0]+u*Math.max(e,24*o),m[1]+_*Math.max(e,24*o)];return Tt`<g class="physical-chrome" data-kind="square-selection">
|
||
<path class="frame" d=${r(h)}></path>
|
||
<circle class="move-dot" cx=${l.center[0]} cy=${l.center[1]} r=${a}></circle>
|
||
<line class="stem" x1=${m[0]} y1=${m[1]} x2=${g[0]} y2=${g[1]}></line>
|
||
<circle class="rotate-handle" cx=${g[0]} cy=${g[1]} r=${n}
|
||
data-kind="rotate" @pointerdown=${t=>this._physicalRotateDown(t,s)}
|
||
@pointermove=${t=>this._physicalRotateMove(t)}
|
||
@pointerup=${t=>this._physicalRotateUp(t)}></circle>
|
||
</g>`})();return Tt`<g class="physical-editor">${h}${c}${u}${_}</g>`}_renderHiddenWallDiagnosticOverlay(){if(!this.host._markup)return Tt``;const t=this._hiddenWallDiagnosticSnapshot().value;if(!t.segments.length)return Tt``;const e=X(5,this.host._cellCm,this.host._gridPitch);return Tt`<g class="hidden-wall-diagnostic" data-hp="hidden-wall-diagnostic"
|
||
data-segment-count=${t.segments.length}
|
||
data-endpoint-count=${t.endpoints.length}
|
||
aria-hidden="true" pointer-events="none">
|
||
${t.segments.map(t=>Tt`<line class="hidden-wall-line"
|
||
data-key=${t.key} data-source-kind=${t.sourceKind}
|
||
data-source-id=${t.sourceId}
|
||
x1=${t.a[0]} y1=${t.a[1]} x2=${t.b[0]} y2=${t.b[1]}
|
||
vector-effect="non-scaling-stroke" pointer-events="none"></line>`)}
|
||
${t.endpoints.map(t=>Tt`<circle class="hidden-wall-node"
|
||
data-key=${t.key} data-source-kind=${t.sourceKind}
|
||
data-source-id=${t.sourceId}
|
||
cx=${t.point[0]} cy=${t.point[1]} r=${e}
|
||
pointer-events="none"></circle>`)}
|
||
</g>`}_renderPlanSnapOverlay(){if(!this.host._markup)return Tt``;const t=this._planSnapGeometrySnapshot().value,e=this.host._activePlanSnapCandidate,i=new Set(this.host._activePlanSnapConflicts.map(t=>t.key)),s=X(5,this.host._cellCm,this.host._gridPitch),o=X(10,this.host._cellCm,this.host._gridPitch);return Tt`<g class="plan-snap-overlay" data-hp="plan-snap-overlay"
|
||
data-segment-count=${t.segments.length}
|
||
data-endpoint-count=${t.endpoints.length}
|
||
aria-hidden="true" pointer-events="none">
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${ca([t,s,[...i].sort().join("|")],()=>Tt`
|
||
========
|
||
${la([t,i,[...s].sort().join("|")],()=>Tt`
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
${t.segments.map(t=>Tt`<line class="plan-snap-line"
|
||
data-key=${t.key} data-source-kind=${t.sourceKind}
|
||
x1=${t.a[0]} y1=${t.a[1]} x2=${t.b[0]} y2=${t.b[1]}
|
||
vector-effect="non-scaling-stroke" pointer-events="none"></line>`)}
|
||
${t.endpoints.map(t=>Tt`<circle class="plan-snap-node ${i.has(t.key)?"conflict":""}"
|
||
data-kind="endpoint" data-key=${t.key} data-active="false"
|
||
cx=${t.point[0]} cy=${t.point[1]} r=${s}
|
||
pointer-events="none"></circle>`)}
|
||
`)}
|
||
<circle class="plan-snap-node ${e?"active":""} ${"line"===e?.kind?"dynamic":""}"
|
||
data-hp="plan-snap-active-marker"
|
||
data-kind=${e?.kind??d} data-key=${e?.key??d}
|
||
data-active=${e?"true":"false"}
|
||
cx=${e?.point[0]??0} cy=${e?.point[1]??0} r=${o}
|
||
visibility=${e?"visible":"hidden"} pointer-events="none"></circle>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</g>`}_syncPlanSnapActiveMarker(t){const e=this.host.renderRoot?.querySelector('[data-hp="plan-snap-active-marker"]');if(e){if(e.setAttribute("class",`plan-snap-node${t?" active":""}${"line"===t?.kind?" dynamic":""}`),e.setAttribute("data-active",t?"true":"false"),e.setAttribute("visibility",t?"visible":"hidden"),!t)return e.removeAttribute("data-kind"),void e.removeAttribute("data-key");e.setAttribute("data-kind",t.kind),e.setAttribute("data-key",t.key),e.setAttribute("cx",String(t.point[0])),e.setAttribute("cy",String(t.point[1])),e.setAttribute("r",String(X(10,this.host._cellCm,this.host._gridPitch)))}}_syncPlanSnapConflictMarkers(t){const e=new Set(t.map(t=>t.key));for(const t of this.host.renderRoot?.querySelectorAll('.plan-snap-node[data-kind="endpoint"]')||[])t.setAttribute("class","plan-snap-node"+(e.has(t.dataset.key||"")?" conflict":""))}_planSnapPhysicalSegment(t){let e=0;const i=this.host._spaceModel();return i?(e="partition"===t.sourceKind?Number(i.partitions.find(e=>e.id===t.sourceId)?.cm)||0:Ys(i.rooms,this.host._spaceWalls,this.host._openCuts(),[t.a[0],t.a[1],t.b[0],t.b[1]],this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Qd),e>0?{a:[...t.a],b:[...t.b],halfDepth:X(e,this.host._cellCm,this.host._gridPitch)/2}:null):null}_drawPreviewJoinPatchD(t,e){if(t.length<2)return"";const i=[];for(let s=0;s+1<t.length;s++)e[s]>0&&i.push({a:t[s],b:t[s+1],halfDepth:e[s]});if(!i.length)return"";const s=2e-4*this.host._gridPitch,o=this._planSnapGeometrySnapshot().value.segments.filter(e=>t.some(t=>ge(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=s)).map(t=>this._planSnapPhysicalSegment(t)).filter(t=>!!t);return Zs([...i,...o],s).map(t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`).join(" ")}_renderMarkupLayer(t){const e=this.host._openCuts(),i=this.host._thickWallCuts(),s=e.concat(i),o=s.length?me(this.host._segments,s,.02*this.host._gridPitch):this.host._segments,a=this.host._path,n=this.host._gridPitch,r=this.host._viewOr(this.host._baseVb()),l="draw"===this.host._tool?this.host._drawWallCm:null,h=(()=>"draw"===this.host._tool&&a.length&&null!=l?this.host._contourClosed?a:this.host._cursorPt?[...a,this.host._cursorPt]:a.length>=2?a:null:null)(),c=h?Tc(h.length-1,this.host._contourClosed?[...this.host._wallChainSegmentCms,this.host._closingWallCm??void 0]:this.host._wallChainSegmentCms,l,j).map(t=>X(t,this.host._cellCm,this.host._gridPitch)/2):[],p=h?Xs(h,X(l,this.host._cellCm,this.host._gridPitch)/2,this.host._contourClosed,c):"",u=h?this._drawPreviewJoinPatchD(h,c):"",_=this.host._wallFaceBatch?.candidates[this.host._wallFaceBatch.index]?.repair||this.host._wallRepairDiagnostic;return Tt`
|
||
========
|
||
</g>`}_syncPlanSnapActiveMarker(t){const e=this.host.renderRoot?.querySelector('[data-hp="plan-snap-active-marker"]');if(e){if(e.setAttribute("class",`plan-snap-node${t?" active":""}${"line"===t?.kind?" dynamic":""}`),e.setAttribute("data-active",t?"true":"false"),e.setAttribute("visibility",t?"visible":"hidden"),!t)return e.removeAttribute("data-kind"),void e.removeAttribute("data-key");e.setAttribute("data-kind",t.kind),e.setAttribute("data-key",t.key),e.setAttribute("cx",String(t.point[0])),e.setAttribute("cy",String(t.point[1])),e.setAttribute("r",String(X(10,this.host._cellCm,this.host._gridPitch)))}}_syncPlanSnapConflictMarkers(t){const e=new Set(t.map(t=>t.key));for(const t of this.host.renderRoot?.querySelectorAll('.plan-snap-node[data-kind="endpoint"]')||[])t.setAttribute("class","plan-snap-node"+(e.has(t.dataset.key||"")?" conflict":""))}_planSnapPhysicalSegment(t){let e=0;const s=this.host._spaceModel();return s?(e="partition"===t.sourceKind?Number(s.partitions.find(e=>e.id===t.sourceId)?.cm)||0:Zi(s.rooms,this.host._spaceWalls,this.host._openCuts(),[t.a[0],t.a[1],t.b[0],t.b[1]],this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Vd),e>0?{a:[...t.a],b:[...t.b],halfDepth:X(e,this.host._cellCm,this.host._gridPitch)/2}:null):null}_drawPreviewJoinPatchD(t,e){if(t.length<2)return"";const s=[];for(let i=0;i+1<t.length;i++)e[i]>0&&s.push({a:t[i],b:t[i+1],halfDepth:e[i]});if(!s.length)return"";const i=2e-4*this.host._gridPitch,o=this._planSnapGeometrySnapshot().value.segments.filter(e=>t.some(t=>me(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=i)).map(t=>this._planSnapPhysicalSegment(t)).filter(t=>!!t);return Yi([...s,...o],i).map(t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`).join(" ")}_renderMarkupLayer(t){const e=this.host._openCuts(),s=this.host._thickWallCuts(),i=e.concat(s),o=i.length?_e(this.host._segments,i,.02*this.host._gridPitch):this.host._segments,a=this.host._path,n=this.host._gridPitch,r=this.host._viewOr(this.host._baseVb()),l="draw"===this.host._tool?this.host._drawWallCm:null,h=(()=>"draw"===this.host._tool&&a.length&&null!=l?this.host._contourClosed?a:this.host._cursorPt?[...a,this.host._cursorPt]:a.length>=2?a:null:null)(),c=h?Pc(h.length-1,this.host._contourClosed?[...this.host._wallChainSegmentCms,this.host._closingWallCm??void 0]:this.host._wallChainSegmentCms,l,G).map(t=>X(t,this.host._cellCm,this.host._gridPitch)/2):[],p=h?Xi(h,X(l,this.host._cellCm,this.host._gridPitch)/2,this.host._contourClosed,c):"",u=h?this._drawPreviewJoinPatchD(h,c):"",_=this.host._wallFaceBatch?.candidates[this.host._wallFaceBatch.index]?.repair||this.host._wallRepairDiagnostic;return Tt`
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
${this._gridLevels()?Tt`<rect x="${r.x}" y="${r.y}" width="${r.w}" height="${r.h}" fill="url(#hp-grid-major)" pointer-events="none"></rect>`:d}
|
||
${o.map(t=>Tt`<line class="seg" x1="${t[0]}" y1="${t[1]}" x2="${t[2]}" y2="${t[3]}"></line>`)}
|
||
${this._renderPhysicalEditorLayer()}
|
||
${"column"===this.host._tool&&this.host._cursorPt&&this.host._drawWallCm?Tt`<path class="physical-drag" d=${(()=>{const t={shape:"square",center:this.host._cursorPt,cm:this.host._drawWallCm};return`M ${ni(t,this.host._cellCm,this.host._gridPitch).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`})()}></path>`:d}
|
||
${p?Tt`<path class="drawwall-preview-fill" d="${p}"></path>
|
||
<path class="drawwall-preview" d="${p}"></path>`:d}
|
||
${h&&0===l?Tt`<polyline class="drawwall-zero-preview ${gs(this.host._curSpaceCfg)}"
|
||
points=${h.map(t=>t.join(",")).join(" ")}></polyline>`:d}
|
||
${u?Tt`<path class="drawwall-preview-fill" d="${u}"></path>
|
||
<path class="drawwall-preview" style="stroke:none" d="${u}"></path>`:d}
|
||
${_?Tt`<line class="wall-repair-preview"
|
||
x1=${_.from[0]} y1=${_.from[1]}
|
||
x2=${_.to[0]} y2=${_.to[1]}
|
||
aria-hidden="true" pointer-events="none"></line>`:d}
|
||
${"split"===this.host._tool&&this.host._splitSel?.pts?.length?Tt`${this.host._splitSel.pts.length>1?Tt`<polyline class="pathline" points="${this.host._splitSel.pts.map(t=>t.join(",")).join(" ")}"></polyline>`:d}
|
||
${this.host._splitSel.pts.map((t,e)=>Tt`<circle class="vertex ${0===e?"first":""}"
|
||
cx="${t[0]}" cy="${t[1]}" r="${Et(.22*n,this.host._cellCm)}"></circle>`)}
|
||
${this.host._cursorPt?Tt`<line class="preview" x1="${this.host._splitSel.pts[this.host._splitSel.pts.length-1][0]}" y1="${this.host._splitSel.pts[this.host._splitSel.pts.length-1][1]}"
|
||
x2="${this.host._cursorPt[0]}" y2="${this.host._cursorPt[1]}"></line>`:d}`:d}
|
||
`}_renderActiveChainInk(){const t=this.host._path,e=this.host._gridPitch;return Tt`
|
||
${t.length>1?Tt`<polyline class="pathline" points="${t.map(t=>t.join(",")).join(" ")}"></polyline>`:d}
|
||
${t.length&&this.host._cursorPt&&"draw"===this.host._tool&&!this.host._contourClosed?Tt`<line class="active-axis" x1="${t[t.length-1][0]}" y1="${t[t.length-1][1]}"
|
||
x2="${this.host._cursorPt[0]}" y2="${this.host._cursorPt[1]}" aria-hidden="true"></line>
|
||
${this.host._activePlanSnapCandidate||this.host._activePlanSnapConflicts.length?d:Tt`<circle class="active-vertex" cx="${this.host._cursorPt[0]}" cy="${this.host._cursorPt[1]}"
|
||
r="${Et(.22*e,this.host._cellCm)}" aria-hidden="true"></circle>`}`:d}
|
||
${t.map((t,i)=>Tt`<circle class="vertex ${0===i?"first":""}"
|
||
cx="${t[0]}" cy="${t[1]}" r="${Et(.22*e,this.host._cellCm)}"></circle>`)}
|
||
`}_renderPartitionDeleteDialog(){const t=this.host._partitionDeleteDialog,e="mi"===this.host.hass?.config?.unit_system?.length;return p`<hp-dialog .hass=${this.host.hass} data-kind="confirm"
|
||
.title=${this.host._t("confirm.delete_partition_openings_title")}
|
||
icon="mdi:wall" dismiss-on-scrim
|
||
@hp-close=${()=>this.host._partitionDeleteDialog=null}>
|
||
<div class="body">
|
||
<p>${this.host._t("confirm.delete_partition_openings_body",{count:t.openings.length})}</p>
|
||
<ul aria-label=${this.host._t("confirm.delete_partition_openings_title")}>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
${t.openings.map(t=>p`<li>${this.host._t("confirm.delete_partition_openings_item",{type:this.host._t(`opening.${t.type}`),length:pe(t.length*Qd/this.host._gridPitch*this.host._cellCm,e)})}</li>`)}
|
||
========
|
||
${t.openings.map(t=>p`<li>${this.host._t("confirm.delete_partition_openings_item",{type:this.host._t(`opening.${t.type}`),length:pe(t.length*Vd/this.host._gridPitch*this.host._cellCm,e)})}</li>`)}
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
</ul>
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._partitionDeleteDialog=null}>
|
||
${this.host._t("btn.cancel")}
|
||
</button>
|
||
<span class="spacer"></span>
|
||
<button class="btn danger" data-hp="dialog-confirm" @click=${()=>this._confirmPartitionDelete()}>
|
||
<ha-icon icon="mdi:delete-outline"></ha-icon>${this.host._t("btn.delete")}
|
||
</button>
|
||
</div>
|
||
</hp-dialog>`}_renderRoomDeleteDialog(){const t=this.host._roomDeleteDialog;return p`<hp-dialog .hass=${this.host.hass} data-kind="confirm"
|
||
.title=${this.host._t("confirm.delete_room_title",{name:t.name})}
|
||
icon="mdi:floor-plan" dismiss-on-scrim
|
||
@hp-close=${()=>this.host._roomDeleteDialog=null}>
|
||
<div class="body">
|
||
<p>${this.host._t("confirm.delete_room_body")}</p>
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._roomDeleteDialog=null}>
|
||
${this.host._t("btn.cancel")}
|
||
</button>
|
||
<span class="spacer"></span>
|
||
<button class="btn" data-hp="dialog-confirm" @click=${()=>this._confirmRoomDelete(!0)}>
|
||
<ha-icon icon="mdi:wall"></ha-icon>${this.host._t("btn.delete_room_keep_walls")}
|
||
</button>
|
||
<button class="btn danger" data-hp="dialog-confirm" @click=${()=>this._confirmRoomDelete(!1)}>
|
||
<ha-icon icon="mdi:delete-outline"></ha-icon>${this.host._t("btn.delete_room_with_walls")}
|
||
</button>
|
||
</div>
|
||
</hp-dialog>`}_renderPhysicalDialog(){const t=this.host._physicalDialog,e="column"===t.kind;return p`<hp-dialog .hass=${this.host.hass} data-kind="physical" wide
|
||
.title=${this.host._t(e?"physical.column_properties":"physical.partition_properties")}
|
||
icon=${e?"mdi:vector-square":"mdi:wall"}
|
||
@hp-close=${()=>this.host._physicalDialog=null}>
|
||
<div class="body">
|
||
${e?p`<label>${this.host._t("physical.shape")}</label>
|
||
<select class="areasel" @change=${e=>{const i=e.target.value;this.host._physicalDialog={...t,shape:i}}}>
|
||
<option value="square" ?selected=${"square"===t.shape}>${this.host._t("physical.square")}</option>
|
||
<option value="circle" ?selected=${"circle"===t.shape}>${this.host._t("physical.circle")}</option>
|
||
</select>`:d}
|
||
<label>${this.host._t(e?"circle"===t.shape?"physical.diameter":"physical.side":"wallthick.field")}</label>
|
||
<div class="row"><input class="namein tempin" type="number"
|
||
min=${Ue(e?1:0,this.host._imperial)}
|
||
max=${Ue(e?150:100,this.host._imperial)} step="any" .value=${t.cm}
|
||
@input=${e=>this.host._physicalDialog={...t,cm:e.target.value}} />
|
||
<span class="opl">${this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}</span></div>
|
||
${e&&"square"===t.shape?p`
|
||
<label>${this.host._t("physical.rotation")}</label>
|
||
<input class="namein tempin" type="number" min="0" max="89.999" step="5"
|
||
.value=${t.angle||"0"}
|
||
@input=${e=>this.host._physicalDialog={...t,angle:e.target.value}} />`:d}
|
||
${t.length?p`<div class="muted">${this.host._t("physical.length")}: ${t.length}</div>`:d}
|
||
</div>
|
||
<div class="row dialog-action-footer physicalfooter" slot="footer">
|
||
<div class="dialog-action-group dialog-action-danger">
|
||
<button class="btn danger" @click=${()=>this._deletePhysicalSelection()}>
|
||
<ha-icon icon="mdi:delete-outline"></ha-icon>${this.host._t("btn.delete")}
|
||
</button>
|
||
</div>
|
||
<div class="dialog-action-group dialog-action-commit">
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._physicalDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>this._savePhysicalDialog()}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${this.host._t("btn.save")}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</hp-dialog>`}_renderMarkupBar(){const t=this.host._geometryHistory.undoName,e=this.host._geometryHistory.redoName,i=t?this.host._t("history.undo_named",{name:t}):this.host._t("history.undo_empty"),s=e?this.host._t("history.redo_named",{name:e}):this.host._t("history.redo_empty");return p`<div class="editbar planbar" data-hp="toolbar" data-kind="plan">
|
||
<div class="editbar-tools" tabindex="-1" ?inert=${this.host._modeTransitionBusy}>
|
||
<ha-icon icon="mdi:vector-square-edit" class="warn"></ha-icon>
|
||
<span class="wallsgroup">
|
||
<button class="btn ${"select"===this.host._tool?"on":""}" data-hp="tool" data-tool="select"
|
||
@click=${()=>this._activateMarkupTool("select")}
|
||
title=${this.host._t("title.markup_select")}>
|
||
<ha-icon icon="mdi:cursor-default-outline"></ha-icon>${this.host._t("markup.select")}
|
||
</button>
|
||
<button class="btn ${"draw"===this.host._tool?"on":""}" data-hp="tool" data-tool="draw"
|
||
aria-pressed=${"draw"===this.host._tool?"true":"false"}
|
||
@click=${()=>this._activateMarkupTool("draw")}
|
||
title=${this.host._t("title.markup_add")}>
|
||
<ha-icon icon="mdi:vector-polyline-plus"></ha-icon>${this.host._t("markup.add")}
|
||
</button>
|
||
<button class="btn ${"column"===this.host._tool?"on":""}" data-hp="tool" data-tool="column"
|
||
@click=${()=>this._activateMarkupTool("column")}
|
||
title=${this.host._t("title.markup_column")}>
|
||
<ha-icon icon="mdi:vector-square"></ha-icon>${this.host._t("markup.column")}
|
||
</button>
|
||
</span>
|
||
<button class="btn ${"merge"===this.host._tool?"on":""}" data-hp="tool" data-tool="merge"
|
||
@click=${()=>this._activateMarkupTool("merge")}
|
||
title=${this.host._t("title.markup_merge")}>
|
||
<ha-icon icon="mdi:vector-union"></ha-icon>${this.host._t("markup.merge")}
|
||
</button>
|
||
<button class="btn ${"split"===this.host._tool?"on":""}" data-hp="tool" data-tool="split"
|
||
@click=${()=>this._activateMarkupTool("split")}
|
||
title=${this.host._t("title.markup_split")}>
|
||
<ha-icon icon="mdi:vector-polyline-remove"></ha-icon>${this.host._t("markup.split")}
|
||
</button>
|
||
<button class="btn ${"resize"===this.host._tool?"on":""}" data-hp="tool" data-tool="resize"
|
||
@click=${()=>this._activateMarkupTool("resize")}
|
||
title=${this.host._t("title.markup_resize")}>
|
||
<ha-icon icon="mdi:arrow-expand-all"></ha-icon>${this.host._t("markup.resize")}
|
||
</button>
|
||
${this.host._editorToolbarGroups.map(t=>this._renderEditorGroupLauncher(t))}
|
||
<button class="btn ${"wallthick"===this.host._tool?"on":""}" data-hp="tool" data-tool="wall-thickness"
|
||
@click=${()=>this._activateMarkupTool("wallthick")}
|
||
title=${this.host._t("title.markup_wallthick")}>
|
||
<ha-icon icon="mdi:wall"></ha-icon>${this.host._t("markup.wallthick")}
|
||
</button>
|
||
<button class="btn ${"delroom"===this.host._tool?"on":""}" data-hp="tool" data-tool="delete-room"
|
||
@click=${()=>this._activateMarkupTool("delroom")}
|
||
title=${this.host._t("title.markup_delroom")}>
|
||
<ha-icon icon="mdi:delete-outline"></ha-icon>${this.host._t("markup.delete_room")}
|
||
</button>
|
||
<button class="btn ghost" @click=${()=>this._undoGeometry()}
|
||
?disabled=${!t}
|
||
title=${i} aria-label=${i}>
|
||
<ha-icon icon="mdi:undo-variant" aria-hidden="true"></ha-icon>
|
||
</button>
|
||
<button class="btn ghost" @click=${()=>this._redoGeometry()}
|
||
?disabled=${!e}
|
||
title=${s} aria-label=${s}>
|
||
<ha-icon icon="mdi:redo-variant" aria-hidden="true"></ha-icon>
|
||
</button>
|
||
</div>
|
||
<div class="editbar-end">
|
||
<button class="btn barclose" title=${this.host._t("title.close_editor")} data-hp="editor-close"
|
||
data-editor-navigation="view"
|
||
@click=${()=>this._setMode("view")}>
|
||
<ha-icon icon="mdi:close"></ha-icon>
|
||
</button>
|
||
</div>
|
||
</div>`}_renderDevicesBar(){const t=this.host._devicePositionHistory.undoName,e=this.host._devicePositionHistory.redoName,i=t?this.host._t("history.undo_named",{name:t}):this.host._t("history.undo_empty"),s=e?this.host._t("history.redo_named",{name:e}):this.host._t("history.redo_empty");return p`<div class="editbar devbar" data-hp="toolbar" data-kind="device">
|
||
<div class="editbar-tools" tabindex="-1" ?inert=${this.host._modeTransitionBusy}>
|
||
<ha-icon icon="mdi:tune-variant" class="warn"></ha-icon>
|
||
<button class="btn" data-hp="tool" data-tool="add-device" @click=${()=>this._openMarkerDialog()}
|
||
title=${this.host._t("title.add_device")}>
|
||
<ha-icon icon="mdi:plus-box-outline"></ha-icon>${this.host._t("devbar.add")}
|
||
</button>
|
||
<button class="btn ${this.host._showAll?"on":""}" data-hp="tool" data-tool="device-inbox" @click=${()=>this._openDeviceInbox()}
|
||
title=${this.host._t("device_inbox.title")}>
|
||
<ha-icon icon="mdi:devices"></ha-icon>${this.host._t("device_inbox.button")}
|
||
</button>
|
||
<button class="btn" data-hp="tool" data-tool="icon-rules" @click=${()=>this._openRulesDialog()} title=${this.host._t("title.icon_rules")}>
|
||
<ha-icon icon="mdi:shape-plus-outline"></ha-icon>${this.host._t("devbar.rules")}
|
||
</button>
|
||
${this.host._editorToolbarGroups.map(t=>this._renderEditorGroupLauncher(t))}
|
||
</div>
|
||
<div class="editbar-end">
|
||
<button class="btn ghost" data-device-position-history="undo"
|
||
@click=${()=>this.host._undoDevicePosition()}
|
||
?disabled=${this.host._devicePositionBusy||!t}
|
||
title=${i} aria-label=${i}>
|
||
<ha-icon icon="mdi:undo-variant" aria-hidden="true"></ha-icon>
|
||
</button>
|
||
<button class="btn ghost" data-device-position-history="redo"
|
||
@click=${()=>this.host._redoDevicePosition()}
|
||
?disabled=${this.host._devicePositionBusy||!e}
|
||
title=${s} aria-label=${s}>
|
||
<ha-icon icon="mdi:redo-variant" aria-hidden="true"></ha-icon>
|
||
</button>
|
||
<button class="btn barclose" title=${this.host._t("title.close_editor")} data-hp="editor-close"
|
||
data-editor-navigation="view"
|
||
@click=${()=>this._setMode("view")}>
|
||
<ha-icon icon="mdi:close"></ha-icon>
|
||
</button>
|
||
</div>
|
||
</div>`}_discoveryFilterState(t){const e=this.host._settings,i=void 0!==t.draftGroupLights?t.draftGroupLights:!1!==e.group_lights,s=e.exclude_integrations,o=void 0!==t.draftExcluded?null===t.draftExcluded?[...Qs]:t.draftExcluded:s?[...s]:[...Qs],a=void 0!==t.draftExcluded?null===t.draftExcluded:!s,n=void 0!==t.draftGroupLights||void 0!==t.draftExcluded;return{groupLights:i,excluded:o.sort(),usesProductList:a,dirty:n}}_registryIntegrations(){const t=new Set,e=this.host._fullRegistryHass;for(const i of Object.values(e?.entities||{}))i?.platform&&t.add(String(i.platform));for(const i of Object.values(e?.devices||{})){const e=i?.identifiers?.[0],s=Array.isArray(e)?e[0]:null;s&&t.add(String(s))}return[...t].sort()}_discoveryFilterPreview(t){const e=this._discoveryFilterState(t),i=[e.groupLights?1:0,e.usesProductList?"p":e.excluded.join(","),this.host._cfgEpoch,this.host._regSignature].join("|");if(this._discoveryPreviewMemo?.key===i)return this._discoveryPreviewMemo.value;const s={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(mo({...s,settings:t,excluded:e})),a=(t,e)=>new Set(go({...s,settings:t,excluded:e}).map(t=>t.bindingRef||t.id)),n=to(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:i,value:f},f}async _saveDiscoveryFilters(t){const e=this.host._serverCfg;if(!e)return;const i=this._discoveryFilterState(t),s={...e.settings};i.groupLights?delete s.group_lights:s.group_lights=!1,i.usesProductList?delete s.exclude_integrations:s.exclude_integrations=i.excluded,this.host._serverCfg={...e,settings:s},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),i=e=>this.host._deviceInbox={...t,...e},s=t.filtersOpen&&e.dirty?this._discoveryFilterPreview(t):null,o=this._registryIntegrations().filter(t=>!e.excluded.includes(t));return p`<details class="device-inbox-discovery" ?open=${t.filtersOpen}
|
||
@toggle=${t=>i({filtersOpen:t.target.open})}>
|
||
<summary>${this.host._t("device_inbox.filters_title")}</summary>
|
||
<label class="srcrow">
|
||
<input type="checkbox" .checked=${e.groupLights}
|
||
@change=${t=>i({draftGroupLights:t.target.checked})} />
|
||
${this.host._t("device_inbox.filters_group_lights")}
|
||
</label>
|
||
<div class="device-inbox-excluded">
|
||
<span>${this.host._t("device_inbox.filters_excluded")}</span>
|
||
<div class="device-inbox-chips">
|
||
${e.excluded.map(t=>p`<span class="chip">${t}
|
||
<button type="button" aria-label="×"
|
||
@click=${()=>i({draftExcluded:e.excluded.filter(e=>e!==t)})}>×</button>
|
||
</span>`)}
|
||
</div>
|
||
<input type="text" list="hp-discovery-integrations"
|
||
placeholder=${this.host._t("device_inbox.filters_search_ph")}
|
||
@change=${t=>{const s=t.target,o=s.value.trim();o&&!e.excluded.includes(o)&&i({draftExcluded:[...e.excluded,o]}),s.value=""}} />
|
||
<datalist id="hp-discovery-integrations">
|
||
${o.map(t=>p`<option value=${t}></option>`)}
|
||
</datalist>
|
||
<button type="button" class="btn ghost" ?disabled=${e.usesProductList}
|
||
@click=${()=>i({draftExcluded:null})}>
|
||
${this.host._t("device_inbox.filters_reset")}
|
||
</button>
|
||
</div>
|
||
${s?p`<div class="device-inbox-preview">
|
||
${this.host._t("device_inbox.filters_preview_appear",{count:String(s.appear)})}
|
||
· ${this.host._t("device_inbox.filters_preview_hide",{count:String(s.hide)})}
|
||
· ${this.host._t("device_inbox.filters_preview_lights",{count:String(s.lights)})}
|
||
</div>`:d}
|
||
<button type="button" class="btn on" ?disabled=${!e.dirty}
|
||
@click=${()=>this._saveDiscoveryFilters(t)}>
|
||
${this.host._t("device_inbox.filters_save")}
|
||
</button>
|
||
</details>`}_renderDeviceInbox(){const t=this.host._deviceInbox,e=this._deviceInboxRows(),i=Object.fromEntries(["on_plan","available","hidden","readd"].map(t=>[t,e.filter(e=>e.category===t).length])),s=function(t,e,i,s=!1){const o=i.trim().toLocaleLowerCase();return t.filter(t=>t.category===e&&(!s||t.isNew)&&(!o||t.searchText.includes(o)))}(e,t.tab,t.search,"on_plan"===t.tab&&t.onlyNew),o=s.slice(0,t.limit),a=t=>this.host._t(`device_inbox.tab_${t}`),n=`device_inbox.empty_${t.tab}`;return p`<hp-dialog class="device-inbox-dialog" .hass=${this.host.hass}
|
||
data-kind="device-inbox"
|
||
.title=${this.host._t("device_inbox.title")} icon="mdi:devices" wide
|
||
@hp-close=${()=>this.host._deviceInbox=null}>
|
||
<div class="device-inbox" ?inert=${!!t.busy}>
|
||
<div class="device-inbox-head">
|
||
<input class="device-inbox-search" type="search" autofocus
|
||
placeholder=${this.host._t("device_inbox.search")} .value=${t.search}
|
||
@input=${e=>this.host._deviceInbox={...t,search:e.target.value,limit:100}} />
|
||
<button type="button" class="btn" @click=${()=>{this.host._deviceInboxReturn={...t},this.host._deviceInbox=null,this._openMarkerDialog(),this.host._markerDialog||this._closeMarkerDialog()}}>
|
||
<ha-icon icon="mdi:map-marker-plus-outline"></ha-icon>
|
||
${this.host._t("device_inbox.add_virtual")}
|
||
</button>
|
||
</div>
|
||
<div class="device-inbox-tabs" role="tablist" @keydown=${t=>this._deviceInboxTabKey(t)}>
|
||
${["on_plan","available","hidden","readd"].map(e=>p`
|
||
<button type="button" role="tab" aria-selected=${t.tab===e?"true":"false"}
|
||
class=${t.tab===e?"on":""}
|
||
@click=${()=>this.host._deviceInbox={...t,tab:e,limit:100,onlyNew:!1}}>
|
||
${a(e)} <span>${i[e]}</span>
|
||
</button>`)}
|
||
</div>
|
||
<div class="device-inbox-filters">
|
||
${"on_plan"===t.tab?p`<label>
|
||
<input type="checkbox" .checked=${t.onlyNew}
|
||
@change=${e=>this.host._deviceInbox={...t,onlyNew:e.target.checked,limit:100}} />${this.host._t("device_inbox.only_new")}
|
||
</label>`:d}
|
||
${"available"===t.tab?p`<label>
|
||
<input type="checkbox" .checked=${t.showEntities}
|
||
@change=${e=>{this.host._deviceInboxMemo=null,this.host._deviceInbox={...t,showEntities:e.target.checked,limit:100}}} />${this.host._t("device_inbox.show_entities")}
|
||
</label>`:d}
|
||
<span class="device-inbox-filter-help">
|
||
<label>
|
||
<input type="checkbox" .checked=${this.host._showAll}
|
||
@change=${t=>{this.host._showHidden=t.target.checked,this.host._deviceInboxMemo=null,this.host.requestUpdate()}} />${this.host._t("device_inbox.show_hidden")}
|
||
</label>
|
||
${this._help("device_inbox.show_hidden.help")}
|
||
</span>
|
||
</div>
|
||
${"available"===t.tab?this._renderDiscoveryFilters(t):d}
|
||
<div class="device-inbox-results" aria-live="polite">
|
||
${o.length?o.map(t=>{const e="on_plan"===t.category?t.canFind?p`<button type="button" class="btn" @click=${()=>this._findInboxDevice(t)}>
|
||
<ha-icon icon="mdi:crosshairs-gps"></ha-icon>${this.host._t("device_inbox.find")}</button>`:p`<button type="button" class="btn" @click=${()=>this._openInboxMarker(t)}
|
||
?disabled=${!t.canEdit}>${this.host._t("device_inbox.edit")}</button>`:"hidden"===t.category?p`<button type="button" class="btn" @click=${()=>this._setInboxHidden(t,!1)}
|
||
title=${t.canShow?"":this.host._t("device_inbox.show_disabled")}
|
||
?disabled=${!t.canShow}>${this.host._t("device_inbox.show")}</button>`:p`<button type="button" class="btn" @click=${()=>this._openInboxMarker(t,!0)}
|
||
?disabled=${!t.canAdd}>${this.host._t("readd"===t.category?"device_inbox.readd":"device_inbox.add")}</button>`,i="active"===t.status.kind?"":this.host._t(`device_inbox.status_${t.status.kind}`);return p`<article class="device-inbox-row" data-binding=${t.binding}
|
||
data-category=${t.category} data-status=${t.status.kind}>
|
||
<ha-icon class="device-inbox-icon" .icon=${t.icon}></ha-icon>
|
||
<div class="device-inbox-copy">
|
||
<div class="device-inbox-name"><b>${t.name}</b>
|
||
${t.isNew?p`<span class="device-inbox-new">${this.host._t("device_inbox.new")}</span>`:d}
|
||
</div>
|
||
<div class="device-inbox-meta">
|
||
${[t.model,t.integration,t.spaceName,t.areaName].filter(Boolean).join(" · ")}
|
||
</div>
|
||
<div class="device-inbox-reason">
|
||
${"excluded_integration"===t.reason&&t.integration?this.host._t("device_inbox.reason_excluded_integration",{integration:t.integration}):this.host._t(`device_inbox.reason_${t.reason}`)}
|
||
${i?p`<span class="device-inbox-status">${i}</span>`:d}
|
||
</div>
|
||
<code>${t.binding}</code>
|
||
</div>
|
||
<div class="device-inbox-actions">
|
||
${e}
|
||
${t.canEdit||t.canHide||"available"===t.category||"hidden"===t.category||this.host._bindingHasHaPage(t.binding)?p`
|
||
<details class="device-inbox-menu">
|
||
<summary class="btn ghost" aria-label=${this.host._t("device_inbox.more_actions")}
|
||
title=${this.host._t("device_inbox.more_actions")}>
|
||
<ha-icon icon="mdi:dots-vertical"></ha-icon>
|
||
</summary>
|
||
<div class="device-inbox-menu-items">
|
||
${t.canEdit&&("on_plan"!==t.category||t.canFind)?p`<button type="button" class="btn ghost" @click=${()=>this._openInboxMarker(t)}>
|
||
${this.host._t("device_inbox.edit")}</button>`:d}
|
||
${t.canHide?p`<button type="button" class="btn ghost"
|
||
@click=${()=>this._setInboxHidden(t,!0)}>${this.host._t("device_inbox.hide")}</button>`:d}
|
||
${"available"===t.category?p`<button type="button" class="btn ghost"
|
||
@click=${()=>this._setInboxHidden(t,!0)}>${this.host._t("device_inbox.hide_available")}</button>`:d}
|
||
${"hidden"===t.category?p`<button type="button" class="btn ghost"
|
||
title=${t.canFind?"":this.host._t("device_inbox.find_hidden_hint")}
|
||
?disabled=${!t.canFind} @click=${()=>this._findInboxDevice(t)}>
|
||
<ha-icon icon="mdi:crosshairs-gps"></ha-icon>${this.host._t("device_inbox.find")}</button>`:d}
|
||
${this.host._bindingHasHaPage(t.binding)?p`<button type="button" class="btn ghost"
|
||
@click=${()=>this.host._openBindingInHa(t.binding)}>${this.host._t("btn.open_in_ha")}</button>`:d}
|
||
</div>
|
||
</details>`:d}
|
||
</div>
|
||
</article>`}):p`<div class="device-inbox-empty">${this.host._t(n)}</div>`}
|
||
</div>
|
||
${s.length>o.length?p`<button type="button" class="btn device-inbox-more"
|
||
@click=${()=>this.host._deviceInbox={...t,limit:t.limit+100}}>
|
||
${this.host._t("device_inbox.show_more")} (${s.length-o.length})
|
||
</button>`:d}
|
||
</div>
|
||
<div slot="footer" class="row">
|
||
<button type="button" class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._deviceInbox=null}>
|
||
${this.host._t("btn.close")}</button>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}_markerValueBadgeFields(t){return eo({touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition})}_markerValueSourceFields(t){return io({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=P(t.room),i=ss(t.binding,t.devId,()=>"__hp_device_preview__"),s=this.host._markers.find(e=>e.id===i||e.id===t.devId),o=N(t.binding,t.controls,this.host._bindingEntities(t.binding)),a=this._effectiveStoredTapAction(t),n={id:i,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===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=Mt(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:s?.vacuum||null},r=!!s&&("string"==typeof s.area&&s.area.length>0||null===s.area&&!!s.space&&!!s.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=s.space,n.area=s.area,n.room_id=s.room_id),n}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this.host._haRegistry.revision}\n${xt(this.host._markers)}\n${JSON.stringify(e)}`;if(this.host._markerPreviewMemo?.key===i)return this.host._markerPreviewMemo.device;const s=so({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:i,device:s},s}_markerPreviewDevices(t){const e=this.host._markerPreviewDevicesMemo;if(e?.base===this.host._devices&&e.preview===t)return e.devices;const i=[...this.host._devices.filter(e=>e.id!==t.id),t];return this.host._markerPreviewDevicesMemo={base:this.host._devices,preview:t,devices:i},i}_toggleIntent(t,e=this.host._devices){return this.host._toggleIntent(t,e)}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_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("-","_")}`),i=t=>this.host._t(`marker.toggle_skip_${t.replace("-","_")}`);return oo(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:""),i=t.name||e;return this.host._t("marker.toggle_hint_single",{name:i,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,i)=>"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(i)}):this.host._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this.host._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),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}: ${i(t.reason)})`}).join(", ")}),none:t=>this.host._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:as(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const o=[...this.host._devices.filter(t=>t.id!==s.id),s],a=y(this.host._planHass,s,o),n=w(this.host._planHass,s,a);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!n,valueBadgeSource:n,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return ao(no(this.host._planHass,[...this.host._devices.filter(t=>t.id!==i.id),i],null,this.host._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&ro(this.host._planHass,{...i})}_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),i=this.host._markers.find(t=>t.id===e),s=this.host._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.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===(s?.space||i.space)),a=!!s&&M(s).length>0;return{label:i.name||s?.name||e,sub:[o?.title||s?.space||i.space,i.room_id||s?.area,a?"":this.host._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this.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 i=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:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=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 M(o))s.add(t);i.push({value:`marker:${t.id}`,label:a.label,sub:a.sub,icon:a.icon,search:`${a.label} ${a.sub} ${t.id} ${M(o).join(" ")}`.toLowerCase()})}const o=Object.keys(this.host.hass.states||{}).filter(e=>lo(e)&&!s.has(e)&&ho(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[...i,...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 i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this.host._showToast(this.host._t("toast.marker_binding_required"));const s=e.slice(7),o=this._markerDraft(t),a=o?[...this.host._markers.filter(t=>t.id!==i),o]:this.host._markers;if(co(a,i,s))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 i=this._markerSpatialSource(e),s=po(i?this.host._planHass.states[i.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?s.c:e.glowColor,glowBrightness:a?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderRadarSection(t,e,i="main"){return cc({dialog:t,device:e,registryHass:this.host._fullRegistryHass,planHass:this.host._planHass,hass:this.host.hass,spaceModelById:t=>this.host._spaceModelById(t),currentSpace:()=>this.host._spaceModel(),position:t=>this.host._pos(t),updateDialog:t=>{this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,...t})},dialogDeviceId:()=>this.host._markerDialog?.devId,t:(t,e)=>this.host._t(t,e),help:t=>this._help(t),boolInput:(t,e)=>this._boolInput(t,e),toast:t=>this.host._showToast(t),setup:this._radarSetup,configRev:this.host._cfgRev},i)}_renderMarkerDialog(){return Ha.call(this)}_renderSpaceDialog(){return Sr.call(this)}_renderMergeDialog(){const t=this.host._mergeDialog,e=this.host._spaceModel()?.rooms||[],i=(i,s)=>{const o=e.find(t=>t.id===i),a=o?.area?this.host.hass.areas[o.area]?.name:null;return p`<label class="srcrow">
|
||
<input type="radio" name="mergekeep" .checked=${t.pick===s}
|
||
@change=${()=>this.host._mergeDialog={...t,pick:s}} />
|
||
========
|
||
</hp-dialog>`}_markerValueBadgeFields(t){return eo({touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition})}_markerValueSourceFields(t){return so({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=P(t.room),s=ei(t.binding,t.devId,()=>"__hp_device_preview__"),i=this.host._markers.find(e=>e.id===s||e.id===t.devId),o=N(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=Mt(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${xt(this.host._markers)}\n${JSON.stringify(e)}`;if(this.host._markerPreviewMemo?.key===s)return this.host._markerPreviewMemo.device;const i=io({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 oo(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:ii(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=y(this.host._planHass,i,o),n=w(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 ao(no(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&&ro(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&&M(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 M(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} ${M(o).join(" ")}`.toLowerCase()})}const o=Object.keys(this.host.hass.states||{}).filter(e=>lo(e)&&!i.has(e)&&ho(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(co(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=po(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}}_renderRadarSection(t,e,s="main"){return rc({dialog:t,device:e,registryHass:this.host._fullRegistryHass,planHass:this.host._planHass,hass:this.host.hass,spaceModelById:t=>this.host._spaceModelById(t),currentSpace:()=>this.host._spaceModel(),position:t=>this.host._pos(t),updateDialog:t=>{this.host._markerDialog&&(this.host._markerDialog={...this.host._markerDialog,...t})},dialogDeviceId:()=>this.host._markerDialog?.devId,t:(t,e)=>this.host._t(t,e),help:t=>this._help(t),boolInput:(t,e)=>this._boolInput(t,e),toast:t=>this.host._showToast(t),setup:this._radarSetup,configRev:this.host._cfgRev},s)}_renderMarkerDialog(){return Ea.call(this)}_renderSpaceDialog(){return xr.call(this)}_renderMergeDialog(){const t=this.host._mergeDialog,e=this.host._spaceModel()?.rooms||[],s=(s,i)=>{const o=e.find(t=>t.id===s),a=o?.area?this.host.hass.areas[o.area]?.name:null;return p`<label class="srcrow">
|
||
<input type="radio" name="mergekeep" .checked=${t.pick===i}
|
||
@change=${()=>this.host._mergeDialog={...t,pick:i}} />
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|
||
<span>${o?.name||""} <span class="muted">· ${a||this.host._t("merge.no_area")}</span></span>
|
||
</label>`};return p`<hp-dialog .hass=${this.host.hass} data-kind="room" .title=${this.host._t("merge.header")} icon="mdi:vector-union"
|
||
@hp-close=${()=>this.host._mergeDialog=null}>
|
||
<div class="body">
|
||
<p class="muted">${this.host._t("merge.hint")}</p>
|
||
<label>${this.host._t("merge.keep")}</label>
|
||
${i(t.aId,"a")}
|
||
${i(t.bId,"b")}
|
||
</div>
|
||
<div class="row" slot="footer">
|
||
<span class="spacer"></span>
|
||
<button class="btn ghost" data-hp="dialog-cancel" @click=${()=>this.host._mergeDialog=null}>${this.host._t("btn.cancel")}</button>
|
||
<button class="btn on" data-hp="dialog-confirm" @click=${()=>this._commitMerge()}>
|
||
<ha-icon icon="mdi:check"></ha-icon>${this.host._t("btn.save")}
|
||
</button>
|
||
</div>
|
||
<<<<<<<< HEAD:dist/houseplan-assets/houseplan-editor-runtime-JBeajuPp.js
|
||
</hp-dialog>`}_renderRoomDialog(){return zr.call(this)}}export{vd as EDITOR_LANGUAGE_RUNTIME,ip as EDITOR_RUNTIME_FINGERPRINT,sp as HouseplanEditorRuntime};
|
||
========
|
||
</hp-dialog>`}_renderRoomDialog(){return Tr.call(this)}}export{Yd as EDITOR_RUNTIME_FINGERPRINT,Xd as HouseplanEditorRuntime};
|
||
>>>>>>>> f2c9321a (fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)):dist/houseplan-assets/houseplan-editor-runtime-CI5VOnPK.js
|